四种内部类的详解

目录

基本介绍

内部类的特点

内部类的基本语法

内部类的四种分类

定义在外部类局部位置上(比如方法内):

(1)局部内部类

局部内部类的使用

(2)匿名内部类(没有类名,重点!!!!

匿名内部类的细节

匿名内部类习题

第一题

第二题

定义在外部类的成员位置上:

1)成员内部类(没用static修饰)

成员内部类的使用

2)静态内部类(使用static修饰)

静态内部类的使用 

内部类的习题


基本介绍

一个类的内部又完整的嵌套了另一个类结构被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是我们类的第五大成员

类的五大成员是哪些?

分别是 属性 方法 构造器 代码块 内部类

内部类的特点

内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系 外部

内部类的基本语法

class Outerf { //外部类

        class Innert { //内部类

        }

}

class Othert{//外部其他类

}

代码演示:

package idea.chapter10.innerclass;

/**
 * 演示内部类的基本使用
 */
public class InnerClass01 {
    public static void main(String[] args) {
        /*
        一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是我们类的第五大成员
        类的五大成员是哪些
        分别是 属性 方法 构造器 代码块 内部类
         */

    }
}

class outer {//外部类

    //私有属性
    private int n1 = 100;//属性

    //构造器
    public outer(int n1) {//构造器
        this.n1 = n1;
    }

    //方法
    public void m1() {//方法
        System.out.println("m1()");
    }

    {//代码块
        System.out.println("代码块");
    }

    //内部类在outer类的内部
    class Inner {
        public void hi() {
            //内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系,方法和属性都可以使用
            System.out.println(n1);
            m1();
        }
    }
}

内部类的四种分类

内部类的分类有四种分别是,局部内部类,匿名内部类,成员内部类,静态内部类。其中匿名内部类是最重要也是最难的。

接下我们先来看局部内部类

定义在外部类局部位置上(比如方法内):

(1)局部内部类

局部内部类的使用

说明:

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

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

3.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final

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

5.局部内部类---访问---->外部类的成员[访问方式:直接访问]

6.外部类---访问---->局部内部类的成员 ;

访问方式:创建对象,再访问(注意:必须在作用域内)

记住:

(1)局部内部类定义在方法中/代码块

(2)作用域在方法体或者代码块中

(3)本质仍然是一个类

7.外部其他类---不能访问----->局部内部类(因为 局部内部类地位是一个局部变量)

8.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

