内部类/外部类/匿名类的一些介绍

类的成员:Java类包含5种成员:成员变量、方法、构造器、初始化块、内部类(包括接口、枚举)5种成员。

static可以修饰除了构造器之外的其它四种

static 修饰的类成员属于整个类,不属于单个实例。

一.内部类(成员类)

1.什么是内部类

指一个类定义在另一个类的内部,并且具有访问外部类成员的能力。内部类可以访问外部类的私有成员

分为四种类型:

1.成员内部类(Member Inner Class): 成员内部类是定义在外部类的成员位置(字段、方法等)的类。它可以访问外部类的成员,包括私有成员。成员内部类的实例必须与外部类的实例相关联。

2.静态内部类(Static Inner Class): 静态内部类是定义在外部类的成员位置,但使用 static 关键字修饰的内部类。静态内部类不依赖于外部类的实例,可以像普通类一样被实例化。

3.局部内部类(Local Inner Class): 局部内部类是定义在方法内部的类,它的作用域被限制在所在的方法内。局部内部类可以访问外部方法中的局部变量,但这些变量必须是 final 或实际上相当于 final 的(在Java 8+ 中,可以访问被捕获的局部变量)。

4.匿名内部类(Anonymous Inner Class): 匿名内部类是一种特殊类型的局部内部类,它没有显式的类名,通常用于创建一个实现某个接口或继承某个类的临时类。

内部类:

public class OuterClass {
    private int outerField = 10;

public class InnerClass {
    public void displayOuterField() {
        System.out.println("Outer Field: " + outerField);
    }
}

}

1.外部类可以访问内部类

访问静态内部类:

外部类名.内部类名.成员

访问实例类:

外部类名.创建该类的实例.成员名
实例化顺序
public class A {
//静态内部类的静态成员是与类本身关联的,不受实例化的影响。因此,b1 实例的静态变量 a 也会受到影响。
    static int a;  

    static {
        System.out.println("A static{}");
    }

    static class B {
        static {
            System.out.println("A$B static{}");
        }

        static int a;
    }

    class C {
        static int a;

        static {
            System.out.println("A$C static{}");
        }
    }

    public static void test() {
        System.out.println(B.a);
        System.out.println(C.a);
    }
}

//外部类
class TestA {

    public static void main(String[] args) {
        A.test();
        A.B b = new A.B(); //因为B是静态内部类可以直接通过类名调用,创建实例
        A.B b1 = new A.B();

        b.a = 2;

        System.out.println(b1.a);
    }
}

输出结果: 过程是先进行外部类的静态初始化,然后分别是调用顺序BC

A static{}
AB static{} 0 AC static{}
0
2

二.外部类

1.什么是外部类

外部类(Outer Class)是指一个类,它包含其他类或成员,作为它的直接成员。外部类是一个独立的类,不被包含在其他类的内部。

外部类的实例化顺序以及this对外部类成员的调用

调用外部类的成员时,使用外部类名.this.成员名

外部类和内部类互相之间可以访问私有属性成员

public class OuterClass {
    private int outerPrivateVariable = 10;

    private void outerPrivateMethod() {
        System.out.println("Outer private method"); //5
    }

    class InnerClass {
        private int innerPrivateVariable = 20;

        private void innerPrivateMethod() {
            System.out.println("Inner private method"); //3
            System.out.println("Accessing outer private variable: " + outerPrivateVariable); //4
            outerPrivateMethod();
        }

        public void accessPrivateMembers() {
            System.out.println("Accessing inner private variable: " + innerPrivateVariable);  //2
            innerPrivateMethod();
        }
    }

    public void test() {
        InnerClass innerInstance = new InnerClass();
        innerInstance.accessPrivateMembers(); //1
    }

    public static void main(String[] args) {
        OuterClass outerInstance = new OuterClass();
        outerInstance.test();
    }
}

Accessing inner private variable: 20
Inner private method
Accessing outer private variable: 10
Outer private method

可见:内部类与外部类之间的私有属性可以互相访问

三.匿名类

1.什么是匿名类

匿名类没有显式的类名,通常在定义和使用的同时创建对象,并且常用于创建一次性的、小型的、临时的类实例,例如用于实现回调功能、事件处理等场景。

2.匿名类的使用

假设有一个Student抽象类,StudentTest类中:Stu继承Student类

public abstract class Student {

    public abstract void play();


    public void study() {
        System.out.println("学习");
    }
}

class StudentTest {

    public static void main(String[] args) {
        // 内部类, 当 main 方法调用结束,就销毁
        class Stu extends Student {

            @Override
            public void play() {
                System.out.println("玩游戏");
            }

            public void test(){
                System.out.println("test");
            }
        }

        Student s = new Stu();

        s.study();


        // 匿名类
        Student stu = new Student() {
            @Override
            public void play() {
                System.out.println("玩游戏");
            }

        };

        Person p = new Person();

        p.say();


        Person p1 = new Person(){
            @Override
            public void say(){
                System.out.println("放");
            }
        };

        p1.say();


    }


}

为了实现play这个方法,因为Student是抽象类,只能通过子类的实例化调用,而此时就是这一段

class Stu extends Student {

            @Override
            public void play() {
                System.out.println("玩游戏");
            }

            public void test(){ //子类内容的扩容
                System.out.println("test");
            }
        }

因为这种创建对象调用方法代价较大,因此,这种时候可以通过匿名类来进行临时的实例进行方法的重写

此时我们可以用匿名类:

Student stu = new Student() {
         @Override
         public void play() {
             System.out.println("玩游戏");
         }

     };

写法简单来说就是通过抽象类的实例化但是后面需要跟类的方法实现