一文带你真正理解Java中的内部类

目录
  • 概述
  • 内部类介绍和分类
    • 常规内部类
    • 局部内部类
    • 匿名内部类
    • 静态内部类
  • 静态内部类和普通内部类的区别
  • 内部类的作用

概述

不知道大家在平时的开发过程中或者源码里是否留意过内部类,那有思考过为什么要有内部类,内部类都有哪几种形式,静态内部类和普通内部类有什么区别呢?本篇文章主要带领大家理解下这块内容。

内部类介绍和分类

顾名思义,内部类是指一个类在另外一个类的内部,是定义在另一个类中的类。根据类的位置和属性不同,可以分为下面几种。

常规内部类

@Data
public class Tree {

    private String treeName;

    private String treeType;

    private List<Leaf> leafs;

    @Data
    public class Leaf {
        private String color;

        private String leafSize;

        public void show() {
            System.out.println("tree name: " + Tree.this.treeName);
            System.out.println("tree name: " + treeName);
        }
    }

    public static void main(String[] args) {
        Tree tree = new Tree();
        Leaf leaf = tree.new Leaf();
    }
}

上面就是一个内部类的例子,Leaf是Tree的内部类。

  • 内部类中可以直接访问外部类的数据,包括私有数据。
  • 常规内部类中的方法或者字段不能是静态的。
  • 内部类中可以使用如下的语法Tree.this.treeName
  • 内部类创建对象需要外部对象的存在,如下:
Tree tree = new Tree();
Leaf leaf = tree.new Leaf();

字节码分析:

我们查看下内部类的字节码,如下图:

我们看到内部类Leaf的构造方法init,实际上会隐式地将外部对象传入,初始化,这样才能在内部类中访问。

局部内部类

局部内部类,比如只有在一个方法内部创建。

@Data
public class Tree {

    private String treeName;

    private String treeType;

    private List<Leaf> leafs;

    public void treeRoot(int height) {
        class TreeRoot {
            private int rootHeight;

            public void showRootHeight() {
                this.rootHeight = height;
                System.out.println("root height " + height);
            }
        }
        TreeRoot root = new TreeRoot();
        root.showRootHeight();
    }
}
  • 局部类不能用public或private访问说明符进行声明,因为作用域只在这个局部,没有必要。
  • 局部内部类可以完全将自己隐藏起来,体现良好的封装性。
  • 局部内部类可以直接访问方法的变量。

匿名内部类

匿名内部类,就更加简洁了,连类名都省略了, 这个配合lambda食用,非常简便,想必大家也经常使用了。

public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable");
            }
        };

        Runnable runnable2 = () -> System.out.println("runnable");
    }

匿名内部类也体现了良好的封装性和简洁性。

静态内部类

最后,再介绍下静态内部类,这个也使用的非常频繁。java源码中也有很多这样的例子,比如HashMap中,Node节点就是一个静态内部类。

如果用static来修饰一个内部类,那么就是静态内部类。这个内部类属于外部类本身,但是不属于外部类的任何对象。因此使用static修饰的内部类称为静态内部类。静态内部类有如下规则:

  • 静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。
  • 外部类可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象访问其实例成员。

静态内部类和普通内部类的区别

我们可以通俗按下面的方式理解:

内部类:就是我是你的一部分,我了解你,我知道你的全部,没有你就没有我。(所以内部类对象是以外部类对象存在为前提的)

静态内部类:就是我跟你没关系,自己可以完全独立存在,但是我就借你的壳用一下,来隐藏自己。

从字节码角度上看,静态内部类和非静态内部类最大的区别是:非静态内部类编译后隐式保存着外部类的引用(就算外部类对象没用了也GC不掉),但是静态内部类没有。

内部类的作用

通过上面的了解,我想内部类还是有一定的意义的。

  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
  • 内部类可以对同一个包中的其他类隐藏起来。

其实内部类更多的时候,不想把这个类暴露出去,它可能只是外部类的一个逻辑组成部分,不需要其他地方知道什么,这时候我们用内部类更加的清楚。

