详解内部类

一个类的内部又嵌套了另一个类 --> 内部类

1.定义在局部位置(方法/代码块)

        1)局部内部类(有类名)

        2)匿名内部类(无类名)

2.定义在成员位置

        1)成员内部类

        2)静态内部类

 

一.局部内部类

1.什么是局部内部类?

——将类定义在另一个类的内部方法或代码块中

 

2.局部内部类的格式

class 类名 {
    //1)定义在方法中
    权限修饰符 返回类型 方法名(形参列表...) {
        class 类名 {                    
        }    
    }
    
    //2)定义在代码块中
    {
        class 类名 {                    
        }    
    }
}
public class Test {
    public static void main(String[] args) {
    }
}

class Person {
    public void say() {
        //1)定义在方法中
        class Teacher {}
    }

    //2)定义在代码块中
    {
        class Student {}
    }
}

 

3.一个小case快速了解局部内部类

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    private int age = 10;

    public void hello() {
        //1)定义在方法中
        class Teacher {
            private int num = 20;

            public void hi() {
                System.out.println("hi~");
                System.out.println(num);
            }
        }

        //访问局部内部类的属性
        Teacher teacher = new Teacher();
        teacher.hi();
    }

    //2)定义在代码块中
    {
        class Student {
            public void say() {
                System.out.println("say~");
                System.out.println(age);
            }
        }

        //访问局部内部类的属性
        Student student = new Student();
        student.say();
    }
}

 

4.局部内部类的细节讨论及实现

1)局部内部类可以直接访问外部类的所有成员,包括私有的属性

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;
    int num = 130;
    public double price = 13001.13;

    public void hello() {
        class Teacher {
            public void hi() {
                //局部内部类可以直接访问外部类的所有成员,包括私有的属性
                System.out.println(age);
                System.out.println(num);
                System.out.println(price);
                go();
            }
        }

        //访问局部内部类的属性
        Teacher teacher = new Teacher();
        teacher.hi();
    }

    //外部类的方法
    public void go() {
        System.out.println("bro,go go go~");
    }
}

2)局部内部类不能添加访问修饰符,因为它本身的地位就是一个局部变量(局部变量不能使用访问修饰符,但是能使用final关键字修饰)

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        //局部内部类不能任何访问修饰符,因为局部内部类本质上是局部变量
        //public class Stu{}

        //局部内部类可以使用final修饰
        final class Teacher {
            public void hi() {
                System.out.println(age);
                go();
            }
        }

        //访问局部内部类的属性
        Teacher teacher = new Teacher();
        teacher.hi();
    }

    public void go() {
        System.out.println("bro,go go go~");
    }
}

3)局部内部类的作用域:在定义它的方法中或代码块中

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    //局部内部类的作用域:在定义它的方法中或代码块中
    public void hello() {
        class Teacher {
            public void hi() {
                System.out.println(age);
                go();
            }
        }

        //访问局部内部类的属性
        Teacher teacher = new Teacher();
        teacher.hi();
    }

    //除了所在的作用域(hello方法内)后,无法使用
    public void go() {
        //Teacher teacher = new Teacher();//错误
    }
}

4)局部内部类本质是还是类,遵守类的一切规定

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        //局部内部类本质是还是类,遵守类的一切规定
        class Teacher {
            //属性
            private int num;
            public static int AGE = 100;

            //构造器
            public Teacher() {}

            //方法
            public int getNum() {
                return num;
            }
            public void setNum(int num) {
                this.num = num;
            }
        }
    }
}

5)外部类访问局部内部类的成员:创建对象,再访问(需在作用域内)

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        class Teacher {
            public void get() {
                System.out.println(age);
            }
        }
        
        //外部类访问局部内部类的成员:创建对象,再访问(需在作用域内)
        Teacher teacher = new Teacher();
        teacher.get();
    }
}

6)外部其他类不能访问局部内部类,因为局部内部类的地位就是局部变量

public class Test {
    public static void main(String[] args) {
        //外部其他类不访问局部内部类,因为局部内部类的地位就是局部变量
        //Test是外部其他类
        //Teacher teacher = new Teacher();//不能访问
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        class Teacher {
            public void get() {
                System.out.println(age);
            }
        }
    }
}

7)外部类的成员与局部内部类的成员重名的时候,访问的时候遵循就近原则,若要访问同名的外部类的成员,使用 外部类名.this.类名 访问

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        class Teacher {
            public int age = 20;
            //外部类的成员与内部类的成员重名的时候,访问的时候遵循就近原则,
            //若要访问同名的外部类的成员,使用 外部类名.this.类名 访问
            public void get() {
                System.out.println(age);//20
                //理解:谁调用这个对象就是指谁
                System.out.println(Person.this.age);//10
            }
        }

        //访问局部内部类
        Teacher teacher = new Teacher();
        teacher.get();
    }
}

 

 

二.匿名内部类

1.什么是匿名内部类?

——匿名内部类是没有类名的类,它只能存在于另一个类的方法中或代码块中

 

2.匿名内部类的格式

new 类名/接口(形参列表...) {
    //类体
};
//在底层原理中,匿名内部类实现接口或继承类(重点)
//当要把匿名内部类的地址返回给一个实例时,实例获得地址

 

3.一个小case快速了解匿名内部类

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
        person.hi();
    }
}

//接口
interface Usb {
    void set();
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        //基于类的匿名内部类
        //使用方式1
        //匿名内部类使用一次就销毁
        new Teacher() {
            public void hi() {
                System.out.println("hi~ I love you~");
            }
        }.hi();

        //使用方式2
        //把匿名内部类的地址返回给teacher实例
        Teacher teacher = new Teacher() {
            //这个地方是继承父类,如果父类中没有对应方法则报错
            public void say() {
                System.out.println("hello~");
            }
        };

        teacher.say();
    }

    public void hi() {
        //基于接口的匿名内部类
        new Usb() {
            @Override
            public void set() {
                System.out.println("connection~");
            }
        }.set();
    }
}

class Teacher {
    public void say() {
    }
}

 

4.匿名内部类真的没有类名吗?

——匿名内部类是有类名的,这个类名是有系统分配的,一般命名为包名.外部类$数字

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        //编译类型: Teacher
        //运行类型?
        Teacher teacher = new Teacher() {
            //这个地方是继承父类,如果父类中没有对应方法则报错
            public void say() {
                System.out.println("hello~");
            }
        };
        //查看匿名内部类的运行类型
        System.out.println(teacher.getClass());//class inner.Person$1
    }
}

class Teacher {
    public void say() {
    }
}

 

5.匿名内部类的细节讨论及实现

1)匿名内部类既是一个类的定义,同时也是一个对象(含有定义类和创建对象的特征)

2)匿名内部类可以直接访问外部类的所有成员,包括私有的

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;
    public double rate = 0.03;

    public void hello() {
        Teacher teacher = new Teacher() {
            public void say() {
                //匿名内部类可以直接访问外部类的所有成员,包括私有的
                System.out.println(age);//10
                System.out.println(rate);//0.03
            }
        };
        teacher.say();
    }
}

class Teacher {
    public void say() {
    }
}

3)不能添加访问修饰符,它本身的地位就是局部变量

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        //不能添加访问修饰符,它本身的地位就是局部变量
        //public new Teacher() {}//错误

        //能使用final
        final Teacher teacher = new Teacher() {
            public void say() {
                System.out.println("hi~  bro~");
            }
        };
        teacher.say();
    }
}

class Teacher {
    public void say() {
    }
}

4)作用域:定义的方法或代码块中

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        Teacher teacher = new Teacher() {
            public void say() {
                System.out.println("hi~  bro~");
            }
        };
        teacher.say();
    }

    //作用域:定义匿名内部类的方法或代码块中
    //teacher.say();//错误,不在作用域内
    public void set() {
        //teacher.say();//错误,不在作用域内
    }
}

class Teacher {
    public void say() {
    }
}

5)外部其他类不能访问匿名内部类(匿名内部类的地位本质是局部变量)

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();

        //外部其他类不能访问匿名内部类(匿名内部类的地位本质是局部变量)
        //Test是外部其他类
        //teacher.say();//错误,不能访问
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        Teacher teacher = new Teacher() {
            public void say() {
                System.out.println("hi~  bro~");
            }
        };
        teacher.say();
    }
}

class Teacher {
    public void say() {
    }
}

6)外部类的成员与匿名内部类的成员重名的时候,访问的时候遵循就近原则,若要访问同名的外部类的成员,使用 外部类名.this.类名 访问

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.hello();
    }
}

class Person {
    //外部类的属性
    private int age = 10;

    public void hello() {
        Teacher teacher = new Teacher() {
            private int age = 20;
            public void say() {
                System.out.println(age);//20
                //访问同名的外部类的成员,使用 外部类名.this.类名 访问
                System.out.println(Person.this.age);//10
            }
        };
        teacher.say();
    }
}

class Teacher {
    public void say() {
    }
}

 

6.匿名内部的实践 —— 作为实参传递

1)基于接口作为实参

public class Test {
    public static void main(String[] args) {
        //匿名内部类作为实参传递
        fulfill(new Usb() {
            public void set() {
                System.out.println("创建成功~");
            }

            public void connect() {
                System.out.println("连接成功~");
            }
        });

    }

    //形参使用接口接收
    public static void fulfill(Usb usb) {
        usb.set();
        usb.connect();
    }
}

interface Usb {
    void set();
    void connect();
}

2)基于类作为实参

public class Test {
    public static void main(String[] args) {
        //匿名内部类作为实参传递
        fulfill(new Teacher() {
            public void hello() {
                System.out.println("hello~ 小朋友~");
            }
        });
    }

    //形参使用接口接收
    public static void fulfill(Teacher teacher) {
        teacher.hello();
    }
}

class Teacher {
    public void hello() {}
}

 

 

三.成员内部类

1.什么是成员内部类?

——成员内部类位于另一个类的成员位置上,本质就是外部类的一个成员

 

2.成员内部类的格式

class 类名 {
    //属性和方法
    class 类名 {
        //属性和方法    
    }
}

 

3.一个小case快速了解成员内部类

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.age = 19;
        //外部其他类访问成员内部类
        Person.Teacher teacher = person.new Teacher("jack");
        teacher.get();
    }
}

//成员内部类的演示
class Person {
    //外部属性
    public int age;
    private char gender = '男';

    //外部构造器
    public Person() {
    }

    //成员内部类
    class Teacher {
        //内部属性
        public String name;

        public Teacher(String name) {
            this.name = name;
        }

        public void get() {
            System.out.println(name);
            System.out.println(age);
            System.out.println(gender);
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

 

4.成员内部类的细节讨论及实现

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

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.age = 19;
        //外部其他类访问成员内部类
        Person.Teacher teacher = person.new Teacher();
        teacher.get();
    }
}

//成员内部类的演示
class Person {
    //外部属性
    public int age;
    private char gender = '男';

    //成员内部类
    class Teacher {
        public void get() {
            //成员内部类能直接访问外部类的所有成员,包括私有的
            System.out.println(age);
            System.out.println(gender);
        }
    }
}

2)可以添加任意的权限访问修饰符(public、protected、默认、private),因为成员内部类的地位就是外部类的一个成员

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

//成员内部类的演示
class Person {
    //外部属性
    public int age;
    private char gender = '男';

    //成员内部类
    //可以添加任意的权限访问修饰符(public、protected、默认、private)
    public class Teacher {}
    protected class Stu {}
    class Student {}
    private class Colleague {}
}

3)作用域和外部类的其他成员相同,为整个类体

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        //外部可以访问创建成员内部类
        Person.Teacher teacher = person.new Teacher();
        teacher.get();
    }
}

//成员内部类的演示
class Person {
    //外部属性
    public int age;
    private char gender = '男';

    //成员内部类
    //作用域和外部类的其他成员相同,为整个类体
    class Teacher {
        public void get() {
            System.out.println("外部能创建实例对象~");
        }
    }
}

4)外部类访问成员内部类:创建对象进行访问

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.assess();
    }
}

//成员内部类的演示
class Person {
    //外部属性
    public int age;
    private char gender = '男';

    //成员内部类
    class Teacher {
        public void get() {
            System.out.println("外部类访问成员内部类~");
        }
    }

    //外部类访问成员内部类:创建对象进行访问
    public void assess() {
        Teacher teacher = new Teacher();
        teacher.get();
    }
}

5)外部其他类访问成员内部类的形式

        a.直接创建对象访问

                外部类名.成员内部类名 对象名 = 外部类名的实例.new 成员内部类类名(参数);

        b.外部类中通过返回一个成员内部类的对象实例来进行访问

class 外部类 {
    class 成员内部类 {            
    }
    //提供返回成员内部类的实例对象的方法
    public 成员内部类名 方法名() {
        //返回实例对象    
    }
}
public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        //外部其他类访问成员内部类
        //1.直接创建对象访问
        Person.Teacher teacher = person.new Teacher();
        teacher.get();
        //2.外部类提供公共的内部类实例方法
        Person.Teacher teacher1 = person.getInstance();
        teacher1.get();
    }
}

//成员内部类的演示
class Person {
    //外部属性
    public int age;
    private char gender = '男';

    //成员内部类
    class Teacher {
        public void get() {
            System.out.println("外部其他类访问成员内部类~");
        }
    }

