問:一個”.java”源文件是否可以包含多個類(不是內部類)?有什麼限制?
一個java源文件中可以有多個類,但只能有一個public類,並且public的類名必須和文件名保持一致。
關於內部類
顧名思義,將一個類的定義放在另一個類的定義內部,這就是內部類。
創建內部類
public class Test{
//inner calss
class Contents{
private int i=11;
public int value(){return i;}
}
class Destination{
private String label;
Destination(String whereTo){
label=whereTo;
}
String readLabel(){return label;}
}
public void ship(String dest){
Contents c=new Contents();
Destination d=new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args){
Test t=new Test();
t.ship("Hello world!");
}
}
運行結果:
Hello world!
當我們在ship()方法中使用內部類的時候,與使用普通類並沒有什麼區別,實際的區別只是內部類的類名是嵌套在Test類中的。但是,這並不是唯一的區別。
public class Test{
//inner class
class Contents{
private int i=11;
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=new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args){
Test t=new Test();
t.ship("Hello world!");
//Defining references to inner classes
Test t1=new Test();
Test.Contents c=t1.contents();
Test.Destination d=t1.to("Borneo");
}
}
如果你需要從外部類的非靜態方法之外的任意位置創建某個內部類的對象,那麼必須像在main()方法中一樣,具體指明這個對象的類型:OutClassName.InnerClassName。
鏈接到外部類
當生成一個內部類的對象的時候,此對象和製造它的外圍對象之間就有了一種聯繫,所以它能訪問其外圍對象的所有成員,而不需要任何特殊條件。除此之外,內部類還擁有其外圍類的所有元素的訪問權。
interface Selector{
boolean end();
Object current();
void next();
}
public class Test{
private Object[] items;
private int next=0;
public Test(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){
Test test=new Test(10);
for(int i=0;i<10;i++){
test.add(Integer.toString(i));
}
Selector selector=test.selector();
while(!selector.end()){
System.out.print(selector.current()+" ");
selector.next();
}
}
}
運行結果:
0 1 2 3 4 5 6 7 8 9
上例代碼中,Test類只是一個固定大小的Object的數組,以類的形式包裝了起來而已。可以調用add()方法在數組末尾在還有空間的前提下增加新的Object。
要獲取Test數組中的每一個元素,就可以依賴Selector接口來實現。(這是“迭代器”設計模式的一個例子。)
Selector接口允許檢查數組是否到達了末尾——end();或者訪問當前對象——current();或者訪問序列中的下一個對象——next()。
這裏SequenceSelector是提供Selector功能的private類。可以看到,在main()方法中,先創建了一個Test對象,並向其中添加了一系列String對象。然後通過Selector類中的selector()方法獲取一個Selector,並用它訪問Test中的數組元素。
對於SequenceSelector類,可能你只覺得它是一個內部類而已,但是仔細閱讀代碼,就會發現,在方法end()、next()、current()中都用到了object,這是一個引用,並不是SequenceSelector類的一部分,而是外部類Test的一個private字段。然而內部類可以訪問其外部類的方法和字段,就像是自己擁有一樣。
所以內部類自動擁有對其外部類所有成員的訪問權。
內部類的對象只能在與其外部類相關聯的情況下才能被創建(在內部類是static的時候)。