为什么需要内部类?
2013-08-24 13:25
218 查看
你已经看到了许多描述内部类的语法和语义,但是这并不能说明“为什么需要内部类?”。
那么,Sun 公司为什么会如此费心地增加这项基本的语言特性呢?
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类
的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。
内部类必须要回答一个问题是:如果我只是需要一个对接口的引用,为什么我不通过外围
类实现那个接口呢?答案是:“如果这能满足你的需求,那么你就应该这样做。”那么内
部类实现一个接口与外围类实现这个接口有什么区别呢?答案是你不是总能享用到接口带
来的方便,有时你需要与接口的实现进行交互,所以使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承
了某个(接口的)实现,对于内部类都没有影响。
如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很
难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,
而内部类有效地实现了“多重继承”。也就是说,内部类允许你继承多个非接口类型(译
注:类或抽象类)。
为了看到更多的细节,考虑下面这种情形,你必须在一个类中以某种方式实现两个接口。
由于接口的灵活性,你有两种选择:只使用单一的一个类,或者使用一个内部类:
//:c08:MultiInterfaces.java
// Two waysthat a class can implement multiple interfaces.
interface A {}
interface B {}
class X
implements A, B {}
class Y
implements A {
B makeB() {
// Anonymousinner class:
return new B() {};
}
}
public class MultiInterfaces {
static void takesA(A a) {}
static void takesB(B b) {}
public static void main(String[] args) {
X x = new X();
Y y = new Y();
takesA(x);
takesA(y);
takesB(x);
takesB(y.makeB());
}
} ///:~
当然,这里假设在两种方式下的代码结构都确实有逻辑意义。通常遇到问题的时候,问题
本身就能给出某些指引,告诉你应该使用单独一个类,或是使用内部类。但如果没有任何
其它限制,从实现的观点来看,前面的例子并没有什么区别。它们都能正常运作。
如果要继承的是抽象的类或具体的类,而不是接口,那你就只能使用内部类才能实现多重
继承。
//:c08:MultiImplementation.java
// Withconcrete or abstract classes, inner
// classes arethe only way to produce the effect
// of"multiple implementation inheritance."
package c08;
class D {}
abstract class E {}
class Z
extends D {
E makeE() { return new E() {}; }
}
public class MultiImplementation {
static void takesD(D d) {}
static void takesE(E e) {}
public static void main(String[] args) {
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
} ///:~
如果不需要解决“多重继承”的问题,你自然可以用别的方式编码,而不需要使用内部类。
但如果使用内部类,你还可以获得其他一些特性:
1. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对
象的信息相互独立。
2. 在单个外围类中,你可以让多个内部类以不同的方式实现同一个接口,或继
承同一个类。稍后就会展示一个这样的例子。
3. 创建内部类对象的时刻并不依赖于外围类对象的创建。
4. 内部类并没有令人迷惑的“is-a”关系;它就是一个独立的实体。
举个例子,如果Sequence.java 不使用内部类,你就必须要声明“Sequence 是一个
Selector”,对于一个特定的 Sequence 只能有一个 Selector。然而使用内部类你可以很
容易地就拥有另一个方法 getRSelector(),用来生成一个反方向遍历序列的 Selector。只
有内部类才有这种灵活性。
那么,Sun 公司为什么会如此费心地增加这项基本的语言特性呢?
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类
的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。
内部类必须要回答一个问题是:如果我只是需要一个对接口的引用,为什么我不通过外围
类实现那个接口呢?答案是:“如果这能满足你的需求,那么你就应该这样做。”那么内
部类实现一个接口与外围类实现这个接口有什么区别呢?答案是你不是总能享用到接口带
来的方便,有时你需要与接口的实现进行交互,所以使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承
了某个(接口的)实现,对于内部类都没有影响。
如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很
难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,
而内部类有效地实现了“多重继承”。也就是说,内部类允许你继承多个非接口类型(译
注:类或抽象类)。
为了看到更多的细节,考虑下面这种情形,你必须在一个类中以某种方式实现两个接口。
由于接口的灵活性,你有两种选择:只使用单一的一个类,或者使用一个内部类:
//:c08:MultiInterfaces.java
// Two waysthat a class can implement multiple interfaces.
interface A {}
interface B {}
class X
implements A, B {}
class Y
implements A {
B makeB() {
// Anonymousinner class:
return new B() {};
}
}
public class MultiInterfaces {
static void takesA(A a) {}
static void takesB(B b) {}
public static void main(String[] args) {
X x = new X();
Y y = new Y();
takesA(x);
takesA(y);
takesB(x);
takesB(y.makeB());
}
} ///:~
当然,这里假设在两种方式下的代码结构都确实有逻辑意义。通常遇到问题的时候,问题
本身就能给出某些指引,告诉你应该使用单独一个类,或是使用内部类。但如果没有任何
其它限制,从实现的观点来看,前面的例子并没有什么区别。它们都能正常运作。
如果要继承的是抽象的类或具体的类,而不是接口,那你就只能使用内部类才能实现多重
继承。
//:c08:MultiImplementation.java
// Withconcrete or abstract classes, inner
// classes arethe only way to produce the effect
// of"multiple implementation inheritance."
package c08;
class D {}
abstract class E {}
class Z
extends D {
E makeE() { return new E() {}; }
}
public class MultiImplementation {
static void takesD(D d) {}
static void takesE(E e) {}
public static void main(String[] args) {
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
} ///:~
如果不需要解决“多重继承”的问题,你自然可以用别的方式编码,而不需要使用内部类。
但如果使用内部类,你还可以获得其他一些特性:
1. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对
象的信息相互独立。
2. 在单个外围类中,你可以让多个内部类以不同的方式实现同一个接口,或继
承同一个类。稍后就会展示一个这样的例子。
3. 创建内部类对象的时刻并不依赖于外围类对象的创建。
4. 内部类并没有令人迷惑的“is-a”关系;它就是一个独立的实体。
举个例子,如果Sequence.java 不使用内部类,你就必须要声明“Sequence 是一个
Selector”,对于一个特定的 Sequence 只能有一个 Selector。然而使用内部类你可以很
容易地就拥有另一个方法 getRSelector(),用来生成一个反方向遍历序列的 Selector。只
有内部类才有这种灵活性。
相关文章推荐
- 为什么内部类访问的外部变量需要使用final修饰
- 【面试对宝典40题的解释】为什么从内部类中访问局部变量需要被声明为final最终类型
- 为什么需要内部类?
- Java之内部类(1) - 为什么需要内部类
- 为什么内部类访问的外部变量需要使用final修饰
- Java为什么匿名内部类参数引用需要用final进行修饰?
- 为什么需要内部类,内部类的作用
- Java 为什么需要内部类
- 为什么内部类访问的外部变量需要使用final修饰
- 内部类_为什么需要内部类 1.闭包与回调(笔记)
- java为什么需要内部类
- 为什么匿名内部类中引用的局部变量和参数需要final而成员字段不用?
- 内部类访问局部变量时,为什么需要加final关键字
- 为什么内部类访问的外部变量需要使用final修饰
- 为什么Java匿名内部类访问的外部局部变量或参数需要被final修饰
- 为什么需要内部类 ?
- 从头认识java-8.11 为什么需要内部类?(2)
- java中为什么需要内部类?
- 局部内部类访问外部变量为什么需要使用final修饰
- 为什么从内部类中访问局部变量需要被声明为最终类型