Java SE 四大内部类

内部类

1、成员内部类

  1. 调用成员内部类

    //在外面的类的最后,写一个方法,调用成员内部类(创建对象,在访问)
    class Outer08{
        class Inner08{ //成员内部类
            public void say(){
                
            }
        }
        
        public void t1(){
            Inner08 inner08 = new Inner08();
            inner08.say();
        }
    }
    
  2. 可以直接访问外部类的所有成员,包含私有的。

  3. 外部其他类调用内部类的二种方法

    //
    Outero8.Inner08 inner08 = outero8.new Inner08();
    inner08.say();
    //2. 在外部类中,编写一个方法,可以返回 Inner08 对象
    //方法,返回一个Inner08实例
    public Inner08 getInner08Instance(){
        return new Inner08();
    }
    //调用
    Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
    inner08Instance.say();
    
  4. 如果成员内部类的成员和外部类的成员重名,会遵守就近原则,可以通过 外部类.this.属性 来访问。

2、静态内部类

public class StaticInnerClass01 {
    public static void main(String[] args) {

        Outer10 outer10 = new Outer10();
        outer10.m1();
        //外部其他类 使用静态内部类
        //方式1
        //直接创建一个 外部类.静态内部类 对象
        Outer10.Inner10 inner10 = new Outer10.Inner10();
        inner10.say();
        //方式2
        //编写一个方法,可以返回静态内部类的对象实例
        Outer10.Inner10 inner101 = outer10.getInner10();

        Outer10.Inner10 inner10_ = Outer10.getInner10_();
        inner10_.say();
    }
}

class Outer10 {//外部类
    private int n1 = 10;
    private static String name = "张三";
    private static void cry() {}
    //Inner10就是静态内部类
    //1. 放在外部类的成员位置
    //2. 使用static修饰
    //3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
    //4. 可以添加任意访问修饰符(public, protected,默认,private),因为它的地位就是一个成员
    //5. 作用域:同其他的成员,为整个类体
    //6. 如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵循就近原则,
    //      如果想访问外部类的成员,则可以使用(外部类名.成员)
    static class Inner10 {
        private static String name = "李四";
        public void say() {
            System.out.println(name + " 外部类name= " + Outer10.name);
            cry();
        }
    }
    //外部类访问静态内部类,创建对象,在访问
    public void m1() {
        Inner10 inner10 = new Inner10();
        inner10.say();
    }

    public Inner10 getInner10() {
        return new Inner10();
    }

    public static Inner10 getInner10_() {
        return new Inner10();
    }
}

/* 运行结果
	李四 外部类name= 张三
	李四 外部类name= 张三
	李四 外部类name= 张三
*/

3、局部内部类

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 不能添加访问修饰符,但是可以使用 final 修饰

  3. 作用域:仅仅在定义它的方法或代码块中

  4. 外部类在方法中,可以创建 Inner02 对象,然后调用方法即可

    class Outer02{//外部类
        public void m1(){//方法
            final class Inner02{//局部内部类(本质仍然是一个类)
                public void f1(){
                    
                }
            }
            Inner02 inner02 = new Inner02();
    		inner02.fi();
        }
    }
    
    //main 方法中调用
    Outer02 outer02 = new Outer02();
    outer02.m1();	//调用了fi() 方法
    
  5. (在类的方法中的类,调用的时候可以在此方法最后 new 局部内部类)

  6. 如果外部类和局部内部类的成员重名,默认遵循就近原则,可以通过 外部类.this.成员 来访问。

4、匿名内部类

  1. 匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

  2. 匿名内部类的基本语法

    ​ new 类或接口(参数列表){

    ​ 类体

    ​ };

  3. 本质还是一个类,内部类,该类没有名字,同时还是一个对象

  4. 可以直接访问外部类的所有成员,包含私有的

  5. 不能添加访问修饰符,因为它的地位就是一个局部变量

  6. 作用域:仅仅在定义它的方法或代码快中

  7. 匿名内部类访问外部类成员,直接访问

  8. 外部其他类不能访问匿名内部类(因为匿名内部类地位是一个局部变量)

  9. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,

    如果想访问外部类成员,则可以使用 (外部类名.this.成员) 去访问

public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}

class Outer04 { //外部类
    private int n1 = 10;
    public void method() {
        //基于接口的匿名内部类
        //3. 需求是 Tiger/Dog 类只是使用一次,后面再不使用
        //4. 可以使用匿名内部类来简化开发
        //5. tiger的编译类型    A
        //6. tiger的运行类型    就是匿名内部类 XXXX => Outer04$1
        /*
            我们看底层
            class XXXX implements A {
                @Override
                public void cry() {
                    System.out.println("老虎来了。。。");
                }
            }
         */
        //7. jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址
        //   返回给 tiger
        //8. 匿名内部类使用一次,就不能使用了,但是tiger可以多次使用
        A tiger = new A() {
            @Override
            public void cry() {
                System.out.println("老虎来了。。。");
            }
        };
        System.out.println("tiger的运行类型=" + tiger.getClass());
        tiger.cry();
        tiger.cry();
        tiger.cry();



        //演示基于类的匿名内部类
        //1. father编译类型 Father
        //2. father运行类型 Outer04$2
        //3. 底层会创建匿名内部类
        /*
            class Outer04$2 extends Father{
            }
         */
        //4. 同时也返回了 匿名内部类 Outer04$2 的对象
        //5. 注意("jack")参数列表会传递给 构造器
        Father father = new Father("jack") {
            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        };
        System.out.println("father的运行类型=" + father.getClass());
        father.test();


        //基于抽象类的匿名内部类
        Animal animal = new Animal(){
            @Override
            void eat() {
                System.out.println("小狗吃骨头。。。");
            }
        };
        animal.eat();

    }
}

interface A { //接口
    public void cry();
}

class Father {
    public Father(String name) { //构造器
        System.out.println("接收到的name= " + name);
    }
    public void test() {

    }
}

abstract class Animal { //抽象类
    abstract void eat();
}

/*
	运行结果
        tiger的运行类型=class com.hspedu.practice.Outer04$1
        老虎来了。。。
        老虎来了。。。
        老虎来了。。。
        接收到的name= jack
        father的运行类型=class com.hspedu.practice.Outer04$2
        匿名内部类重写了test方法
        小狗吃骨头。。。
*/
public class AnonymousInnerClassDetail {
    public static void main(String[] args) {
        Outer05 outer05 = new Outer05();
        outer05.f1();
        System.out.println("main outer05 hashcode=" + outer05);

    }
}

class Outer05 {
    private int n1 = 99;
    public void f1(){
        //创建一个基于基本类的匿名内部类
        Person01 p = new Person01(){
            private int n1 = 88;
            @Override
            public void hi() {
                System.out.println("匿名内部类重写了 hi()方法 n1 = " + n1 +
                        "外部类的n1=" + Outer05.this.n1);
                //Outer05.this 就是调用 f1的 对象
                System.out.println("Outer05.this hashcode=" + Outer05.this);
            }
        };
        p.hi(); //动态绑定,运行类型是 Outer05$1

        //也可以直接调用,匿名内部类本身也是返回对象
        // class 匿名内部类 extends Person {}
        new Person01(){
            @Override
            public void hi() {
                System.out.println("匿名内部类重写了 hi()方法,哈哈哈。。。");
            }

            @Override
            public void ok(String str) {
                super.ok(str);
            }
        }.ok("jack");
    }
}

class Person01 {
    public void hi() {
        System.out.println("Person01 hi()");
    }

    public void ok(String str) {
        System.out.println("Person01 ok()" + str);
    }
}

/*
	运行结果
		匿名内部类重写了 hi()方法 n1 = 88外部类的n1=99
        Outer05.this hashcode=com.hspedu.practice.Outer05@154617c
        Person01 ok()jack
        main outer05 hashcode=com.hspedu.practice.Outer05@154617c
*/
public class InnerClassExercise01 {
    public static void main(String[] args) {

        //当作实参直接传递,简洁高效
        f1(new IL() {
            @Override
            public void show() {
                System.out.println("这是一副名画。。。");
            }
        });

        //传统方法
        f1(new Picture());

    }
    //静态方法 形参是接口类型
    public static void f1(IL il) {
        il.show();
    }
}

interface IL {
    void show();
}

class Picture implements IL {
    @Override
    public void show() {
        System.out.println("这是一副名画。。。");
    }
}

/*
	运行结果
		这是一副名画。。。
		这是一副名画。。。
*/
public class InnerClassExercise02 {
    public static void main(String[] args) {
        CellPhone cellPhone = new CellPhone();
        //1. 传递的是实现了 Bell接口的匿名内部类
        //2. 重写了 ring
        //3. Bell bell = new Bell() {
        //            @Override
        //            public void ring() {
        //                System.out.println("懒猪起床了。");
        //            }
        //        }
        cellPhone.alarmClock(new Bell() {
            @Override
            public void ring() {
                System.out.println("懒猪起床了。");
            }
        });

        cellPhone.alarmClock(new Bell() {
            @Override
            public void ring() {
                System.out.println("小伙伴们上课了。");
            }
        });
    }
}

interface Bell{
    void ring();
}

class CellPhone{
    public void alarmClock(Bell bell){
        System.out.println(bell.getClass());
        bell.ring();
    }
}

/*
	运行结果
		class com.hspedu.practice.InnerClassExercise02$1
        懒猪起床了。
        class com.hspedu.practice.InnerClassExercise02$2
        小伙伴们上课了。
*/
posted @ 2022-09-13 21:29  花er公子  阅读(21)  评论(0编辑  收藏  举报