内部类

发布于 2021-09-18  247 次阅读


1. 内部类

  • 成员内部类、静态内部类 、局部内部类、匿名内部类

1.1. 成员内部类

  • 成员内部类 定义位置: 外部类里里面 方法的外面 和成员变量的位置一样
  • 创建内部类对象的格式 外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
    • 也就是说:创建内部类对象,但必须先创建外部类对象

1.1.1. 代码

  • 类Outer中定义里一个内部类Inner,

  • 内部类里面可以直接访问外部类的成员, , 包括私有成员,比如下面show方法中 访问了外部的变量name

public class DEmo01 {
    public static void main(String[] args) {
        //创建外部类的对象
        Outer outer = new Outer();
        //System.out.println(outer.age);

        //外部类的对象来创建内部类的对象
        outer.new Inner();

        //创建内部类的对象
        Outer.Inner inner = new Outer().new Inner();

        //调用show方法
        inner.show();

    }
}

public class Outer {
    private String name = "xiaoming";
    int age = 20;

    class Inner {
        double weight = 200;

        //内部类里面可以直接访问外部类的成员, 包括私有成员
        public void show() {
            System.out.println(weight);
            System.out.println(name);
            System.out.println(age);
        }
    }
}

1.1.2. 私有成员内部类

  • 私有成员内部类 就像私有成员变量一样,在外面无法直接访问
代码
  • 这里通过外部类Outer的对象 调用了method方法, 访问了内部类里的成员
public class Test2Innerclass {
    /*
        私有成员内部类演示
     */
    public static void main(String[] args) {
        //私有成员内部类 就像私有成员变量一样,在外面无法直接访问
        // Outer.Inner oi = new Outer().new Inner();

       Outer outer = new Outer();
        //通过外部类的method方法 访问了内部类里的成员
        outer.method();
    }
}

class Outer {
    private  int age;

    //私有成员内部类
    private class Inner {
        public void show(){
            System.out.println("inner..show");
        }
    }

    public void method(){
        Inner i = new Inner();
        i.show();
    }
}

1.2. 静态成员内部类

  • 创建对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();

1.2.1. 代码

  • 访问静态内部类里的静态方法, 外部类名.内部类名.静态方法()
  • 静态内部类Inner里的show方法和eat方法中,不能访问外部非静态成员,只能访问静态的
public class Test3Innerclass {
    /*
        静态成员内部类演示
     */
    public static void main(String[] args) {
        // 外部类名.内部类名 对象名 = new 外部类名.内部类名();
        Outer.Inner oi = new Outer.Inner();
        oi.show();

        //访问静态内部类里的静态方法
        Outer.Inner.method();
    }
}

class Outer {

    int age;
    static String name = "halon";

    public static void method() {
        System.out.println(name);
        //System.out.println(age);//不能调用非静态的
    }

    static class Inner {
        int height = 30;

        public void show() {
            System.out.println(height);
            method();
            System.out.println(name);
            //System.out.println(age);//不能调用外部类的非静态的
        }

        public static void eat() {
            System.out.println("吃");
             System.out.println(num);
            //System.out.println(name);//不能调用外部类的非静态的
        }
    }
}

1.2.2. 非静态内部类不能有静态成员(jdk16之前)

代码

  • Inner类中不能有静态的变量和静态的方法

1659942234704

1.2.3. 静态的内部类不能访问外部的非静态的成员员

  • 静态内部类Inner不能访问外部的非静态变量num
class Outer {
    int num = 10;

    static class Inner {
        public void show() {
            //静态内部类 不能访问外部的非静态成员
           // System.out.println(num);
        }

        public static void method() {
            System.out.println("inner..method");
        }
    }
}

1.3. 局部内部类

1.3.1. 代码

  • 类Inner定义在method方法里,也只能在method方法内部使用
public class Test4Innerclass {
    /*
        局部内部类:
            编写位置: 方法中
            访问方式: 只能在方法中, 创建对象并访问
     */
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

class Outer {

    int a = 10;
    public void method() {
        int b = 20;
        class Inner {
            public void show() {
                System.out.println("show...");
                System.out.println(a);
                System.out.println(b);
            }
        }
        Inner i = new Inner();
        i.show();
    }

}

1.4. 外部类.this (内部类里访问外部类变量)

  • 在内部类访问外部的成员
  • 如下代码中 show方法里Outer.this.age
public class Demo01 {
    public static void main(String[] args) {
        //外部类名.内部类名 对象名 = new 外部类名.内部类名();
        Outer.Inner inner = new Outer().new Inner();
        inner.show();
    }
}

class Outer {
    int age = 10;
    public void eat() {
        System.out.println(this.age);
    }

