内部类的理解以及扩展

来源:互联网 发布:二手手机平台 知乎 编辑:程序博客网 时间:2024/06/02 02:38

作者:叁念


内部类

  • 在一个类的内部定义一种类型
  • 内部类仅仅是一个编译时的概念,一旦编译完成,就会变成两个完全不同的类

内部类分为四种

  1. 成员内部类
public class Outer {    public static void main(String[] args) {//      成员内部内创建对象方法        new Outer().new Inner();    }//  成员内部类    class Inner{    }}



以上代码编译后生成以下文件:(bin文件夹)


这里写图片描述

作为外部类的成员,可以直接使用外部类的所有成员方法和变量,即使是private的
同时外部类要访问内部类的所有成员属性和方法,则要通过获取内部类对象来获取

  • 成员内部类不能含有static变量和方法,因为成员内部类需要创建外部类对象,然后才能创建自己的
  • 在成员内部类引用外部类对象时,使用 Outer.this 表示外部类对象
  • 需要创建内部类对象时,可以使用 Outer.Inner obj = outer.new Outer.Inner();
public class Outer {    public static void main(String[] args) {//      成员内部内创建对象方法//          方法一//      Inner inner = new Outer().new Inner();//          方法二        Outer outer = new Outer();        Inner inner = outer.new Inner();//      调用内部类方法        inner.print("我是内部类成员");        inner.name = "成员内部类";        System.out.println(inner.name);        System.out.println(outer.name);    }//  外部类成员    public String name;    public void print(String str) {        System.out.println("外部类打印" + str);    }/** * 成员内部类 */    class Inner{        public String name;        public void print(String str) {            System.out.println("内部类打印" + str);//          调用外部类方法            Outer.this.print(str);            Outer.this.name = "我是外部类";        }    }}

2 . 局部内部类(方法内部类)

public class Outer {    public static void main(String[] args) {        getAnimal("麦克").eat();//      局部内部类不能再作用域外构造对象,如下两种都是是错误使用方法//      new Dog();//      new Outer().new Dog();    }    public static Animal getAnimal(final String name) {//      局部内部类        class Dog extends Animal {            @Override            public void eat() {                System.out.println(name + "狗在吃东西");            }        }        return new Dog();    }}class Animal {    public void eat() {        System.out.println("动物在吃东西");    }}



以上代码编译后生成以下文件:(bin文件夹)


这里写图片描述

内部类定义在方法或作用域内

  • 局部内部类也像别的类一样进行编译,但只是作用域不同而已
    只有在该方法或条件的作用域内可以使用,退出这些作用域之后是无法引用的
    当所在的方法的形参需要在内部类使用时,该参数必须是final

3.静态内部类

public class Outer {    public static void main(String[] args) {        // 构造静态内部类对象        Inner inner = new Outer.Inner();        System.out.println(Outer.Inner.add(3, 5));        System.out.println(Outer.Inner.inner);    }    public void print(String str) {        System.out.println("外部类打印" + str);    }    // 静态内部内    public static class Inner {        public static int inner = 5;        public static int add(int n1, int n2) {            return n1 + n2;        }    }}
  • 修饰为static的内部类,不需要内部类和外部类对象之间的联系
  • 就是说可以直接调用 Outer.Inner 引用到内部类
  • 既不用创建外部类对象,也不一定要创建内部类对象
  • 普通内部类不能有static方法和属性,也不能有静态内部类;但是静态内部类可以
  • 静态内部类不能使用任何外部非static的方法和变量
  • 静态内部类一般声明为public,里面的方法一般声明为public static,方便调用

4.匿名内部类
一个没有名字的类:

  • 不能加访问修饰符
  • new 匿名类,这个类或者接口必须是事先定义好的
  • 如果需要传参数,要么是本来的类就有可以传参数的构造器,或者可以用final的局部变量传递

内部类的继承:

  • 子类的构造方法中需要使用父类的外部类对象 . super()
  • 而这个父类的外部类对象需要从外面创建并传给形参
public class Outer {    public static void main(String[] args) {        System.out.println(getInnerObj().getName());    }    public static Inner getInnerObj() {        // 匿名内部类        return new Inner() {            @Override            public String getName() {                return "张三";            }        };    }}interface Inner {    String getName();}

public class Demo {    public static void main(String[] args) {        // 普通的狗        Dog dog = new Dog();        dog.eat();        // 突然看到一只狗        Dog dog1 = new Dog() {            @Override            public void eat() {                System.out.println("狗在吃草");            }        };        dog1.eat();    }}class Dog {    public void eat() {        System.out.println("狗在吃骨头");    }}
public class Demo {    public static void main(String[] args) {        // 普通的狗        Dog dog = new Dog();        dog.eat();        // 突然看到一只狗        Dog dog1 = new Dog("麦克") {            @Override            public void eat() {                System.out.println(name + "狗在吃草");            }        };        dog1.eat();    }}class Dog {    protected String name;    public Dog() {    }    public Dog(String name) {        this.name = name;    }    public void eat() {        System.out.println("狗在吃骨头");    }}