内部类

内部类

一个简单的Demo

创建内部类时,首先需要有外部类对象

下面的代码中使用两种方式来创建内部类

public class TestSet {

	public static void main(String[] args) {
		// 第一种方式获取内部类
		TestSet testSet = new TestSet();
		TestSet.Test test1 = testSet.getTest();

		// 第二种方式获取内部类
		TestSet.Test test2 = new TestSet().new Test();
	}

	class Test {
	}

	public Test getTest() {
		return new Test();
	}
}

对象的传递

所有的内部类自动拥有对其外围类所有成员的访问权

在下面的例子中外部类有个属性outer且为私有类型,在内部类中直接对外部类的outer进行了赋值操作,通过两次打印输出,我们看到outer的值发生了变化。注意:内部类只是对外部类的方法和属性有访问权,但这些属性和方法只属于外部类。

public class TestSet {
	private int outer = 0;
	public static void main(String[] args) {
		TestSet testSet = new TestSet();
		System.out.println(testSet.outer);

		TestSet.Test test2 = testSet.new Test();
		System.out.println(testSet.outer);
	}

	class Test {
		public Test() {
			outer = 10;
		}
	}
}

内部类的继承与覆盖

子类可以继承父类的内部类(非private),但是内部类不存在覆盖的情况。因为内部类来自于不同的名字空间

class Contents {
	protected int i;
	class Test {
		{
			System.out.println("Contents.Test");
		}
	}
}

public class TestSet extends Contents {
	class Test {
		{
			System.out.println("TestSet.Test");
		}
	}
	public static void main(String[] args) {
		Contents contents = new TestSet();
		Contents.Test test = contents.new Test();
	}
}

上面的代码输出结果为Contents.Test

静态内部类

静态内部类也叫嵌套类,如果不需要内部类对象与外部类对象之间有联系,则可以将内部类声明为static。静态内部类对象不会隐式的持有外部类对象引用,所以静态内部不能直接使用外部类的非静态属性和方法。

public class TestSet {
	private int i = 0;
	static class Test {
		public Test() {
			// 无法访问TestSet的i成员
			// i = 10;
		}
	}
}

匿名内部类

匿名内部类是没有名字的内部类,先看一个demo:

interface Contents {

}

public class TestSet {
	public Contents contents() {
		return new Contents() {
			private int i = 0;
		};
	}

}

在上面的例子中,我们创建一个实现Contents接口的匿名类对象,通过new表达式返回的引用自动向上转型为Contents,由于匿名类没有名字,所以不能为其添加构造器。

class Contents {
	public Contents() {
	}
	public Contents(int x) {

	}
}

public class TestSet {
	public Contents getContents(final int x) {
		return new Contents(x) {
			private int i = x;
		};
	}
}

上面的代码中我们在创建匿名内部类对象时为其传入了参数x,这是因为基类Contents有个有参构造器。并且我们发现getContents方法的参数必须被final修饰,这是因为我们在匿名类内部访问了该参数(i = x)

如果我们想要在构造器中添加一些逻辑可以使用下面的方式,大括号中的内容会直接被添加到匿名类的构造函数中去

abstract class Contents {
	protected int i;
	public Contents() {

	}
	public Contents(int x) {

	}
}

public class TestSet {
	public Contents contents(final int x) {
		return new Contents(x) {
			{
				if (x > 0)
					i = 10;
				else
					i = x;
			}
		};
	}
}

小结

内部类丰富了多重继承的问题,可以通过内部类来达到继承多个基类的效果。如果在继承上有方法冲突,则可以用内部类解决

闭包

闭包是一个可以调用的对象,它不仅记录了自己的信息,而且还记录了一些来自于创建它的作用域的信息。内部类就是面向对象的闭包。它扩大了我们对域的访问范围。

posted @ 2017-05-08 23:14  被罚站的树  阅读(543)  评论(0编辑  收藏  举报