System.out.println("外部类的n2=”+外部类名.this.n2);

代码演示:

package idea.chapter10.innerclass;

/**
 * 演示局部内部类的使用
 */
public class LocalInnerClass {//外部其他类
    public static void main(String[] args) {
        /*
        结论
        局部内部类的使用
        说明:
        1.局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。
        2.可以直接访问外部类的所有成员,包含私有的
        3.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
        4.作用域:仅仅在定义它的方法或代码块中。
        5.局部内部类---访问---->外部类的成员[访问方式:直接访问]
        6.外部类---访问---->局部内部类的成员 ;
        访问方式:创建对象,再访问(注意:必须在作用域内)
        记住:
        (1)局部内部类定义在方法中/代码块
        (2)作用域在方法体或者代码块中
        (3)本质仍然是一个类

        7.外部其他类---不能访问----->局部内部类(因为 局部内部类地位是一个局部变量)
        8.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
        System.out.println("外部类的n2=”+外部类名.this.n2);
         */


        //7.外部其他类---不能访问----->局部内部类(因为 局部内部类地位是一个局部变量)
        //我们的LocalInnerClass就是一个外部其他类,外部其他类来访问局部内部类,是不能访问的

        outer02 outer02 = new outer02();
        outer02.m1();
        
    }
}

class outer02 {
    //私有属性
    private int n1 = 100;
    private int a = 0;

    //私有方法
    private void m2() {
        System.out.println("Outer02 m2()");
    }

    public void m1() {
        //1.局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。
        //  这就是一个局部内部类,定义在方法中,也可以定义在代码块中 类名是Inner02,定义在方法中
        //3.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
        //注意不可以使用访问修饰符去修饰局部类,只能使用final 注意使用final修饰后的类还是可以被实例化的,如果是abstract那么就是一个抽象类就不能被实例化不要搞混了
        //4.作用域:仅仅在定义它的方法或代码块中。
        final class Inner02 {//局部内部类
            private int n1 = 800;

            public void hi() {
                //2.局部内部类可以直接访问外部类的所有成员,包含私有的
                //直接访问外部类的私有属性和私有方法
                System.out.println(n1);
                m2();

                //5.局部内部类---访问---->外部类的成员[访问方式:直接访问]
                System.out.println(a);

                //8.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
                //此时我们的Inner02类(也就是局部内部类)中有一个私有的n1属性,在外部类中也有一个n1s属性,因为默认遵守就近原则,所以当我们直接去输出n1的时候,访问到的是内部类中的值
                //如果想访问外部类中的值,使用外部类名.this.属性名去访问
                //看演示
                System.out.println(outer02.this.n1);//这里输出的就是外部类的n1
                System.out.println(n1);//因为默认遵守就近原则,所以访问到的就是内部类中的n1
                System.out.println(Inner02.this.n1);//这样访问的也是内部类中的n1
            }
        }
        //6.外部类---访问---->局部内部类的成员 ;
        //访问方式:创建对象,再访问(注意:必须在作用域内) 因为他的作用域是在定义他的方法或者代码块中
        //记住:
        //(1)局部内部类定义在方法中/代码块
        //(2)作用域在方法体或者代码块中
        //(3)本质仍然是一个类
        //注意此时这段代码的范围是在m1()方法中的,外部类也可以直接访问内部类的私有属性
        Inner02 inner02 = new Inner02();
        System.out.println(inner02.n1);

    }


}


(2)匿名内部类(没有类名,重点!!!!

匿名内部类的使用(重要!!!!!!!) 

(1)本质是类

(2)内部类

(3)该类没有名字

(4)同时还是一个对象

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

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

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

        类体

};

代码演示:

package idea.chapter10.innerclass;

/**
 * 演示匿名内部类的使用
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}

class Outer04 { //外部类
    private int n1 = 10;//属性

    public void method() {//方法
        //基于接口的匿名内部类
        //解读
        //1.现在我们有一需求就是需求: 想使用IA接口,并创建对象
        //2.传统方式,是写一个类,实现该接口,然后创建对象
        //3.需求是 Tiger/Dog 类只是使用一次,后面再不使用
        //4. 可以使用匿名内部类来简化开发
        //5. tiger的编译类型 -> IA
        //6. tiger的运行类型 -> 就是匿名内部类  Outer04$1
        /*
            在底层 会分配 类名 Outer04$1  (就是类名+$1)
            class Outer04$1 implements IA {
                @Override
                public void cry() {
                    System.out.println("老虎叫唤...");
                }
            }
         */
        //7. jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1实例,并且把地址返回给 tiger
        //8. 匿名内部类使用一次,就不能再使用
        IA tiger = new IA() {
            @Override
            public void cry() {
                System.out.println("老虎在叫");
            }
        };
        //getClass就是获取到对象的运行类型
        System.out.println("tiger的运行类型=" + tiger.getClass());
        //因为匿名内部类只会创建一次对象使用完后对象就销毁了,但是创建出来的对象实例,可以继续使用
        tiger.cry();
        tiger.cry();

//        IA tiger = new Tiger();
//        tiger.cry();

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

            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        };
        System.out.println("father对象的运行类型=" + father.getClass());//Outer04$2
        father.test();

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

interface IA {//接口

    public void cry();
}
//class Tiger implements IA {
//
//    @Override
//    public void cry() {
//        System.out.println("老虎再叫");
//    }
//}
//class Dog implements  IA{
//    @Override
//    public void cry() {
//        System.out.println("小狗再叫");
//    }
//}

class Father {//类

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

    public void test() {//方法
    }
}

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

匿名内部类的细节

2.匿名内部类的语法比较奇特,请大家注意,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。

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

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

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

6.匿名内部类---访问---->外部类成员[访问方式:直接访问]

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

8.如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

代码演示:

package idea.chapter10.innerclass;


/**
 * 演示匿名内部类的注意事项和使用细节
 */
