欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

深入探索Java内嵌类与匿名类的精详解读,超级详细全面讲解

最编程 2024-02-21 15:24:53
...

内部类

内部类初识

内部类顾名思义就在类的内部中的类!


我们知道,类中可以有两种重要的成员,成员变量(字段/属性)和方法(行为),实际上java还允许类有一种成员——内部类!

java支持在一个类中定义另一个类,这样的类就称为内部类,而包含内部类的类称为内部类的外嵌类!


内部类是类的第5大成员

类的5大成员:


属性,方法,构造器,代码块,内部类


内部类最大特点:

可以访问类中的私有属性,体现类和类的包含关系!


内部类是java一个重点和难点,并且在java底层代码中有很多内部类的使用!


嵌套:


嵌套指的是一种类之间的关系,而不是对象之间的关系。外嵌类对象并不会包含内部类类型的子对象!


基础语法

class 外嵌类类名 {
    class 内部类类名 {
    } 
}

外嵌类和内部类的之间的关系:


1.外嵌类中的成员变量内部类中仍然有效,外嵌类方法可以在内部类中的方法中调用!

class People{
    protected String name;
    protected int age;
    public void speak(){
        System.out.println(name+":speak()");
    }
    class Child{
        //内部类可以访问外嵌类中的成员变量!
        String name = People.this.name;
        public void speak1(){
            speak(); //在内部类方法中调用外嵌类中的方法!
        }
        public void speak(){
            People.this.speak();//当内部类中的方法和外嵌类方法名相同时
                 //通过类名.this.方法名调用外嵌类同名方法
            // speak();
        }
    }
}

2.内部类的类体中不能声明类变量和类方法

//内部类中不含类变量和类方法!
class People{
    class Child{
        static String sex; //error
       public static void eat(){  //error
           System.out.println("eat::()!");
       }
    }
}

image.png

因为我们知道stataic修饰的类变量和类方法属于类,类加载时便一起加载了,而外嵌类加载完并不会加载内部类,而static类型的变量和方法在类加载时会初始化,这两者就会导致内部类未加载,但其成员却初始化了,这是矛盾的,所以内部类中的变量和方法不能被static关键字修饰!


3.外嵌类的类体中可以用内部类声明的对象作为外嵌类的成员。

class People{
    //外嵌类中声明内部类对象
    Child child = new Child();
    public void speak(){
        System.out.println();
    }
    class Child{
        String sex;
       public void eat(){
           System.out.println("eat::()!");
       }
    }
}

4.内部类仅提供他的外嵌类使用,其他类不可以用某个类的内部类声明对象

class People{
    Child child = new Child();
    public void speak(){
        child.eat(); //内部类对象只能在外嵌类中使用!
        System.out.println();
    }
    class Child{
       public void eat(){
           System.out.println("eat::()!");
       }
    }
}
public class Test_1 {
    public static void main(String[] args) {
        People.Child child = new People.Child();//error
        //内部类无法在其他类中创建对象 
    }
}

image.png



5.内部类可以用protected和private修饰,而一般类只能用public修饰!

class People{
    public void speak(){
        System.out.println();
    }
    private class Child{ //内部类可用private和protect修饰
       public void eat(){
           System.out.println("eat::()!");
       }
    }
}
 protect class A{ //error 一般类只能用public 修饰
   
}

image.png


6.当外嵌类和内部类中成员变量或方法同名时,相互使用或调用语法规则

//在外嵌类中调用内部类中的同名的方法!
class People{
    public void eat(){
        System.out.println("People eat::()!");
    }
    public void speak(){
        //People的eat
        eat();
        this.eat();
        People.this.eat();
        System.out.println("======");
        //Child的eat
        new Child().eat();
    }
    private class Child{ 
       public void eat(){
           System.out.println("Child eat::()!");
       }
    }
}
public class Test_1 {
    public static void main(String[] args) {
        People people = new People();
        people.speak();//调用谁的eat()?
    }
}

image.png

在内部类中可以通过类名.this.方法名调用外嵌类中同名方法!


7.内部类的字节码文件名字和通常的类不同,内部类字节码文件名字格式是:外嵌类类名$内部类类名.class

image.png

内部类分类

我们刚刚大概了解了内部类的语法和使用,可能有点绕,没有捋清楚,不要急,bug郭带你仔细学一遍!

根据内部类在外部类中的位置可以分为4种:


局部内部类,定义在外部类中的局部范围(方法和代码块中)

匿名内部类(学习的重点和难点)也通常定义在局部

成员内部类(定义在外部类的成员位置)

静态内部类(用stataic修饰的内部类)

我会一一给大家详细介绍这四种内部类的使用方法和细节!


局部内部类

在外嵌类的局部位置,通常在方法中或代码块中!


局部内部类特点:

1.定义在外部类局部(方法或者代码块中)

2.作用域在局部,只能在他的作用域中使用(方法或者代码块中)

3.本质还是一个类(可以被继承)

4.属于局部变量,不能用限定符修饰(可用finall修饰后不可被继承)

5.内部类可以直接访问外部类中的属性和方法(包括private修饰)

6.外部类访问局部内部类,只能创建内部类对象访问(且只能在该局部中)

7.当外部类和内部类重名时,遵守就近原则


//局部内部类
class Outer{//外部类
    private int m = 10; //属性
    private static String s = "Outer";
    public void f1(){ //方法
        System.out.println("Outer::f1");
    }
    public void f2(){//方法
        /*
        局部内部类:
        1.定义在外部类局部(方法或者代码块中)
        2.作用域在局部,只能在他的作用域中使用(方法或者代码块中)
        3.本质还是一个类(可以被继承)
        4.属于局部变量,不能用限定符修饰(可用finall修饰后不可被继承)
        5.内部类可以直接访问外部类中的属性和方法(包括private修饰)
        6.外部类访问局部内部类,只能创建内部类对象访问(且只能在该局部中)
        7.当外部类和内部类重名时,遵守就近原则
         */
        class Inner {//内部类
            private int a = 12;//属性
            public void f2(){//方法
                System.out.println("Inner::f2");
                f1(); //局部内部类直接访问外部类成员和方法
                System.out.println("Outer:private m="+m+" Inner::a="+a);
            }
        }
        //外部类只能通过创建外部类对象访问内部类
        Inner inner = new Inner();
        inner.f2();//方法同名就近原则
        class Inner1 extends Inner {//继承Inner类
        }
    }
}
public class Test_1{
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.f2();
    }
}

image.png


因为有前面学习的基础,bug郭就不一一列举代码了,可以自行尝试!


匿名类

我们是否想过一个问题,内部类既然只能在外嵌类中使用,显然当我们只需要使用该内部类一次时,常规方法创建一个内部类比较麻烦,价值不高,有其他方法解决该问题嘛?

那就是匿名类!

匿名类是不能有名字的类,它们不能被引用,只能在创建时用 new 语句来声明它们。


匿名类特点:

1.本质是一个类

2.没有名字的类

3.属于内部类

4.还是个对象


匿名类语法格式: