eric-1001c

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  3 随笔 :: 45 文章 :: 12 评论 :: 0 Trackbacks

 

class Egg{
    
private Yolk y;
    
protected class Yolk{
        
public Yolk(){
            System.out.println(
"Egg.Yolk()");
        }

    }

    
public Egg(){
        System.out.println(
"new Egg()");
        y 
= new Yolk();
    }

}

//bigegg extend egg, and try "override" the yolk
public class BigEgg extends Egg{
    
public class Yolk{
        
public Yolk(){
            System.out.println(
"BigEgg.Ylok()");    
        }

    }

    
public static void main(String[] args) {
        
new BigEgg();
    }

}

内部类是一种非常有用的机制,它允许你把一些逻辑相关的类组织在一起,并控制位于内部类的可视性(进入修饰符和其它普通类元素没有区别)。同时内部类能够与外部类通信。利用内部类的特性可以使得写出的代码优雅而清雅。

1)内部类可以在内部进行使用,更典型的情况是在外部类设置一个方法返回一个指向内部类的引用
2)如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象(这个内部类必须是public),必须具体指明这个对象的类型:OuterClassName.InnerClassName;在new表达式中提供对其它外部类对象的引用,需要使用.new语法。


OutClass oc 
= new OutClass();
OutClass.InnerClass ocic 
= oc.new InnerClass();

这个例子也告诉我们,必须使用外部类的对象来创建内部类对象,不能直接创建内部类对象,因为它们之前必须建立一个联系(当然除了嵌套类--静态内部类)

3)内部类和制造它的外围对象之间有一种联系(对象创建一个内部类对象时,内部类对象会捕获一个指向那个外围类对象的引用),这种联系使得它能访问外围对象的所有成员,而不要任何特殊条件。此外,内部类还拥有其外围类的所有元素的访问权。(是不是可以把内部类看成外部类的一个元素,一个“特殊”的“类元素”)
如果需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this“.this”:

public class Outer{

   
public class Inner{
   
      
public Outer getOuter(){
         
return Outer.this;
      }


}

4) 当将内部类向上转型为其基类,尤其是转型为一个接口的时候,内部类就有了用武之地。这是因为内部类--某个接口的实现--能够完全不可见,并且不可用(将内部类进入修饰符设置为private或protected就可以了)。所得到的只是指向基类或接口的引用,所以能够很方便地隐藏实现细节,也完全阻止任何依赖于类型的编码
package chapter10;

interface Destination{
    String readLabel();
}

interface Contents{
    
int value();
}

class OuterInner{
    
//inner class1
    private class PDestination implements Destination{
        
private String label;
        
private PDestination (String whereto){
            label 
= whereto;
        }

        
public String readLabel() {
            
return label;
        }

    }
;
    
//inner class2
    protected class PContents implements Contents{
        
private int i = 11;
        
public int value() {
            
return i;
        }

    }
;
    
    
//method to ge the reference of the inner class pdestination and pcontent
//    notice that we return a interface instead of the implements of the interface
    public Destination getDestination(String s){
        
return new PDestination(s);
    }

    
public Contents getContents(){
        
return new PContents();
    }

}


public class InnerUpcast {

    
/**
     * 
@param args
     
*/

    
public static void main(String[] args) {
        OuterInner oi 
= new OuterInner();
//        we also use the interface as the type of the class instead of the inner class type
        Contents c =oi.getContents();
        Destination d 
= oi.getDestination("Hello");
    }


5) 同样的我们可以在任意一个方法中或作用域内创建一个内部类,除了要注意它(内部类)的使用作用域外,其它用法和在类的内部类用法无异。
6)匿名内部类:没有名字的,不能有构造器的类
interface Contents{
    
int value();
}

abstract class Base{
    
public abstract void f();
}

//use anonymous inner class as the vaule of return
//play your attendtion on that the value of return not only is a inner class
//but also it will be casted up as a interface, that's the amazing place
class OuterInner{
//  use interface as anonymous inner class
    public Contents getContents(){
        
return new Contents(){
            
private int i = 11;
            
public int value() {
                
return i;
            }

        }
;
    }

//    use abstract class as anonymous inner class
    public Base getBase(){
        
return new Base(){
            
public void f(){
                
//do something here
            }

        }
;
    }

}