public class AnonymousInnerClassDetail {
    public static void main(String[] args) {
        /*
        2.匿名内部类的语法比较奇特,请大家注意,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
        3.可以直接访问外部类的所有成员,包含私有的[案例演示]
        4.不能添加访问修饰符,因为它的地位就是一个局部变量。[过]
        5.作用域:仅仅在定义它的方法或代码块中。[过]
        6.匿名内部类---访问---->外部类成员[访问方式:直接访问]
        7.外部其他类---不能访问----->匿名内部类(因为 匿名内部类地位是一个局部变量)
        8.如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
         */

        Outer05 outer05 = new Outer05();
        outer05.m1();

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

class Outer05 {
    private int a = 10;

    public void m1() {
        //创建一个基于类的匿名内部类
        //此时p的 编译类型 -> Person
        //       运行类型 -> Outer05&1
        //4.不能添加访问修饰符,因为它的地位就是一个局部变量
        //5.作用域:仅仅在定义它的方法或代码块中
        Person p = new Person() {
            private int a = 20;

            @Override
            public void hi() {
                //3.可以直接访问外部类的所有成员,包含私有的
                //6.匿名内部类---访问---->外部类成员[访问方式:直接访问]
                //直接访问外部类的私有属性
                System.out.println(a);
                System.out.println("匿名内部类重写了hi方法");

                //8.如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
                System.out.println(a);//因为默认遵守就近原则,所以访问到的是匿名内部类中的a
                //如何访问外部类中的属性
                System.out.println(Outer05.this.a);//这样访问到的就是外部类中的a

            }
        };
        p.hi();//会有动态绑定 , 因为运行类型是Outer05$1 所以会找到Outer05$1中的方法

        //如果没有重写hi方法
        //此时p1的 编译类型 -> Person
        //        运行类型 -> Person
        Person p1 = new Person() {

        };
        p1.hi();//此时调用的方法就是Person中的hi方法因为,p1的运行类型是Person

        //也可以直接调用,因为匿名内部类本身返回的就是一个对象
        new Person() {
            @Override
            public void hi() {
                System.out.println("匿名内部类又一次的重写了hi方法");
            }
        }.hi();//可以直接调用
        /*
        可以这样理解
        new Person(){
            @Override
            public void hi() {
                System.out.println("匿名内部类又一次的重写了hi方法");
            }
        }

        上面这一大块,返回的就是一个对象,在使用对象.方法,不就是我们传统的调用方法的形式吗,对象名.方法名

         */

    }
}

class Person {
    public void hi() {
        System.out.println("Person中的hi方法");
    }
}

匿名内部类习题

第一题

代码演示:

package idea.chapter10.innerclass;

public class InnerClassExercise01 {
    public static void main(String[] args) {
        //当做实参直接传递,简洁高效
        f(new AA() {
            @Override
            public void show() {
                System.out.println("AA接口中的show方法被调用");
            }
        });

        //传统方法
        /*
        因为我们的f方法的形参是AA 因为我们的Picture实现了AA接口,所以可以吧Picture传入到方法中,因为接口可以指向实现了该接口的对象实例
         */
        f(new Picture());

    }

    //静态方法,形参是接口类型
    public static void f(AA a) {
        a.show();
    }
}


interface AA {
    void show();
}

//类->实现AA => 编程领域 (硬编码)
class Picture implements AA {

    @Override
    public void show() {
        System.out.println("这是一副画");
    }
}

第二题

代码演示:

package idea.chapter10.innerclass;

/**
 * 匿名内部类习题
 */
public class InnerClassExercise02 {
    public static void main(String[] args) {

    /*
    1.有一个铃声接口Bell,里面有个ring方法。
    2.有一个手机类Cellphone,具有闹钟功能alarmClock,参数是Bell类型
    3.测试手机类的闹钟功能,通过匿名内部类(对象)作为参数,打印:懒猪起床了
    4.再传入另一个匿名内部类(对象),打印:小伙伴上课了
     */

        Cellphone cellphone = new Cellphone();

        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) {
        //因为我们不同的匿名内部类传入进来,运行类型也会不同,会根据运行类型去找到,对应的方法去执行
        bell.ring();//会有动态绑定
    }
}

定义在外部类的成员位置上:

1)成员内部类(没用static修饰)

成员内部类的使用

说明:

1.成员内部类是定义在外部类的成员位置,并且没有static修饰。

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

3.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。

4.作用域和外部类的其他成员一样,为整个类体 比如前面案例,在外部类的成员方法中创建成员内部类对象,再调用方法.

5.成员内部类---访问---->外部类成员(比如:属性)访问方式:直接访问

6.外部类---访问------>成员内部类(说明)访问方式:创建对象,再访问

7.外部其他类---访问---->成员内部类

8.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如 果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

代码演示:

package idea.chapter10.innerclass;

/**
 * 演示成员内部类的使用
 */
public class MemberInnerClass01 {
    public static void main(String[] args) {
        outer08 outer08 = new outer08();
        /*
        说明:
        1.成员内部类是定义在外部类的成员位置,并且没有static修饰。
        2.可以直接访问外部类的所有成员,包含私有的
        3.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
        4.作用域和外部类的其他成员一样,为整个类体 比如前面案例,在外部类的成员方法中创建成员内部类对象,再调用方法.
        5.成员内部类---访问---->外部类成员(比如:属性)访问方式:直接访问
        6.外部类---访问------>成员内部类(说明)访问方式:创建对象,再访问
        7.外部其他类---访问---->成员内部类
        8.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如 果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
         */


        //7.外部其他类---访问---->成员内部类
        // 第一种方式
        // outer08.new Inner08(); 相当于把 new Inner08()当做是outer08成员
        // 这就是一个语法,不要特别的纠结.
        outer08.Inner08 inner081 = outer08.new Inner08();
        inner081.m1();
        // 第二方式 在外部类中,编写一个方法,可以返回 Inner08对象
        outer08.Inner08 inner082 = outer08.getInner08();
        inner082.m1();


    }
}

class outer08 {//外部类
    //私有属性
    private int n1 = 10;
    public String name = "jack";

    //私有方法
    private void hi() {
        System.out.println("hello,word");
    }

    //1.成员内部类是定义在外部类的成员位置,并且没有static修饰。 此时我们的内部类就是定义在属性的位置上的
    //3.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
    public class Inner08 {
        private int n1 = 66;

        public void m1() {
            //2.可以直接访问外部类的所有成员,包含私有的
            //直接访问外部类的私有属性和私有方法
            System.out.println(n1);
            hi();

            //5.成员内部类---访问---->外部类成员(比如:属性)访问方式:直接访问
            //访问外部类的私有属性
            System.out.println(name);
            //访问外部类的私有方法
            hi();


            //8.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如 果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
            System.out.println(outer08.this.n1);//访问的是外部类的n1
            System.out.println(n1);//因为遵守就近原则,所以访问的是,Inner08中的n1
            System.out.println(Inner08.this.n1);//访问的也是Inner08中的n1
        }
    }

    //编写一个方法,返回一个Inner08的对象
    public Inner08 getInner08() {
        return new Inner08();
    }

    //4.作用域和外部类的其他成员一样,为整个类体 比如前面案例,在外部类的成员方法中创建成员内部类对象,再调用方法.
    //6.外部类---访问------>成员内部类(说明)访问方式:创建对象,再访问
    public void ok() {
        //外部类使用内部类成员,先创建对象,然后使用相关属性或者方法
        Inner08 inner08 = new Inner08();
        inner08.m1();
        System.out.println(inner08.n1);//可以直接访问成员内部类的私有属性
    }
}

2)静态内部类(使用static修饰)

静态内部类的使用 

说明:

1.静态内部类是定义在外部类的成员位置,并且有static修饰

2.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

3.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。

4.作用域:同其他的成员,为整个类体

5.静态内部类---访问---->外部类(比如:静态属性)[访问方式:直接访问所有静 态成员]

6.外部类---访问------>静态内部类 访问方式:创建对象,再访问

7.外部其他类---访问----->静态内部类

8.如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近 原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问。

代码演示:

package idea.chapter10.innerclass;

/**
 * 演示静态内部类的使用
 */
