定义:内部类是将类的定义放在另一个类的定义的内部
首先,内部类是一种非常有用的特性,允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性,但是内部类与组合是完全不同的概念;其次内部类了解外围类
,并能与之通信;而且用内部类写出的代码更加优雅而清晰。
但是内部类的定义与用法也是相当的复杂深奥,需要在不断地使用中熟悉之。
1,创建内部类
public class Parcel2{
class Contents{
private int i = 1;
public int value(){return i;}
}
public Contents contents(){
return new Contents();
}
public static void main(String[] args){
Parcel2 p = new Parcel2();
Parcel2.Contents c = q.contents();
Parcel2.Contents c2 = q.new Contents();
}
}
上述代码用了两种方法获得Contens的实例,第一种是通过Parcel2的contents方法获得对象,并且类型的声明用得是Parcel2.Contents这种形式而且只能是这种形式;第二种方
法是通过.new的形式实例化Contents对象;然而这两种方法的前提必须是外围类对象已经存在,这也说明内部类的存在必须依赖与外围类,在拥有外围类之前是不可能创建内部类对
象的(嵌套类除外)。
指明内部类对象的形式:OuterClassName.InnerClassName
2,使用.this来引用外围类的属性和方法
在内部类中的方法中编译器隐式地传递了外围类的this指针,显示引用方法:OuterClassName.this,这些无需程序员关心,编译器已经做的很好了。
3,利用内部类和接口实现迭代器的设计模式
//迭代器的共用接口
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 seq = new Sequence(10);
for(int i=0;i<10;i++){
seq.add(i.toString);
}
//获得迭代器
Selector selector = seq.selector();
//进行迭代
while(selector.end()){
System.out.println(selector.current());
selector.next();
}
}
}
4,匿名内部类:用new表达式直接生成继承或实现某个接口的类,类没有名字。需要注意的一点就是如果想在匿名类中使用外部定义的一个对象,编译器会要求期参数引用必须是
final,否则会出现编译错误
5,嵌套类:将内部类声明为static,这样嵌套类与其外围类对象之间就没有必然联系了。嵌套类意味着:○1要创建为嵌套类的对象,并不需要其外围类的对象。○2不能从嵌套类
的对象中访问非静态的外围类对象。
6,嵌套类与普通的内部类还有另外一个区别。普通内部类的属性和方法,只能放在类的外部层次上,所以普通的内部类不能有static属性和static数据,也不能包含嵌套类。
7,正常情况下,你不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,因为它是static的,只是将嵌套类放入接口的命名空间,这并不违反接口的规则
8,内部类的继承: 在对内部类进行继承时,必须在子类的构造方法中传入外部类的信息,我们必须在构造方法中添加这一句:enclosingClassReference.super();这样才能够通
过编译
9,内部类标识符:每个类都会产生一个.class文件,内部类也不例外,只不过这些类的命名有严格的规则:外围类的名字加上“$”再加上内部类的名字,如果内部类是匿名的,编译器会产生一个数字标识.