黑马程序员_基础复习07_内部类

  ------- android培训java培训、期待与您交流! ---------- 

内部类:

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

  内部类可以控制他自己的可视性,并且内部类可以和外部类进行通信。

1、内部类的访问规则:

外部类要访问内部类,必须建立内部对象,也可以写一个方法,该方法返回一个指向内部类的引用。

内部类具有访问外部类的所有元素的访问权。

interface Selector{

  boolean end();

  Object current();

  void next();

}

public class Sequence {

   private Object[] items;

   private int next = 0;

   public Sequence(int size){

    items = new Object[size];

  }

  public void add(Object x){

   if(next < items.length)

    items[next++] = x;

  }

private class SequenceSelector implements Selector{

  private int i =0;

  public boolean end(){

     return i == items.length;//内部类中可以访问外部类成员,直接使用

  }

  public Object current(){

    return items[i];

  }

  public void next(){

    if(i < items.length)

      i++;

  }

}

 public Selector selector(){

   return new SequenceSelector();//返回一个指向内部类的引用

 }

 public static void main(String[] args) {

   Sequence sequence = new Sequence(10);

   for (int i = 0; i < 10; i++) {

     sequence.add(Integer.toString(i));

   }

   Selector selector = sequence.selector();

   while(!selector.end()){

     System.out.print(selector.current() + " ");

     selector.next();

   }

 }

}

从上例中,我们看到内部类中可以访问外部类中的方法和字段,就好像自己拥有它们似的,这给程序的设计带来了很大的方便。

 

如果在内部类中生成一个对外部类的引用,格式为:外部类名.this

而在main函数中建立内部类对象时,比如有一个外部类Outer,和内部类Inner,我们在创建内部类对象时,格式如下

 Outer out = new Outer();

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

 如果外部类中有方法返回内部类引用getInner(),我们可以这么创建

 Outer out = new Outer();

 Outer.Inner in = out.getInner();

2、在方法和作用域内的内部类

在方法的作用域中的内部类,被称为局部内部类。 

局部内部类不可以被成员修饰符修饰。

局部内部类可以直接访问外部类的成员,因为还持有外部类中的引用,但不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。(局部变量不能被privatestatic修饰)。

局部内部类不能在该方法外被访问。

在任意作用域中创建的内部类,只能在此作用域中使用。

3、匿名内部类

Class Contents{

  int value(){};

}

public class Parcel5 {

   public Contents contents(){

     return new Contents(){//匿名内部类

        private int i = 11;

        public int value(){ return i;}

     };

   }

   public static void main(String[] args) {

    Parcel5 p = new Parcel5();

    Contents c = p.contents();

  }

}

上面这个例子中的contents()方法中,返回一个Contents类型的对象,而我将返回值的生成与表示这个返回值的类的定义结合在一起。这就是匿名内部类。

定义匿名内部类的前提:内部类必须是继承一个类或者实现一个接口。

匿名内部类的格式: new 父类/接口(){定义子类的内容}

有一个约定俗成的说法:匿名内部类中定义的方法最多不能超过三个,否则不用此方式建内部类。

注意:如果匿名内部类要使用一个在其外部定义的对象时,这个参数引用必须定义成final的,否则编译会报错。

下例说明这一点:

interface Destination{

   String readLabel();

}

public class Parcel10 {

  public Destination 

        destination(final String dest,final float price){

     return new Destination() {

       private int cost;

       {

         cost = Math.round(price);

         if(cost >100)

           System.out.println("Over budget!");

       }

       private String label = dest;

       public String readLabel() {

         return label;

       }

     };

  }

  public static void main(String[] args) {

 

    Parcel10 p = new Parcel10();

    Destination d = p.destination("Tasmania", 101.45F);

  }

}

因为destprice在匿名内部类中会用到,所有要定义成final的。

4、嵌套类

如果不需要内部类对象与外部类对象之间有联系,就可以将内部类声明为static。这称为嵌套类。普通的内部类对象隐式地保存了一个引用,指向创建它的外部类对象。而,如果内部类是static时,意味着嵌套类:

 1)要创建嵌套类对象,不需要外部类对象。

 2)不能从嵌套类对象中访问非静态的外部类对象。

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

5、使用内部类的作用

   1)实现“多重继承”

   2)内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对象的信息相互独立。

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

   4)创建内部类对象的时刻,不依赖于外部类对象的创建

   5)内部类并没有令人迷惑的“is a”关系,是一个独立的实体。

;