10 内部类 Innerclasses

  • 啥是内部类呢?

可以将一个类的定义放在另一个类的内部,这就是内部类。

这是一种代码隐藏机制

在外部类中有一个指向内部类引用的方法,可以用来构造内部类

Innerclass i = new Innerclass() ;

 

  • 如果想从外部类的非静态方法之外的任何地方创建某个内部类对象,就必须指明这个对象具体的类型,Outer.Inner

public Inner getInner() {

      return new Inner();

}

public void createInner() {

      Outer out = new Outer();

      Outer.Inner i = out.getInner();

}

inner方法是外部类的一个非静态方法,创建了一个内部类对象,用这种方法创建的时候必须指明Outer.Inner具体的类型

这是因为调用这个方法的时候,this指向一个具体的对象,而不是具体的类名,此时Inner这个类是找不到的,必须用

Outer.Inner才能找到

  • 内部类可以访问外部类的所有成员

当创建一个内部类的时候,这个内部类对象会秘密地捕获一个创建它的外部类对象的引用,并通过这个引用访问外部类对象的成

员,由此可见,每一个内部类对象必然对应唯一一个外部类对象(就是创建它的那个)

 

  • 使用.this和.new

在内部类中使用Outer.this访问当前对象对应的外部类对象

不能引用外部类的名字直接创建内部类对象,而是应该使用外部类对的对象来创建内部类对象,方法是

Outer out = new Outer();

Outer.Inner in = out.new Inner();

 

  • 将内部类向上转型为基类(接口)

如接口public interface Inner {}

class Outer {

      public ImplementInner implements Inner {}

      public static void main(String[] args) {

            Outer out  = new Outer();

            Inner in = out.new Inner();

            //从这里获取一个基类的引用

      }

}

 

  • 内部类可以定义在方法中 作用域中

内部类作为方法的一部分,就不能在方法以外访问了

可以if(b) {

      class A{}

}

并不是说if以外,这个类就不可用了,而是只要在在定义的方法以内,内部类就可用

 

  • 匿名内部类

public Inner getInner() {

      return new Inner() {};

}

作为返回值时,创建一个接口的实现类作为一个匿名内部类,最后要加一个分号

如果要传递参数也可以

class Wrapping {

      private int i;

      Wrapping(int x) { i = x; }

}

public Wrapping wrapping(int x) {

      return new Wrapping(x) {};

}

这里相当于执行了带参数构造器的语句,之后后面顺带了一个匿名内部类的定义,所以可以看成一个return语句,所以最后加了

分号

public Inner inner(final String str) {

      return new Inner() {

            public String s = str;

      }

}

在匿名类中定义字段时,还能够对其执行初始化操作,这里的参数必须是final的

在匿名类的基类内部添加构造器,就可以在创建匿名类时用调用基类构造器,此时的参数不必是final的,因为传递的参数是给基类

的构造器的,并不会直接在匿名内部类中被使用

 

  • 工厂设计模式与内部类结合

i假设有一个工厂接口,一个业务类接口,工厂类有一个生产业务类对象的方法,在业务类的某个具体实现中,加入一个静态方法,

用以返回一个工厂类实现的对象,该实现生产对应的业务类对象,这样就不需要去创建每一个业务类对应工厂类的具名类了

 

  • 嵌套类

静态的内部类,嵌套类相比普通的内部类,不需要对应一个建立它的外部类引用,同时嵌套类内部可以包含静态的数据和字段,以

及嵌套类,而普通内部类则不能包含这些成员

嵌套类可以直接写在接口中,并且可以直接写成接口的实现类的形式,并且,放到接口的任何类都自动是public和static的,如果你

想要创建一些公共代码,被一个接口的不同实现类所公用,可以使用在接口中创建嵌套类的方法

 

  • 为什么需要内部类

每个内部类都能独立地继承自一个接口的实现,所以无论外围类是否已经继承了某个接口的实现,对于内部类都没有影响

内部类使得多重继承的解决方案变得完整,它提供了可以继承多个具体的或抽象的类的能力

一个多重继承问题 比如一个类同时实现两个接口,这个时候使用单一类或者内部类都是可以的,因为单一类可以implements多个

类,当要实现具体的类或者抽象类的时候,就只能用上内部类了,因为单一类只能extends一个类

  • 内部类的其他特性

1.内部类可以有多个实例,每个内部类有自己的状态信息,并且与外部类的状态信息相互独立

2.在单个外部类中, 可以让多个内部类以不同的方式实现同一个接口,或继承同一个类

3.创建内部类的对象的时刻不依赖于外围类对象的创建

4.内部类没有“是一个”关系,它是一个独立的实体

内部类的继承

class WithInner {

      class Inner {}

}

 

class InheritInner extends WithInner.Inner {

      InheritInner(WithInner wi) { wi.super(); }

}

在构造器内部必须使用enclosingClassReference.super();的语法

  • 内部类的覆盖

当继承了某个外围类的时候,外围类和它的导出类中同名的内部类之间并不存在覆盖关系,可以看作是完全独立的两个类 

 

  • 局部内部类

通常写在一个方法体中,可以使用构造器,而不像匿名内部类只能使用实例初始化

  • 内部类标识符

内部类生成的.class文件名称

外围类名字+$+内部类名字.class

匿名内部类则是

外围类名称+$+数字.class

内部类的内部类,把名字跟在它的外围类和$后面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值