内部类
内部类
一个简单的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;
}
};
}
}
小结
内部类丰富了多重继承的问题,可以通过内部类来达到继承多个基类的效果。如果在继承上有方法冲突,则可以用内部类解决
闭包
闭包是一个可以调用的对象,它不仅记录了自己的信息,而且还记录了一些来自于创建它的作用域的信息。内部类就是面向对象的闭包。它扩大了我们对域的访问范围。