    class Inner {
        int age = 20;

        public void show() {
            int age = 30;
            System.out.println(age);
            System.out.println(this.age);
            System.out.println(Outer.this.age);
        }
    }
}

1.5. 匿名内部类

1.5.1. 匿名内部类的前提

  • 存在一个普通类或者抽象类或者接口

1.5.2. 语法

new 类名/接口名 (){
    重写方法
};

1.5.3. 匿名内部类的本质

  • 本质:是一个继承了该类或者实现了该接口的匿名子类的对象

1.5.4. 案例1:用接口

接口代码

interface Inter {
    void show();
}

实现代码

  • 这个过程的理解
    • 1 创建了一个实现了Inter的类,是匿名的
    • 2 实现了接口的方法,写在大括号内
    • 3 创建了这个实现类的对象
    • 4 用这个对象调用了实现的show方法
new Inter() {
    @Override
    public void show() {
        System.out.println("我是匿名内部类中的show方法");
    }
}.show();

1.5.5. 案例2:用接口

接口代码

interface Inter2 {
    void show1();
    void show2();
}

实现代码

  • 这个过程的理解
    • 1 创建了一个实现了Inter1的类,是匿名的
    • 2 实现了接口的方法show1和show2,写在大括号内
    • 3 创建了这个实现类的对象,赋值给了变量i
    • 4 用这个对象i,调用了实现的show1方法和show2方法
public class Demo02 {
    public static void main(String[] args) {
        Inter1 i1 = new Inter1() {
            @Override
            public void show1() {
                System.out.println("show1");
            }

            @Override
            public void show2() {
                System.out.println("show2");
            }
        };
        i1.show1();
        i1.show2();
    }
}

1.5.6. 案例3:用抽象类

抽象类代码

abstract class Animal {
    abstract void eat();

    public void drink() {
        System.out.println("喝点豆浆");
    }
}

实现代码

  • 这个过程的理解
    • 1 创建了一个继承了Animal的子类,是匿名的
    • 2 实现了Animal类的方法eat和drink,写在大括号内,这里drink不强制重写
    • 3 创建了这个子类的对象,赋值给了变量a
    • 4 用这个对象a,调用了实现的eat方法和drink方法
public class Demo01 {
    public static void main(String[] args) {
        Animal a = new Animal() {
            @Override
            void eat() {
                System.out.println("吃猫粮");
            }

            @Override
            public void drink() {
                System.out.println("喝雪碧");
            }
        };
        start(a);

        start(new Animal() {
            @Override
            void eat() {
                System.out.println("吃鱼食");
            }
        });

    }

    public static void start(Animal a) {
        a.eat();
        a.drink();
    }
}

1.5.7. 案例4:用普通类

类代码

public class Animal {
    public void jump() {
        System.out.println("大跳");
    }
}

实现代码

  • 这个过程的理解
    • 1 创建了一个继承了Animal1的子类,是匿名的
    • 2 实现了Animal类的方法jump,写在大括号内,这里jump不强制重写
    • 3 创建了这个子类的对象,赋值给了变量a1
public class Demo01 {
    public static void main(String[] args) {
        Animal a1 = new Animal() {
            @Override
            public void jump() {
                System.out.println("重写了跳跃方法");
            }
        };
        a1.jump();

        //创建了Animal的对象
        new Animal();
        //创建了Animal的子类的对象
        new Animal(){};
    }
}

1.6.1. 匿名内部类的应用

1.6.1. 案例

接口代码

package com.heima.test13;

/*
    游泳接口
 */
interface Swimming {
    void swim();
}

实现代码


class Person implements Swimming {
    @Override
    public void swim() {
        System.out.println("自由泳");
    }
}

package com.heima.test13;

public class Demo01 {
    public static void main(String[] args) {
//        方案1
        //创建Person对象
        Person p01 = new Person();
        //传入对象 去游泳
        goSwim(p01);

        //方案2
        Swimming swimming = new Swimming() {
            @Override
            public void swim() {
                System.out.println("蛙泳");
            }
        };
        goSwim(swimming);
        //方案3
        goSwim(new Swimming() {
            @Override
            public void swim() {
                System.out.println("蝶泳");
            }
        });

    }

    //去游泳, 传入Swimming接口的实现类对象
    public static void goSwim(Swimming s) {
        s.swim();
    }
}
如人饮水,冷暖自知。
最后更新于 2023-07-18