public class AnonymousInner {
    
public static void main(String[] args) {
        OuterInner oi 
= new OuterInner();
        Contents c 
=oi.getContents();
        Base b 
= oi.getBase();
    }

}
匿名内部类既可以扩展类(抽象类),也可以实现接口,但不能两者兼备。如果匿名内部类要使用在其外部定义的对象,则要求该参数引用为final

7)要创建嵌套类(静态内部类)意味着:并不需要其外围类的对象;不能从嵌套类的对象中访问非静态的外围类对象。嵌套类与普通内部类还有一个区别:普通内部类的字段与方法只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类。但是嵌套类可以包含所有这些东西。
8)一个内部类被嵌套多少层并不重要,它能透明地访问所有它所嵌入的外围类的所有成员
9)“每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响”,这样的内部类特性使得其很多解决“多重继承”:
       a. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对象的信息相互独立(通过匿名内部类实现)
       b. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类(通过匿名内部类实现)
       c. 创建内部类对象的时候并不依赖于外围类对象的创建,并没有令人迷惑的“is-a”关系,它就是一个独立的实体

class PetSequence{
    String[] str 
=new String[]{"Rat","Manx","Cymric","Mutt","Pug"};
    
protected ArrayList<String> pets = new ArrayList<String>(
            Arrays.asList(str));
}


public class NonClollectionSequence extends PetSequence{
//    我们在这创建了3个方法,返回类型都是Iterable接口。但不同方法对Iterable接口的实现是不同的
//    使用匿名内部类很好的以不同的方式实现同一个接口,而且并不依赖于外围对象
    public Iterable<String> Iterator(){
        
return new Iterable<String>(){
            
public Iterator<String> iterator(){
                
return new Iterator<String>(){
                    
private int index = 0;
                    
public boolean hasNext(){
                        
return index< pets.size();
                    }

                    
public String next(){return pets.get(index++);}
                    
public void remove(){
                        
throw new UnsupportedOperationException();
                    }

                }
;
            }

        }
;
    }

    
    
public Iterable<String> reversed(){
        
return new Iterable<String>(){
            
public Iterator<String> iterator(){
                
return new Iterator<String>(){
                    
private int index = pets.size()-1;
                    
public boolean hasNext(){
                        
return index< pets.size();
                    }

                    
public String next(){
                        
return pets.get(index--);
                    }

                    
public void remove(){
                        
throw new UnsupportedOperationException();
                    }

                }
;
            }

        }
;
    }

    
    
public Iterable<String> randomized(){
        
return new Iterable<String>(){
            
public Iterator<String> iterator(){
                List
<String> shuffed = new ArrayList<String>(Arrays.asList(str));
                Collections.shuffle(shuffed, 
new Random(47));
                
return shuffed.iterator();
            }

        }
;
    }


    
public static void main(String[] args) {
        NonClollectionSequence s 
= new NonClollectionSequence();
        
for(String string: s.reversed())
            System.out.println(string);
        System.out.println();
        
for(String string2: s.randomized())
            System.out.println(string2);
    }

}

10)如果创建一个继承具有内部类的外围类的新类,并在新类中试图覆盖内部类,会发生什么呢?

当继承了某个外围类的时候,内部类并没有发生什么特别的神奇的变化。这两个内部类是完全独立的两个实体,各自在自己的命名空间内
11)内部类的标识符:外围类的名字,加上‘$’,再加上内部类的名字,比如OuterClass$InnerClass;对了匿名内部类,编译器会简单地产生一个数字作为其标识符,比如OuterClass$1
12)局部内部类VS匿名内部类
      a. 局部内部类可以提供一个构造器,方便重载构造器,而匿名内部类只能用于实例初始化
      b. 局部内部类可以被使用多次,然而匿名内部类只能实例化一次
posted on 2007-07-17 11:18 Eric-1001c 阅读(209) 评论(0)  编辑  收藏 所属分类: ThinkingInJava

只有注册用户登录后才能发表评论。


网站导航: