内部类

1、创建内部类:

内部类:即该类位于一个类的内部。典型的情况是,外部类中有一个方法,可以返回一个指向内部类的引用,如果需要具体指明这个对象的类型,需要使用OuterClassName.InnerClassName。

2、链接到外部类:

内部类可以访问其外围对象的所有成员,包括private修饰的成员变量或者方法。典型的代码如下:

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 SequeneSelector implements Selector{

		private int i = 0;
		@Override
		public boolean end() {
			// TODO Auto-generated method stub
			return i == items.length;
		}

		@Override
		public Object current() {
			// TODO Auto-generated method stub
			return items[i];
		}

		@Override
		public void next() {
			// TODO Auto-generated method stub
			if(i < items.length)
				i++;
		}
	}
	public Selector selector(){
		return new SequeneSelector();
	}

	public static void main(String[] args){
		Sequence sequence = new Sequence(10);
		for(int i=0; i < 10; i++){
			sequence.add(i);
		}
		Selector selector = sequence.selector();
		while(!selector.end()){
			System.out.print(selector.current()+" ");
			selector.next();
		}
	}	
}

这段代码很有价值:

1、说明了内部类可以访问到外部类的所有的元素。

2、介绍了一种“迭代器”方法,这个需要在《Head First设计模式》好好读一读。

同时需要注意的是:当内部类是static类型的情况下,内部类依赖于外部类的存在而存在,因此在构建内部类的情况下,需要一个指向其外围类对象的引用。

3、使用.this和.new

如果需要在内部类中返回对外部类的引用,需要使用 外部类.this 来返回。参见以下代码:

public class Outer {
	void print(){
		System.out.println("Outer print");
	}
	public class Inner{
		public Outer getOuter(){
			return Outer.this;
		}
	}
	public Inner inner(){
		return new Inner();
	}
	public static void main(String[] args){
		Outer outer = new Outer();
		Outer.Inner inner = outer.inner();
		inner.getOuter().print();
	}
}

如果需要在内部类定义的外部类以外的地方生成内部类,需要使用 外部类.new 的方法来生成。参见以下代码:

public class TestOuter {
	public static void main(String[] args){
		Outer outer = new Outer();
		Outer.Inner inner = outer.new Inner();
		inner.getOuter().print();
	}
}

这个地方要注意的是,必须使用外部类的对象来创建内部类。在拥有外部类的对象之前,不能创建内部类。当前,如果内部类是静态static的(即嵌套类),那是可以需要外部类的引用的。

4、匿名内部类

interface Contents{
	String value();
}

public class AnonymousClass {
	public Contents contents(final String conent){
		return new Contents() {
			private String label = conent;
			@Override
			public String value() {
				// TODO Auto-generated method stub
				return label;
			}
		};
	}
	public static void main(String[] args){
		System.out.print(new AnonymousClass().contents("Test").value());
	}
}

如上代码所示,匿名内部类返回了一个继承自Contents的匿名类的对象。需要注意的是,如果传入的变量需要在匿名类内部直接使用的话,那么函数参数要求必须是final修饰的,即不允许匿名类来修改。但如果不是在匿名类中直接使用,那么是可以不需要final修饰的。

需要注意的是:匿名内部类既可以扩展类,也可以扩展接口,但不能两者皆有,而且如果扩展接口的话,只允许扩展一个。

5、匿名内部类与工厂函数

匿名内部类和工厂函数是很好的搭配在一起,参见下面的程序

interface Game{
	boolean move();
}
interface GameFactory{
	Game getGame();
}

class Checkers implements Game{
	private Checkers(){}
	private int moves = 0;
	private static final int MOVES = 3;
	public boolean move(){
		System.out.println("Checkers move " + moves);
		return ++moves != MOVES;
	}
	public static GameFactory factory = new GameFactory() {

		@Override
		public Game getGame() {
			// TODO Auto-generated method stub
			return new Checkers();
		}
	};
}

class Chess implements Game{
	private Chess(){}
	private int moves = 0;
	private static final int MOVES = 4;

	@Override
	public boolean move() {
		// TODO Auto-generated method stub
		System.out.println("Chess move " + moves);
		return ++moves != MOVES;
	}

	public static GameFactory factory = new GameFactory() {

		@Override
		public Game getGame() {
			// TODO Auto-generated method stub
			return new Chess();
		}
	};

}

public class Games {
	public static void playGame(GameFactory factory){
		Game game = factory.getGame();
		while(game.move()){};
	}

	public static void main(String[] args){
		playGame(Checkers.factory);
		playGame(Chess.factory);
	}

}

运行结果为

Checkers move 0
Checkers move 1
Checkers move 2
Chess move 0
Chess move 1
Chess move 2
Chess move 3

 6、嵌套类

嵌套类,即使用了static修饰的内部类。由于使用了static修饰,因此以下两个问题需要注意:

1、要创建嵌套类的对象,不需要其外围类的对象

2、嵌套类中,不能访问非静态的外部类对象。

普通的内部类,不能有static修饰的变量或者方法,也不能包含嵌套类。但是嵌套类可以包含这些东西。同样的嵌套类中也么有.this指向外部类。

7、接口内部的类

普通情况下,接口内不能放置任何代码,但是嵌套类可以作为接口的一部分。放到接口中的任何类都是pubilc static的

8、为什么使用内部类

每个内部类都能够独立的继承自一个接口的实现,所以无论外围类是否已经继承了某个类或者接口的实现,对于内部类没有影响。

 

About: happyhls


发表评论

电子邮件地址不会被公开。 必填项已用*标注