    //返回成员内部类的实例对象
    public Teacher getInstance() {
        return new Teacher();
    }
}

6)若外部类和成员内部类的成员名相同时,按照就近原则访问,若要访问外部类的属性,则使用外部类名.this.属性名访问

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        Person.Teacher teacher = person.new Teacher();
        teacher.get();
    }
}

//成员内部类的演示
class Person {
    //外部属性
    private char gender = '男';

    //成员内部类
    class Teacher {
        private char gender = '女';

        public void get() {
            System.out.println(gender);//女
            //访问外部类的t同名属性,则使用外部类名.this.属性名访问
            System.out.println(Person.this.gender);//男
        }
    }
}

 

 

四.静态内部类

1.什么是静态内部类?

——在外部类的成员位置上使用static又定义了一个类,这个类叫做静态内部类

 

2.静态内部类的格式

class 类名 {
    //属性和方法
    static class 类名 {
        //属性和方法
    }
}

 

3.一个小case快速了解静态内部类

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

class Person {
    //外部属性
    public int age;
    private char gender = '男';

    //静态内部类
    static class Teacher {
        public void get() {
            System.out.println("外部其他类访问成员内部类~");
        }
    }
}

 

4.静态内部类的细节讨论及实现

1)可以直接访问外部的所有静态成员(包含私有的),但不能访问非静态成员

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        //创建Teacher的实例对象
        Person.Teacher teacher = new Person.Teacher();
        teacher.get();
    }
}

class Person {
    //外部属性
    public static int age = 100;
    private char gender = '男';

    //静态内部类
    //可以直接访问外部的所有静态成员(包含私有的),但不能访问非静态成员
    static class Teacher {
        public void get() {
            //可以直接访问外部的所有静态成员(包含私有的)
            System.out.println(age);//100
            //不能访问非静态成员
            //System.out.println(gender);//错误,gender不是静态成员
        }
    }
}

2)可以添加任意的访问修饰符(public、protected、默认、private),静态内部类的本质是外部类的成员

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

class Person {
    //外部属性
    public static int age = 100;
    private char gender = '男';

    //静态内部类
    //可以添加任意的访问修饰符(public、protected、默认、private)
    public static class Teacher {}
    protected static class Stu {}
    static class Scientist {}
    private static class Colleague {}
}

3)作用域:整个类体均可使用

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        Person.Teacher teacher = person.getTeacher();
        teacher.get();
    }
}

class Person {
    //外部属性
    public static int age = 100;

    //静态内部类
    static class Teacher {
        public void get() {
            System.out.println("静态内部类的作用域是整个类体~");
        }
    }

    //作用域:整个类体均可使用
    public Teacher getTeacher() {
        return new Teacher();
    }
}

4)外部类访问静态内部类:创建对象进行访问

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.getResult();
    }
}

class Person {
    //外部属性
    public static int age = 100;

    //静态内部类
    static class Teacher {
        public void get() {
            System.out.println("外部类要创建对象才能访问静态内部类~");
        }
    }

    //外部类访问静态内部类:创建对象进行访问
    public void getResult() {
        Teacher teacher = new Teacher();
        teacher.get();
    }
}

5)外部其他类访问静态内部类:

        a.直接创建静态内部类进行访问

        b.让外部类提供public方法得到静态内部类实例,然后访问

public class Test {
    public static void main(String[] args) {
        //直接创建静态内部类进行访问
        Person.Teacher teacher = new Person.Teacher();
        teacher.get();
        //让外部类提供public方法得到静态内部类实例,然后访问
        Person person = new Person();
        Person.Teacher teacher1 = person.getInstance();
        teacher1.get();
    }
}

class Person {
    //外部属性
    public static int age = 100;

    //静态内部类
    static class Teacher {
        public void get() {
            System.out.println("外部其他类访问静态内部类~");
        }
    }

    //外部类访问静态内部类:创建对象进行访问
    public Teacher getInstance() {
        return new Teacher();
    }
}

6)若外部类和静态内部类的成员名相同时,按照就近原则访问,若要访问外部类的属性,则使用外部类名.属性名访问

public class Test {
    public static void main(String[] args) {
        Person.Teacher teacher = new Person.Teacher();
        teacher.get();
    }
}

class Person {
    //外部属性
    public static int age = 200;

    //静态内部类
    static class Teacher {
        public static int age = 100;

        public void get() {
            System.out.println(age);//100
            //若要访问外部类的属性,则使用 外部类名.属性名 访问
            System.out.println(Person.age);//200
        }
    }
}

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