问:一个”.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的时候)。