《java编程思想》第十章 内部类

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

10.1创建内部类

OuterClassName。InnerClassName

 10.2链接到外部类

内部类能访问外围对象的所有成员,而不需要任何特殊条件。此外内部类还拥有其外部类的所有元素的访问权。包括private

原因:当某个外围类的对象创建了一个内部类对象时,此内部类对象必定会秘密的捕获一个指向那个外围类对象的引用。然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员。

10.3 使用.this和.new

1).this

如果你需要生产对外部类对象的引用,可以说还有外部类的名字后面紧跟圆点和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();
   }
}

输出   DotThis.f()

2).new

告知某些其他对象,去创建其某个内部类的对象,必须在new表达式中提供对其他外部类对象的引用,需要使用.new。

public class DotNew {
    public   class Inner {}

    public static viod main(String [] args){

   DotNew  dn =new DotNew();

   DotNew.Inner dni =dn.new Inner();

   }

}

 必须先声明外部类,才能创建内部类。除非是静态内部类,则不需要创建外部类。

10.4内部类与向上转型

 10.5在方法和作用域内的内部类

1)在方法的作用域内(而不是在其他类的作用域内)创建一个完整的类,叫做局部内部类。

2)在同一个子目录下的任意类中对某个内部类使用已有的局部内部类,并不会产生命名冲突。

10.5 匿名内部类

public class Paecel{

    public Contents contents(){
        return new Contents(){ 

        private  int i=11;

        public int  value() {return i;}

      };

   }

  public static void main(String[] args){

      Parcel p=new Parcel();

      Contents c=p.contents();

   }

}

这种奇怪的语法指的是:“创建一个继承自Contents的匿名类的对象。”通过new表达式返回的引用自动向上转型为Contents的引用。

其中的   匿名内部类末尾的分号,并不是标记内部类的结束,标记的是表达式的结束。

如果定义一个匿名内部类,并且希望使用一个外部定义的对象,那么编译器会要求其参数引用是final的。如果不使用,那么可以不是final。

匿名内部类没有构造器,因为没有名字,但是通过实例初始化,可以创建一个构造器的效果。

对于匿名内部类而言,实例初始化的实际效果就是构造器。当然,他受到了限制——你不能重载实例初始化方法,所以你只能有一个这样的“构造器”。

匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以拓展类,也可以实现接口,但是两者不能兼备。如果是实现接口,也只能实现一个接口。   10.6工厂方法

10.7嵌套类

如果不需要内部类对象与其外围类对象之间有联系,那么可以将内部类声明为static。这通常称为嵌套类。

普通的内部类对象隐私的保存了一个引用,指向创建他的外围类对象,然鹅,当内部类是static的时,就不说这样了。

嵌套类意味着:

①要创建嵌套类的对象 ,并不需要其外围类对象。

②不能从嵌套类的对象中访问非静态的外围类对象。

嵌套类和普通内部类还有一个区别。普通内部类的字段和方法,只能放在类的外部层次上,所有普通内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以包含这些东西。

 

10.7.1接口内部的类

正常情况下,不能再接口内部放置任何代码,但是嵌套类可以作为接口的一部分。你放到接口的任何类都自动的是public 和static 的,因为类是static的,只是将嵌套类置于接口的命名空间内,这听不违反接口的原则。你甚至可以在内部类中实现其外围接口。

 

10.7.2从多层嵌套类中访问外部类的成员

内部类可以多层嵌套。

class A {

 class B{

  class c{}

 }

}

10.8为什么需要内部类

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

内部类允许继承多个非接口类型(类或抽象类)

10.8.1 闭包和回调

10.8.2内部类和框架控制

10.9内部类的继承

10.10内部类可以被覆盖吗

“覆盖”内部类就像它是外围类的一个方法,并不起什么作用。

10.11 局部内部类

局部内部类不能有访问说明符,因为它不是外围类的一部分;但是它可以访问当前代码块的常量,以及此外围类的所有成员。

局部构造器的名字在方法外是不可见的。为什么我们要选择局部内部类而且不是匿名内部类,因为需要一个已命名的构造器,或者是需要重载构造器,而匿名内部类只能用于实例初始化。

所以使用局部内部类而不使用匿名内部类的另一个理由就是,需要不只是一个该内部类的对象。

10.12内部类标识符

内部类也会生成.class文件,以包含他们的Class对象信息。命名规则 外围类的名字+“$”,+内部类的名字 A$B.class。

如果内部类是匿名的,编译器会简单的产生一个数字作为其标识符。如果内部类是嵌套在别的内部类中,只需要直接将他们的名字加载器外围类标识符与$后面。

 

 

 

 

 

 

posted @ 2019-05-18 15:46  夜雨敲墙  阅读(323)  评论(0编辑  收藏  举报