Java中的内部类,你真的理解吗

简介: 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();

字节码分析:

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

1671185990108.jpg

我们看到内部类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节点就是一个静态内部类。

1671186010633.jpg

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

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


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


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

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

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

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


内部类的作用


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

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

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

目录
相关文章
|
2月前
|
Java
【Java基础面试二】、个Java文件里可以有多个类吗(不含内部类)?
这篇文章讨论了Java文件中类的定义规则,指出一个Java文件可以包含多个类(不包含内部类),但其中最多只能有一个public类,且如果有public类,它的名称必须与文件名一致。
|
2月前
|
算法 Java
12 Java常用类(一)(内部类+object类+包装类)
12 Java常用类(一)(内部类+object类+包装类)
30 5
|
3月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
34 6
|
2月前
|
Java
【Java】内部类、枚举、泛型
【Java】内部类、枚举、泛型
|
4月前
|
Java
一篇文章讲明白Java中内部类详解—匿名内部类
一篇文章讲明白Java中内部类详解—匿名内部类
63 2
|
4月前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
4月前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
25 2
|
5月前
|
Java 程序员
Java的内部类与匿名类的技术性文章
Java的内部类与匿名类的技术性文章
37 1
|
4月前
|
Java
Java内部类相关内容总结和解读
Java内部类相关内容总结和解读
29 0
|
4月前
|
存储 Java
Java 五种内部类演示及底层原理详解
Java 五种内部类演示及底层原理详解
28 0