首页 > 代码库 > 内部类

内部类

内部类意义:

  更好的封装:比如cow类,内部定义一个cowleg类,cowleg类只有在cow类里才有意义,不允许其他类访问cowleg类

  内部类成员可以直接访问外部类的私有数据,但外部类不能访问内部类细节,如成员变量

  匿名内部类适合创建仅需要使用一次的类

  内部类比外部类多三个修饰符,private,protected,static,外部类不能使用这三个修饰符

  非静态内部类不能拥有静态成员

通过OuterClass.this.var 访问外部类成员

通过this.var 访问内部类成员

静态内部类:

  可以包含静态成员和非静态成员,根据静态成员不能访问非静态成员规则,静态内部类不能访问外部类的实例成员,只能访问类成员。即使是静态内部类的实例方法,也不能访问外部类的实例成员,只能访问静态成员。

  编译后class文件名称是:outerclass.class,outerclass$innerclass.class

局部内部类(鸡肋):

  把内部类放在一个方法里定义,这个内部类就是一个局部内部类。局部内部类仅在该方法里有效,所以也不能使用访问控制符合static修饰符。

  编译后class文件名称是:outerclass.class,outerclass$1innerclass.class  多了个数字,用于区分不同方法中同名的局部内部类

java8改进的匿名内部类:

  创建一个匿名内部类会立即创建一个该类的实例,这个类定义会立即消失,匿名内部类不能重复使用,格式:

  new 实现接口 | 父类构造器(实参列表){匿名内部类实体部分}

  匿名内部类必须实现一个接口或者继承一个父类,但两只只能取其一

  匿名内部类两个规则:

    匿名内部类不能是抽象类,因为系统在创建匿名内部类是,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义成抽象类

    匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器,但可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事

  最常用的创建匿名内部类的方式是需要创建某个接口类型的对象:

  写法:

  interface A{publice Double get();}

  class B{

    public void test(A a){a.get();}

    publice static void main(String[] args){

      B b = new B();

      b.test(new A(){public Double get(){...}});

    }

  }

  等同于

  class C implements A{public Double get(){...}}

  b.test(new C());   

  通过实现接口来创建匿名内部类时,匿名内部类不能显式的创建构造器,因此匿名内部类只有一个隐式的无参构造器,所以new 接口名后面的括号里不能有参数 w

  通过继承父类来创建匿名内部类时,匿名内部类有和父类相似的构造器,这里的相似指拥有相同的形参列表

  abstruct class A{public A(){}  public A(String str){}}

  class B{

    public void test(A a){a.get();}

    public static void main(String[] args){

      B b = new B();

      b.test(new A("asd"){...});  

java8改进点:

  java8前,要求局部内部类,匿名内部类访问的局部变量必须用final修饰,java8这个限制取消了,但是被访问的局部变量自动使用了final修饰,即别匿名内部类访问后,相当于final变量,不能再赋值

    }

  }

 

内部类