到此这篇关于一文带你真正理解Java中的内部类的文章就介绍到这了,更多相关Java 内部类内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java 内部类的定义与范例

    目录 一.前言 二.内部类 语法格式: static修饰内部类 内部类未被static修饰时: 内部类被static修饰后 演示操作: 一.前言 前面我们学习了一个小的项目,现在我们来学习新的知识点,关于内部类的描述,其实 顾名思义就是在类的内部有一个类,简称套娃类(个人观点) 二.内部类 一个类定义在另一个在一个类的内部叫内部类. 内部类可以直接访问外部类的私有和非私有成员,而外部类不能直接访问内部类 (包括所有外部类成员) 外部类成员要访问内部类是,必须创建内部类对象. 外部类通过创建对象也

  • Java十分钟精通内部类的使用

    内部类: 其实内部类顾名思义,就是类中类,一个类里面还有一个类. 内部类分为四种: 普通内部类 静态内部类 方法内部类 匿名内部类 我们一一去了解一下~~ A.普通内部类: 我们先通过代码去了解一下: package InternalClass; /** * 内部类 */ public class Car { public int a = 10; public int b = 20; //外部类的方法 public void method() { System.out.println("我是外部

  • Java超全面梳理内部类的使用

    目录 一.内部类 1.内部类的概念 2.内部类的定义 3.内部类与外部类的访问规则 4.内部类的注意事项 二.匿名内部类 一.内部类 1.内部类的概念 内部类是定义在类中的类. 内部类把逻辑上相关的类放在一起.而有的内部类不会在其他地方用到,它没有类名,在定义的时候就生成一个该类的实例,称为匿名内部类.匿名内部类是一种特殊的内部类. 当然啦!可以把内部类看作外部类的一个成员,它拥有自己的成员变量和成员方法.通过实例化对象可以访问其成员变量或调用成员方法. 2.内部类的定义 把类的定义放在一个用于

  • 深入了解Java内部类的用法

    目录 1.内部类分类和概念 2.局部内部类 3.匿名内部类(重要) 基于接口的匿名内部类 基于类的匿名内部类 一些细节 匿名内部类的最佳实践 4.成员内部类 5.静态内部类 1.内部类分类和概念 java类的五大成员:属性,方法,构造器(构造方法),代码块,内部类 内部类的分类: 定义在外部类局部的位置(比如方法内): 局部内部类(有类名) 匿名内部类(无类名) 定义在外部类成员位置上: 成员内部类(没有static修饰) 静态内部类(有static修饰) 概念:在一个类的内部再定义一个完整的类

  • java的内部类和外部类用法讲解

    目录 一.为何使用内部类 二.内部类与外部类的联系 2.1 内部类是一个相对独立的实体,与外部类不是is-a关系 2.2 内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素 2.3 外部类可以通过内部类引用间接访问内部类元素 三.创建内部类 3.1 在外部类外面(或外部类main方法)创建内部了对象 3.2 在外部类里面创建内部类 四.内部类的种类: 4.1 成员内部类 4.2 方法内部类 4.3 匿名内部类 4.4 静态内部类 一.为何使用内部类 内部类提供了更好的封装,只有

  • java内部类的最详细详解

    目录 1.成员内部类 2.静态内部类 3.方法内部类 4.匿名内部类 总结 1.成员内部类 内部类与外部类的关系 a.成员内部类的创建需要依赖于外部类对象-(成员方法必须通过对象调用),在没有外部类实例之前无法创建成员内部类对象 b.内部类与外部类相对独立,不是is a 的关系(发动机-汽车) c.私有属性的互相访问,内部类可以直接访问外部类,而外部类访问内部类需要内部类的对象来访问 d.创建内部类的语法 1.在外部类内部创建内部类对象(Inner inner = new Inner()) 2.

  • 全面探究 Java 内部类

    目录 一. 实例内部类 1. 定义 2. 如何获取实例内部类这个对象的引用 3. 注意事项 二. 静态内部类 1. 定义 2. 如何获取静态内部类这个对象的引用 3. 注意事项 三. 匿名内部类 1. 定义 2. 常见用法 3. 注意事项 内部类(inner class)是定义在另一个类中的类.为什么要使用内部类呢?主要有两个原因:1.内部类可以对同一个包中的其他类隐藏.2.内部类方法可以访问定义这个类的作用域中的数据,包括原本私有的数据. 下面,我就来带领大家去学习Java中比较常见的几种内部

  • 一文带你真正理解Java中的内部类

    目录 概述 内部类介绍和分类 常规内部类 局部内部类 匿名内部类 静态内部类 静态内部类和普通内部类的区别 内部类的作用 概述 不知道大家在平时的开发过程中或者源码里是否留意过内部类,那有思考过为什么要有内部类,内部类都有哪几种形式,静态内部类和普通内部类有什么区别呢?本篇文章主要带领大家理解下这块内容. 内部类介绍和分类 顾名思义,内部类是指一个类在另外一个类的内部,是定义在另一个类中的类.根据类的位置和属性不同,可以分为下面几种. 常规内部类 @Data public class Tree

  • 一文带你彻底理解Java序列化和反序列化

    Java序列化是什么? Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程. 反序列化: 客户端重文件,或者网络中获取到文件以后,在内存中重构对象. 序列化: 对象序列化的最重要的作用是传递和保存对象的时候,保证对象的完整性和可传递性.方便字节可以在网络上传输以及保存在本地文件. 为什么需要序列化和反序列化 实现分布式 核心在于RMI,可以利用对象序列化运行远程主机上的服务,实现运行的时候,就像在本地上运行Java对象一样. 实现递归保存

  • 一文带你搞懂Java中的泛型和通配符

    目录 概述 泛型介绍和使用 泛型类 泛型方法 类型变量的限定 通配符使用 无边界通配符 通配符上界 通配符下界 概述 泛型机制在项目中一直都在使用,比如在集合中ArrayList<String, String>, Map<String,String>等,不仅如此,很多源码中都用到了泛型机制,所以深入学习了解泛型相关机制对于源码阅读以及自己代码编写有很大的帮助.但是里面很多的机制和特性一直没有明白,特别是通配符这块,对于通配符上界.下界每次用每次百度,经常忘记,这次我就做一个总结,加

  • 一文带你深入了解Java中延时任务的实现

    目录 概述 JAVA DelayQueue DelayQueue的实现原理 DelayQueue实现延时队列的优缺点 时间轮算法 时间轮的具体实现 进阶优化版时间轮算法 时间轮算法的应用 小结 redis延时队列 mq延时队列 rocketmq延时消息 rocketmq的精准延时消息 总结 概述 延时任务相信大家都不陌生,在现实的业务中应用场景可以说是比比皆是.例如订单下单15分钟未支付直接取消,外卖超时自动赔付等等.这些情况下,我们该怎么设计我们的服务的实现呢? 笨一点的方法自然是定时任务去数

  • 一文带你搞懂Java中Get和Post的使用

    目录 1 Get请求数据 1.1 Controller 1.2 Service 1.3 Application 1.4 Postman 2 Post接收数据 2.1 Controller 2.2 Service 2.3 Application 2.4 Postman 3 Post发送数据 3.1 Controller 3.2 Service 3.3 ResponseResult 3.4 Config 3.5 Application 3.6 Postman 1 Get请求数据 项目地址:https

  • 一文带你搞懂Java中的递归

    目录 概述 递归累加求和 计算1 ~ n的和 代码执行图解 递归求阶乘 递归打印多级目录 综合案例 文件搜索 文件过滤器优化 Lambda优化 概述 递归:指在当前方法内调用自己的这种现象. 递归的分类: 递归分为两种,直接递归和间接递归. 直接递归称为方法自身调用自己. 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法. 注意事项: 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出. 在递归中虽然有限定条件,但是递归次数不能太多.否则也会发生栈内存溢出. 构造方

  • 一文带你弄懂Java中线程池的原理

    目录 为什么要用线程池 线程池的原理 ThreadPoolExecutor提供的构造方法 ThreadPoolExecutor的策略 线程池主要的任务处理流程 ThreadPoolExecutor如何做到线程复用的 四种常见的线程池 newCachedThreadPool newFixedThreadPool newSingleThreadExecutor newScheduledThreadPool 小结 在工作中,我们经常使用线程池,但是你真的了解线程池的原理吗?同时,线程池工作原理和底层实

  • 一文带你深入理解Linux中的nohup命令

    目录 前言 nohup是什么 nohup语法规则 nohup使用方法 后台运行命令 标准输出重定向到文件 标准错误输出重定向到文件 将标准输出和标准错误输出都重定向到文件 nohup后台进程管理 总结 前言 当我们在Linux或Unix系统上执行一个长时间运行的命令或脚本时,我们通常会遇到一个问题,那就是在终端关闭或者退出后,该进程也会随之停止运行.在这种情况下,我们需要一种方式来让进程在后台运行,而不受终端关闭的影响.这时,nohup命令就派上用场了. nohup是什么 nohup是Linux

  • 一文带你搞懂Java中Object类和抽象类

    目录 一.抽象类是什么 二.初始抽象类 2.1 基本语法 2.2 继承抽象类 三.抽象类总结 四.Object类 4.1 初始Object 4.2 toString 4.3 equals 4.4 hashcode 一.抽象类是什么 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类. 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用.也是因为这个原因,通常在设计阶段决定要

  • 一文带你搞懂Java中Synchronized和Lock的原理与使用

    目录 1.Synchronized与Lock对比 2.Synchronized与Lock原理 2.1 Synchronized原理 2.2 Lock原理 3.Synchronized与Lock使用 Synchronized Lock 4.相关问题 1.Synchronized与Lock对比 实现方式:Synchronized是Java语言内置的关键字,而Lock是一个Java接口. 锁的获取和释放:Synchronized是隐式获取和释放锁,由Java虚拟机自动完成:而Lock需要显式地调用lo

随机推荐