public class StaticInnerClass01 {
    public static void main(String[] args) {
        outer10 outer = new outer10();
        /*
        1.静态内部类是定义在外部类的成员位置,并且有static修饰
        2.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
        3.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
        4.作用域:同其他的成员,为整个类体
        5.静态内部类---访问---->外部类(比如:静态属性)[访问方式:直接访问所有静 态成员]
        6.外部类---访问------>静态内部类 访问方式:创建对象,再访问
        7.外部其他类---访问----->静态内部类
        8.如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近 原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问
         */

        //7.外部其他类---访问----->静态内部类
        //方式1
        //因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
        outer10.Inner10 inner10 = new outer10.Inner10();
        inner10.hi();
        //方式2
        //编写一个方法,可以返回静态内部类的对象实例.
        outer10.Inner10 inner101 = outer.getInner10();
        inner101.hi();

    }
}

class outer10 {
    //私有属性
    private int n1 = 10;
    //私有的静态属性
    private static String name = "jack";

    //私有的静态方法
    private static void cry() {
    }

    //1.静态内部类是定义在外部类的成员位置,并且有static修饰
    //Inner10就是静态内部类
    //定义在类的局部位置上
    //并且是static修饰的
    //3.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
    //4.作用域:同其他的成员,为整个类体
    static public class Inner10 {
        private static String name = "tom";

        //2.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
        public void hi() {
            //直接使用外部类的静态私有属性
            System.out.println(name);
            //直接使用外部类的静态私有方法
            cry();
            //不能直接使用外部类的非静态属性,会报错
            //System.out.println(n1);


            //5.静态内部类---访问---->外部类(比如:静态属性)[访问方式:直接访问所有静 态成员]
            //访问外部类的静态私有属性
            System.out.println(name);
            //访问外部类的静态私有方法
            cry();

            //8.如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近 原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问
            System.out.println(name);//因为遵守的是就近原则,所以访问的是内部类中的name
            System.out.println(outer10.name);//访问的就是外部类中的name属性
            System.out.println(Inner10.name);//访问的就是内部类中的name属性
        }
    }

    //编写方法返回Inner10对象
    public Inner10 getInner10() {
        return new Inner10();
    }

    public void m1() {
        //6.外部类---访问------>静态内部类 访问方式:创建对象,再访问
        Inner10 inner10 = new Inner10();
        System.out.println(inner10.name);
        inner10.hi();
    }
}

内部类的习题

思路分析:

1.在执行这句话的时候Test t = new Test(); 会导致类的加载,因此会去执行Test的构造器,在构造器中创建了一个Inner的对象实例s1 然后将s1.a改成了10
  紧接着就创建了一个Inner的对象实例s2,此时直接输出了s2.a,注意输出的值是5并不是10 导致构造器的部分就结束了
2.接下来就执行了这样一句话,  Test.Inner r = t.new Inner();  这句话的意思就是创建了一个内部类的对象,然后直接输出,因为a属性是public的,因此可以输出,
3.最后输出的结果就是两个5
package idea.chapter10.innerclass;

/**
 * 静态内部类习题
 */
public class InnerClassExercise {
    public static void main(String[] args) {
        Test t = new Test();
        Test.Inner r = t.new Inner();//5
        System.out.println(r.a);//5
    }
}
/*
思路分析:
1.在执行这句话的时候Test t = new Test(); 会导致类的加载,因此会去执行Test的构造器,在构造器中创建了一个Inner的对象实例s1 然后将s1.a改成了10
  紧接着就创建了一个Inner的对象实例s2,此时直接输出了s2.a,注意输出的值是5并不是10 导致构造器的部分就结束了
2.接下来就执行了这样一句话,  Test.Inner r = t.new Inner();  这句话的意思就是创建了一个内部类的对象,然后直接输出,因为a属性是public的,因此可以输出,
3.最后输出的结果就是两个5
 */
class Test {//外部类

    public Test() {//构造器
        Inner s1 = new Inner();
        s1.a = 10;
        Inner s2 = new Inner();
        System.out.println(s2.a);
    }

    class Inner { //内部类,成员内部类
        public int a = 5;
    }
}

你可能感兴趣的:(Java,java,开发语言)