内部类

  • 1. 定义内部类
  • 2. 静态内部类
  • 3. 匿名内部类



内部类是在一个类的内部定义的类,在开发的项目中使用内部类的场景不是特别的常见。但也是Java中提供的一种方式。因些在这里也专门写一篇文章供大家参考。

1. 定义内部类

内部类不能被单独的实例化,必须先实例化外部类后,再用外部类实例的new去实例化内部类。

public class OuterClass {
    private int outerVar;

    public void outerFunc(){
        System.out.println("我是外部类的方法");
    }

    class InnerClass {
        public void innerFunc(){
            outerVar++;
        }

    }

    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();

        //内部类不能被单独的实例化,必须先实例化外部类,然后再用外部类实例的new,去实例化内部类
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        
        System.out.println("outerVar = " + outerClass.outerVar);
        innerClass.innerFunc();
        System.out.println("outerVar = " + outerClass.outerVar);
        
    }
}

运行结果:

outerVar = 0
outerVar = 1

注1:代码中我们可以看到内部类可以访问外部类的私有变量。
注2:另外内部类中除了有一个this用来访问本身外,还有一个OuterClass.this用来访问外部类。

将内部类改为如下代码:

class InnerClass {
        public void innerFunc(){
            OuterClass.this.outerFunc();
            outerVar++;
        }

    }

运行结果:

outerVar = 0
我是外部类的方法
outerVar = 1

2. 静态内部类

内部的类可以用static修饰,而变成静态类
注:顶级的外部类是不能用static来修饰的
静态内部类可以直接被实例化,静态内部类中能访问外部类的静态变量和静态方法,但不能访问外部类的非静态变量和方法。也不能使用OuterClass1.this来访问外部类。

public class OuterClass1 {
    private int outerVar;

    public void outerFunc(){
        System.out.println("我是外部类的方法");
    }

    static class StaticInnerClass {
        public void innerFunc(){
            System.out.println("我是静态内部类的方法");
        }

    }

    public static void main(String[] args) {
        OuterClass1.StaticInnerClass staticInnerClass = new OuterClass1.StaticInnerClass();
        staticInnerClass.innerFunc();
    }
}

运行结果:

我是静态内部类的方法

3. 匿名内部类

匿名内部类顾名思义就是没有名字的内部类。
我们看一下用法实例:

public class AnonymousClass {
    public static void main(String[] args) {
        Person person = new Person();
        person.working();

        Person person1 = new Person(){
            public void  working(){
                System.out.println("我是匿名内部类,做好事不留名");
            }
        };
        person1.working();

    }
}

运行结果:

我要撸起袖子加油干
我是匿名内部类,做好事不留名

这里可能有点费解,小编第一次接解是也是这样,不过没关系我们一起来看一下。

Person person1 = new Person(){
  	public void  working(){
       System.out.println("我是匿名内部类,做好事不留名");
   	}
};

上面这段代码在new Person()后面的{}这间就是定义了一个内部类。这个内部类继承了Person类并重写了Person类的working方法。
因此person1.working()方法输出了:我是匿名内部类,做好事不留名 通常情况下匿名内部类就是重写继承类原有的方法,这样就可以用父类的引用调用到匿名类重写的方法。
但是匿名类能否有自已的方法呢?

我们又添加了这样一段代码

Person person2 = new Person(){
public void  working(){
     System.out.println("我是匿名内部类,做好事不留名");
 }

 public void  hello(){
     System.out.println("我是匿名内部类,我用我自已的方法给你打招呼");
 }
};

但是编译器提示找不到hello符串。

nformation:java: Errors occurred while compiling module 'javaStudy'
Information:javac 1.8.0_241 was used to compile java sources
Information:2021/3/26 17:53 - Build completed with 1 error and 0 warnings in 1 s 907 ms
/Users/lxl/work/code_project/javaStudy/src/InnerClass/AnonymousClass.java
Error:(34, 16) java: 找不到符号
  符号:   方法 hello()
  位置: 类型为InnerClass.Person的变量 person2

因为把匿名类赋值给Person后因为Person类没有hello方法,所以用Person的引用是无法访问hello方法的。
我们先不把new出来的匿名类赋值到Person变量,通过下面的代码:

public class AnonymousClass {
    public static void main(String[] args) {
        Person person = new Person();
        person.working();

        Person person1 = new Person(){
            public void  working(){
                System.out.println("我是匿名内部类,做好事不留名");
            }
        };
        person1.working();

        new Person(){
            public void  working(){
                System.out.println("我是匿名内部类,做好事不留名");
            }

            public void  hello(){
                System.out.println("我是匿名内部类,我用我自已的方法给你打招呼");
            }
        }.hello();
    }
}

运行结果:

我要撸起袖子加油干
我是匿名内部类,做好事不留名
我是匿名内部类,我用我自已的方法给你打招呼

现在就可以访问到自定义的方法了。但是我们就没办法用到重写的方法了。我们再改进一下把hello返回 Person引用。

public class AnonymousClass {
    public static void main(String[] args) {
        Person person = new Person();
        person.working();

        Person person1 = new Person(){
            public void  working(){
                System.out.println("我是匿名内部类,做好事不留名");
            }
        };
        person1.working();

        Person person2 = new Person(){
            public void  working(){
                System.out.println("我是匿名内部类,做好事不留名");
            }

            public Person hello(){
                System.out.println("我是匿名内部类,我用我自已的方法给你打招呼");
                return this;
            }
        }.hello();
        
        person2.working();
    }
}

运行结果:

我要撸起袖子加油干
我是匿名内部类,做好事不留名
我是匿名内部类,我用我自已的方法给你打招呼
我是匿名内部类,做好事不留名

如果匿名类中加两个自定义的方法还有办法访问到吗?答案是没有办法了。