java 内部类,
分享于 点击 18962 次 点评:267
java 内部类,
</pre>一、内部类的定义<p></p><p><span > </span>可以将一个类的定义放在另一个类的定义的内部,这就是类。</p><p> <span > </span>内部类是一种非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并且控制位于内部的类的可视性。</p><p><span > </span>在最初,内部类看起来就像是一种代码隐藏机制:将类置于其他类的内部。但是,你将会了解到,内部类远不止这些,它了解外围类,并能与之通信;而且你用内部类写出的代码更优雅而清晰,尽管并不总是这样。</p><p> </p><p>1.1 创建内部类</p><p><span > </span>创建内部类的方式 就如同你想的一样-----把类的定义置于外围类的里面:</p><p></p><pre name="code" class="java"><pre name="code" class="java">//: innerclasses/Parcel1.class
// Creating inner classes
public class Parcel1{
class Contents{
private int i;
public int value() {return i;}
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() {return label;}
}
// Using inner class looks like using
// any othter classes,within Parel1
public void ship(String dest){
Contens c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tasmania");
}
}
当我们在ship()方法里面使用内部类的时候,与普通类没什么不同。在这里,实际的区别只是内部类的名字是嵌套在Parel1里面的。
更典型的情况是,外部类将有一个方法,该方法返回一个指向内部类的引用,就像在to()和contents()方法中看到的那样。
<pre name="code" class="java">//: innerclasses/Parcel2.class
// Returning a reference to an inner class
public class Parcel2{
class Contents{
private int i;
public int value() {return i;}
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() {return label;}
}
public Destination to(String s){
return new Destination(s);
}
public Contents contents(){
return new Contents();
}
public void ship(String dest){
Contents c = new Contents();
Destination d = to(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tasmania");
Parcel2 q = new Parcel2();
Parcel2.Contents c = q.contents();
Parcel2.Destination d = q.to("Borneo");
}
}
如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须像在main()方法中那样,具体地指明这个对象的类型:OuterClassName.InnerClassName.
</pre><pre name="code" class="java">1.2 链接到外部类
<span > </span>到目前为止,内部类似乎还只是一种名字隐藏和组织代码的模式。这些是很有用的,但还不是最引人注目的,它还有其他的用途。当生成一个内部类的对象时,此对象与制造它的外围对象之间就有了一种联系,所以它能访问其外围对象的所有成员,而不需要任何特殊条件。此外,内部类还拥有其外围类的所有元素的访问权。下面的例子说明了这一点:
<pre name="code" class="java">// :innerclasses/Sequence.class
// Holds a sequence of objects
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)
item[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(Interger.toString(i));
}
Selector selector = sequence.selector();
while(!selector.end()){
System.out.println(selector.current()+"");
selector.next();
}
}
}
Sequence类只是一个固定大小的Object的数组,以类的形式包装了起来。可以调用add()在序列末增加新的Object.要获取Sequence中的每一个对象,可以使用Selector接口。这是“迭代器”设计模式的一个例子。
这里,SequenceSelector是提供Selector功能的private类。可以看到,在main()中创建了一个 Sequence,并向其中添加了一些String对象。然后通过调用seletor()获取一个Selector,并用它在Sequence中移动和选择每一个元素。
最初看到SequenceSelector,可能会觉得它只不过是另一个内部类罢了。但仔细观察它,注意方法end()、current()和 next()都用到了Objects,这是一个引用,它并不是SequenceSelector的一部分,而是外围类中的一个Private字段。然而内部类可以访问其外围类的方法和字段,就像自己拥有它们似的,这带来了很大的方便。
所以内部类自动拥有对其外围类所有成员的访问权,这是如何做到的呢?当某个外围类的对象创建了一个内部类对象时,此内部类对象必定秘密地捕获一个指向那个外围类对象的引用。然后,在你访问此外围类的成员时,就是用这个引用来选择外围类的成员。幸运的是,编译器会帮你处理所有的细节,但你现在可以看到:内部类的对象只能
在与外围类的对象相关联的情况下才能被创建(就像你应该看到的,在内部类是非static类时)。构建内部类对象时,需要一个指向其外围类对象的引用,如果编译器访问不到这个引用就会报错。
</pre><pre name="code" class="java">
</pre><pre name="code" class="java">
</pre><pre name="code" class="java">
</pre><pre name="code" class="java">
</pre><pre name="code" class="java">
</pre>
相关文章
- 暂无相关文章
用户点评