第10章 内部类

来源:互联网 发布:power point软件下载 编辑:程序博客网 时间:2024/05/20 14:26

基础知识

  • 内部类感觉就像是一种代码的隐藏机制。内部类了解外部类,并且能与之通信。

  • 内部类和组合完全是不同的概念

  • 内部类能够访问外围对象的所有的成员,而不需要任何特殊条件。内部类还有其外围类所有元素 (子段、方法)的访问权。(原因:当某个外围类对象创建了一个内部类的对象的时候,此内部类对象必定会秘密的捕获一个指向那个外围类对象的引用)

  • 在拥有外部类对象之前是不可能创建内部类对象的。这是因为内部类对象会暗暗的连接到它的外部类对象上

  • 如果创建的是嵌套类(静态内部类),那么它就不需要对外部类对象的引用

  • 可以在一个 方法 里面或者在 任意的作用域 内定义内部类(很有意思,虽然不常用)

  • 匿名类是不可能有构造器的

  • 内部类编译过的类名的特点:外部类$内部类.class,如果内部类是匿名的,编译器产生一个数字作为其标志符

  • 外部类存在的原因:每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。(其实也就是解决了多重继承的问题)

  • -

代码

-如果想在外部类的非静态方法之外的任意位置创建某个内部类对象则:

public class Parcel2 {  class Contents {    private int i = 11;    public int value() { return i; }  }  public Contents contents() {    return new Contents();  }  public void ship(String dest) {//该方法返回内部类对象的引用    Contents c = contents();  }  public static void main(String[] args) {    Parcel2 p = new Parcel2();    p.ship();    Parcel2 q = new Parcel2();    Parcel2.Contents c = q.contents(); //重要  }} 
  • 如果想要生成对外部类对象的引用,则使用 外部类名字.this
public class DotThis {  void f() { System.out.println("DotThis.f()"); }  public class Inner {    public DotThis outer() {      return DotThis.this; //重要    }  }  public Inner inner() { return new Inner(); }  public static void main(String[] args) {    DotThis dt = new DotThis();    DotThis.Inner dti = dt.inner();    dti.outer().f(); //重要  }} 
  • 创建内部类对象的方法:
public class DotNew {  public class Inner {}  public static void main(String[] args) {    DotNew dn = new DotNew();    DotNew.Inner dni = dn.new Inner(); //重要(使用外部类对象创建内部类对象)  }}
  • 当将内部类向上转型为基类或者接口,能够很方便的隐藏实现的细节(这叫内部类和向上转型)
class Parcel4 {  private class PContents implements Contents {//重要    private int i = 11;    public int value() { return i; }  }  public Contents contents() {    return new PContents();  }}public class TestParcel {  public static void main(String[] args) {    Parcel4 p = new Parcel4();    Contents c = p.contents();  //重要    // Illegal -- can't access private class:    //! Parcel4.PContents pc = p.new PContents(); //重要  }} 
  • 如果定义一个匿名的内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求参数引用是 final
public class Parcel9 {  public Destination destination(final String dest) {  //重要    return new Destination() {      private String label = dest;      public String readLabel() { return label; }    };  }  public static void main(String[] args) {    Parcel9 p = new Parcel9();    Destination d = p.destination("Tasmania");  }} 
  • 如果不需要内部类对象与其外围类对象有关系,那么可以将内部类声明为 static ,这通常叫做 嵌套类。

  • 普通的内部类对象隐式的保存了一个引用,指向创建它的对象。但是static的时候,就不是这样:

    • 要创建的嵌套类对象,并不需要其外围类的对象。
    • 不能从嵌套类的对象中访问非静态的外围类对象 (重要)
public class Parcel11 {  private static class ParcelContents implements Contents {    private int i = 11;    public int value() { return i; }  }  public static Contents contents() {    return new ParcelContents();  }  public static void main(String[] args) {    Destination d = destination();  }} 
  • 接口中一般是不能放置任何的代码的,但是 嵌套类 可以作为接口的一部分。接口中的任何类都 自动 的是public static 类型的:
public interface ClassInInterface {  void howdy();  class Test implements ClassInInterface {    public void howdy() {      System.out.println("Howdy!");    }    public static void main(String[] args) {      new Test().howdy();    }  }}