Loading

Java内部类


内部类简介


Java 一个类中可以嵌套另外一个类,语法格式如下:

class OuterClass {   // 外部类
    // ...
    class NestedClass { // 嵌套类,或称为内部类
        // ...
    }
}

嵌套类有如下几种类型:

image


成员内部类


最简单的一种内部类,形式如下,跟其他变量一样,是一个类中的一个成员

class Outer {
    
    String str = "hello";
     
    public Outer(String str) {
        this.str = str;
    }
    
    /* 内部类 */
    class Inner {     
        public void showStr() {
            System.out.println(str);
        }
    }
}

  • 成员内部类可以无条件地访问外部类的所有元素
  • 外部类访问内部类需要先创建一个内部类对象
  • 成员内部类是依附外部类而存在
可以访问外部类原理

编译器会在编译时生成外部类和内部类两个字节码文件,还会给内部类的无参构造函数增加一个参数,为外部类的一个应用,且指向了外部类,故可以随意使用外部类一切。

侧面说明成员内部类依赖于外部类的优先创建,不然会初始化失败


局部内部类


定义在一个方法或者一个作用域里面的类,局部内部类的访问仅限于方法内或者该作用域内

class MyClass{
    public MyClass() {
         
    }
}
 
class Outer{
    public Outer(){
         
    }
     
    public MyClass getInner{
        
        /* 局部内部类 */
        class Inner extends MyClass{   
            int age = 0;
        }
        return new Inner();
    }
}

局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的


匿名内部类


先看一下官方给的例子

public class HelloWorldAnonymousClasses {

    /**
     * 包含两个方法的HelloWorld接口
     */
    interface HelloWorld {
        public void greet();
        public void greetSomeone(String someone);
    }

    public void sayHello() {

        // 1、局部类EnglishGreeting实现了HelloWorld接口
        class EnglishGreeting implements HelloWorld {
            String name = "world";
            public void greet() {
                greetSomeone("world");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hello " + name);
            }
        }

        HelloWorld englishGreeting = new EnglishGreeting();

        // 2、匿名类实现HelloWorld接口
        HelloWorld frenchGreeting = new HelloWorld() {
            String name = "tout le monde";
            public void greet() {
                greetSomeone("tout le monde");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Salut " + name);
            }
        };

        // 3、匿名类实现HelloWorld接口
        HelloWorld spanishGreeting = new HelloWorld() {
            String name = "mundo";
            public void greet() {
                greetSomeone("mundo");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hola, " + name);
            }
        };

        englishGreeting.greet();
        frenchGreeting.greetSomeone("Fred");
        spanishGreeting.greet();
    }

    public static void main(String... args) {
        HelloWorldAnonymousClasses myApp = new HelloWorldAnonymousClasses();
        myApp.sayHello();
    }
}

匿名类表达式包含以下内部分:

  1. 操作符:new;
  2. 一个要实现的接口或要继承的类,案例一中的匿名类实现了HellowWorld接口,案例二中的匿名内部类继承了Animal父类;
  3. 一对括号,如果是匿名子类,与实例化普通类的语法类似,如果有构造参数,要带上构造参数;如果是实现一个接口,只需要一对空括号即可;
  4. 一段被"{}"括起来类声明主体;
  5. 末尾的";"号(因为匿名类的声明是一个表达式,是语句的一部分,因此要以分号结尾)。

本部分参考JAVA匿名内部类(Anonymous Classes)


静态内部类


静态内部类是不需要依赖于外部类的,并且它不能使用外部类的非static成员变量或者方法,这个和普通静态方法不能访问非静态方法或变量的原理一样,具体可以了解一下类的加载生命周期。

简单地说就是静态变量或方法是属于类的,非静态方法或变量是属于对象的,jvm加载类的时候就为类的静态变量或方法分配内存的,而非静态的需要等到要初始化对象时候才给分配内存,而这个过程是动态的,也就是等到我们什么时候想用,才会有累的初始化过程。

简单举个例子:

 
class Outer {
	int a = 1
	static int a = 2;
    public Outter() {
         
    }
     
	/* 静态内部类 */
    static class Inner {
        public Inner() {
             System.out.println(a); // 编译会报错
             System.out.println(b);

        }
    }
}

使用:

public class Test {
    public static void main(String[] args)  {
        Outer.Inner inner = new Outer.Inner();
    }
}

内部类简单应用


为什么在 Java 中需要内部类?总结一下主要有以下四点内部类的使用场景和好处:

  • 1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
  • 2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
  • 3.方便编写事件驱动程序。
  • 4.方便编写线程代码。
posted @ 2021-07-19 22:17  Acelin_H  阅读(318)  评论(0编辑  收藏  举报