以下是学习内部类的几个知识点:
1. 内部类的属性
内部类能访问外围对象的所有成员,而不需要任何特殊条件
Thinking in Java的解释:当外围类对象创建一个内部类对象时,此内部类对象会”秘密的”捕获一个指向那个外围类对象的引用,当你在访问外围类的成员时,就是用那个引用来选择外围类的成员
2. 使用.this和.new
注意:
在拥有外部类对象之前是不可能创建内部类对象的,因为内部类对象会秘密连接到创建它的外部类对象上
public class Test2 {
public static void main(String[] args) {
Test2 test = new Test2();
// 因为内部类Inner属于Test2,所以需要用Test2的实例去调用Inner
// 利用.new来创建Inner的实例
Test2.Inner inner = test.new Inner();
inner.getTest2();
}
public class Inner {
public Test2 getTest2() {
// 获取的是执行getTest2方法的对象,即一个Inner类的实例
// return this;
// 利用.this返回外部类对象的引用
return Test2.this;
}
}
}
3. 匿名内部类”构造器”
匿名类的内部不可能有命名构造器,因为它没有名字,但是’实例初始化’能有构造器的效果,下面代码中的”注意”
public class Test2 {
public static void main(String[] args) {
getA();
}
public static A getA() {
return new A() {
// 注意
{
System.out.println("son: A");
}
@Override
public int f() {
return 0;
}
};
}
}
abstract class A {
A() {
System.out.println("father: A");
}
abstract int f();
}
输出:
father: A
son: A
4. 内部类参数的final修饰
// 如果匿名内部类中使用参数,那参数应该用final修饰
public class Test2 {
public static void main(String[] args) {
getA(47);
}
public static A getA(final int i) {
return new A(i) {
{
System.out.println("son: A" + i);
}
@Override
public int f() {
return 0;
}
};
}
}
abstract class A {
A(int i) {
System.out.println("father: A" + i);
}
abstract int f();
}
// 如果匿名内部类中没有使用参数,那参数不用final修饰
public static A getA(int i) {
return new A(i) {
{
System.out.println("son: A");
}
@Override
public int f() {
return 0;
}
};
}
5. 内部类使用的例子:工厂模式
public class Test2 {
// 生产service的方法
public static void serviceConsumer(ServiceFactory sf) {
Service s = sf.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(Impl1.factory);
serviceConsumer(Impl2.factory);
}
}
// 待生产的实体
interface Service {
void method1();
void method2();
}
// 生产Service的工厂
interface ServiceFactory {
Service getService();
}
// Service的一个实现
class Impl1 implements Service {
// 生成Impl1的工厂
public static ServiceFactory factory = new ServiceFactory() {
@Override
public Service getService() {
return new Impl1();
}
};
private Impl1() {
}
@Override
public void method1() {
System.out.println("Impl1 method1");
}
@Override
public void method2() {
System.out.println("Impl1 method2");
}
}
// Service的一个实现
class Impl2 implements Service {
// 生产Impl2的工厂
public static ServiceFactory factory = new ServiceFactory() {
@Override
public Service getService() {
return new Impl2();
}
};
private Impl2() {
}
@Override
public void method1() {
System.out.println("Impl2 method1");
}
@Override
public void method2() {
System.out.println("Impl2 method2");
}
}
6. 嵌套类
static修饰的内部类
普通内部类中不能有static修饰的属性,除了static final修饰的
注意:
要创建嵌套类的对象,并不需要其外围类的对象
不能从嵌套类的对象中访问非静态的外围类对象
7. 多层嵌套内部类
一个内部类被嵌套多少层都可以透明的访问所有它嵌入的外围类的所有成员
public class Test2 {
private void test2() {
}
class A {
private void a() {
}
class B {
void b() {
test2();
a();
}
}
}
}
8. 为什么使用内部类?
实现”多继承”
public class Test2 {
abstract class B {
}
// 多继承:classA相当于继承了classTest2和classB
class A extends Test2 {
B getB() {
return new B() {
};
}
}
}
9. 内部类的继承
内部类的构造器必须连接到指向其外部类对象的引用,
继承内部类的时候,指向外部类对象的”秘密的”引用必须被初始化,而在导出类不再存在可连接的默认对象。
因此,使用特殊的语法。下面代码的”注意”
public class Test2 extends Outer.Inner {
// No enclosing instance of type Outer is available due to some
// intermediate constructor invocation
// Test2() {
// }
// 注意
Test2(Outer o) {
o.super();
}
public static void main(String[] args) {
}
}
class Outer {
class Inner {
}
}
10. 内部类的覆盖
不同外围类有同名的内部类,这样的内部类属于不用的类
// Outer1.Inner和Outer2.Inner是两个不同的类,Inner都在各自的命名空间中
class Outer1 {
class Inner {
}
}
class Outer2 {
class Inner {
}
}