作者:~小明学编程
文章专栏:JavaSE基础
格言:目之所及皆为回忆,心之所想皆为过往
目录
什么是Java的内部类呢?
简单来说就是在我们原有的类中再次的嵌套一个类。
- class OutClass {
- public int data1 =1;
- private int data2 = 2;
- public static int data3 = 3;
- static class InnerClass {
- public int data4 = 4;
- private int data5 = 5;
- public static int data6 = 6;
-
- }
- }
形如上述代码,我们的OutClass是一个外部类,我们的InnerClass是一个内部,并且我们在InnerClass的前面加了一个static,此时我们的InnerClass就是一个静态内部类了。
然后我们也可以像外部类那样,同时在我们的内部类中定义一些成员,同时我们也可以定义方法,例如:
- class OutClass {
- public int data1 =1;
- private int data2 = 2;
- public static int data3 = 3;
- static class InnerClass {
- public int data4 = 4;
- private int data5 = 5;
- public static int data6 = 6;
- public void func() {
- System.out.println(data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- System.out.println(data6);
- }
-
- }
- }

但是此时我们发现代码报错了,我们在内部类中不能够直接的打印我们的data1和data2,这是为什么呢?
因为此时我们的InnerClass是一个静态的内部类,我们静态的内部类是不依赖对象的,也就是说在我们的静态内部类中是不能直接访问外部非静态的成员的,那么想要访问该怎么办呢?
答案很简单,就是new一个我们的外部对象然后访问就行了。
- public void func() {
- OutClass outClass = new OutClass();
- System.out.println(outClass.data1);
- System.out.println(outClass.data2);
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- System.out.println(data6);
- }
写成这样我们的代码就不会再报错了。
刚说了我们的静态内部类访问外部类的规则,那么我们的外部类去访问我们的静态内部类又会如何呢?
- class OutClass {
- public int data1 =1;
- private int data2 = 2;
- public static int data3 = 3;
- static class InnerClass {
- public int data4 = 4;
- private int data5 = 5;
- public static int data6 = 6;
- public void func() {
- OutClass outClass = new OutClass();
- System.out.println(outClass.data1);
- System.out.println(outClass.data2);
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- System.out.println(data6);
- }
- }
- public void test() {
- System.out.println(data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- System.out.println(data6);
- }
- }

这里我们可以看到我们的下面三个静态内部类的成员均不能直接访问。如何解决这个问题呢?
对于静态变量的data6因为不依赖对象所以我们在前面直接加一个我们的内部类就行了。对于data4和data5来说的话,我们要借助内部类对象了。
- public void test() {
- InnerClass innerClass = new InnerClass();
- System.out.println(data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(innerClass.data4);
- System.out.println(innerClass.data5);
- System.out.println(InnerClass.data6);
- }
那么疑惑再次来袭,我们的data4是一个public可以理解但是我们的data5是一个private 的怎么能直接访问呢?
这是因为我们的外部类可以访问我们静态内部类中的所有成员。
既然我们处理好了我们的静态内部类,那么我们该怎么去实例化我们的静态内部类呢?
- public static void main(String[] args) {
- OutClass.InnerClass innerClass = new OutClass.InnerClass();
- innerClass.func();
- }
这里我们采用的方式是 外部类.内部类 类名 = new 外部类.内部类()的方式去实例化我们的静态内部类的。
- class OutClass2 {
- public int data1 =1;
- private int data2 = 2;
- public static int data3 = 3;
- class InnerClass {
- public int data4 = 4;
- private int data5 = 5;
- public final static int data6 = 6;
- public void func() {
- System.out.println(data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- System.out.println(data6);
- }
- }
- public void test() {
- InnerClass innerClass = new InnerClass();
- System.out.println(data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(innerClass.data4);
- System.out.println(innerClass.data5);
- System.out.println(InnerClass.data6);
- }
- }
下面我们所说的内部类均代表非静态的内部类。
- public void func() {
- System.out.println(data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(data4);
- System.out.println(data5);
- System.out.println(data6);
- }
这里我们可以看到我们的func()方法无论是内部类还是外部类的成员我们都可以直接的访问,所以这里我们内部类在访问外部类的时候还是比较容易的,直接就能进行访问。
- class OutClass2 {
- public int data1 =1;
- private int data2 = 2;
- public static int data3 = 3;
- class InnerClass {
- public int data1 = 111;
- public int data4 = 4;
- private int data5 = 5;
- public final static int data6 = 6;
- public void func() {
- System.out.println(data1);//111
- System.out.println(OutClass2.this.data1);//1
- }
- }
- }
这里我们可以看到我们的内部类和外部类都有data,当我们打印data1的时候将会打印我们内部类中的data1,要是想打印外部类中的data1就得采用 外部类.this.成员的方式去访问。
- public void test() {
- InnerClass innerClass = new InnerClass();
- System.out.println(data1);
- System.out.println(data2);
- System.out.println(data3);
- System.out.println(innerClass.data4);
- System.out.println(innerClass.data5);
- System.out.println(InnerClass.data6);
- }
外部类访问我们内部类的规则依旧同上,需要我们new一个内部类的对象然后才能进行访问,对于静态常量,直接通过类名就能访问。
实例化我们的非静态内部类相对就比较麻烦一点。
- public static void main(String[] args) {
- //方式一
- OutClass2 outClass2 = new OutClass2();
- OutClass2.InnerClass innerClass = outClass2.new InnerClass();
- innerClass.func();
- //方式二
- OutClass2.InnerClass innerClass1 = new OutClass2().new InnerClass();
- innerClass1.func();
- }
我们可以一次性实例化也可以分两次来进行实例化,都能达到我们实例化的需求。
- class OutClass3 {
- public int a = 1;
- public void func() {
- class InnerClass {
- int c = 2;
- public void func() {
- System.out.println("hello");
- }
- }
- InnerClass innerClass = new InnerClass();
- innerClass.func();
- }
- }
形如上述代码,我们在我们外部类的方法中或者{}体中定义的类叫做局部类。
- public static void main(String[] args) {
- OutClass3 outClass3 = new OutClass3();
- outClass3.func();//hello
- }

我们的局部类同样也有字节码文件。
在了解匿名内部类之前让我们先看一段熟悉的代码
- interface A {
- void func();
- }
- class AA implements A {
- @Override
- public void func() {
- System.out.println("haha");
- }
- }
- public static void main(String[] args) {
- A a = new AA();
- a.func();
- }
我们有一个接口,接口里面有一个抽象方法func(),当我们想用这个方法的时候我们需要有一个类去实现它,然后重写里面的方法,最后new一个对象再去调用方法。
对于接口里面方法比较少的话这种写法比较麻烦。
下面我们用内部类的写法:
- public static void main(String[] args) {
- new A() {
- @Override
- public void func() {
- System.out.println("haha");
- }
- }.func();
- }
我们new一个接口然后重写里面的方法,最后在后面直接调用就行了。