什么是内部类
将一个类的定义放在另一个类的内部,就称之为内部类
创建内部类
public class Parcel1 {
class Contents{
private int i = 11;
public int value(){return i;}
}
class Destination{
private String label;
Destination(String whereTo){
label = whereTo;
}
String readLabel(){return label;}
}
public Destination to(String s){
return new Destination(s);
}
public Contents contents(){
return new Contents();
}
public void ship(String dest){
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String args[]){
Parcel1 p = new Parcel1();
p.ship("Tasmania");
}
}
可以使外部类有一个方法,该方法返回一个指向内部类的引用,就像在to()和contents()方法
连接到外部类
内部类拥有其外围类的所有元素的访问权;
内部类的对象可以访问其外为对象的所有成员
.this与.new
- 1. .this可以生成对外部类的对象的引用
public class DotThis{
void f(){System.out.println("DoThis.f()");}
public class Inner{
public DotThis outer(){
return DotThis.this;
}
}
public Inner inner(){return new Inner();}
public static void main(String args[]){
DotThis dt = new DotThis();
DotThis.Inner dti = dt.inner();
dti.outer().f();//利用outer函数调用外部类对象
}
}
- 2. .new告知某些其他对象,去创建其某个内部类的对象;
public class DotNew{
public class Inner{}
public static void main(String args[]){
DotNew dn = new DotNew();
DotNew.Inner dni = dn.new Inner();//使用.new创建内部类对象
}
}
内部类的向上转型
将内部类向上转型为其基类,尤其是转型为一个接口时;内部类就有了用武之地;从实现了某个接口的对象,得到对此接口的引用,与向上转型为这个对象的基类,实质上是一样的;
- 创建以下接口
public interface Destination{
String readLabel();
}
public interface Contents{
int value();
}
class Parcel{
private class PContents implements Contents{
private int i = 11;
public int value(){return i;}
}
protected class PDestination implements Destination{
private String label;
private PDestination(String whereTo){
label = whereTo;
}
public String readLabel(){return label;}
}
public Destination destination(String s){
return new PDestination(s);
}
public Contents contents(){
return new PContents();
}
}
public class TestParcel{
public static void main(String args[]){
Parcel p = new Parcel();
Contents c = p.contents();
Destination d = p.destination("Tasmania");
}
}
在方法和作用域内的内部类
可以在一个方法或者一个作用域内部定义内部类;
有两个理由这么做:
1.实现了某个类型的接口,于是可以创建并返回对其引用
2.要解决一个问题,于是创建一个类来辅助解决方案,但又不希望这个类是公用的
可以这么做:
1.一个定义在方法中的类
2.一个定义在作用域内的类,此作用域在方法的内部
3.一个实现了接口的匿名类
4.一个匿名类,扩展了有非默认构造器的类
5.一个匿名类,执行了字段的初始化
6.一个匿名类,通过实例初始化实现构造(匿名类不可能有构造器)1.方法中的类
public class Parcel{
public Destination destination(String s){
class PDestination implements Destination{
private String label;
private PEestination(String whereTo){
label = whereTo;
}
public String readLabel(){return label;}
}
return new PDestination(s);
}
public static void main(String args[]){
Parcel p = new Parcel();
Destination d = p.destination("Tasmania");
}
}
- 2.嵌入作用域中的内部类
public class Parcel{
private void internalTracking(boolean b){
if(b){
class TrackingSlip{
private String id;
TrackingSlip(String s){
id = s;
}
String getSlip(){return id;}
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
}
public void track(){internalTracking(true);}
public static void main(String args[]){
Parcel p = new Parcel();
p.track();
}
}
匿名内部类
没有名字的类;作为实现了某个接口或基类的对象
public class Parcel{
public Contents contents(){
return new Contents(){//匿名类
private int i = 11;
public int value(){return i;}
};
}
public static void main(String args[]){
Parcel p = new Parcel();
Contents c = p.contents();
}
}
- 注意点:
1.若基类需要一个带有参数的构造器;则给匿名类一个参数:
public class Parcel{
public Wrapping wrapping(int x){
return new Wrapping(x){
//这个参数是提供给基类构造器的,匿名类中不能使用
public int value(){
return super.value()*47;
}
};
}
public static void main(String args[]){
Parcel p = new Parcel();
Wrapping w = p.wrapping(10);
}
}
Wrapping基类如下:
public class Wrapping{
private int i;
public Wrapping(int x){i = x;}
public int value(){return i;}
}
2.若希望匿名类可以使用一个定义在外部的对象,则需要将该参数声明为final;//代码太多懒得写了……
工厂方法
interface Service{
void method1();
void metiod2();
}
interface ServiceFactory{
Service getService();
}
class Implementation1 implements Servie{
private Implementation1(){}
public void method1(){
...
}
public void method2(){
...
}
public static ServiceFactory factory = new ServiceFactory(){
publc Service getService(){
return new Implementation1();
}
};
}
class Implementation2 implements Servie{
private Implementation1(){}
public void method1(){
...
}
public void method2(){
...
}
public static ServiceFactory factory = new ServiceFactory(){
publc Service getService(){
return new Implementation2();
}
};
}
public class Factories{
public static void serviceConsumer(ServiceFactory fact){
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String args[]){
serviceConsumer(Implemention1.factory);
serviceConsumer(Implemention2.factory);
}
}
嵌套类
将内部类声明为static;由此,内部类对象与外部类对象之间没有了联系
It means:
1.要创建嵌套类的对象,不需要其外部类的对象
2.不能从嵌套类的对象中访问非静态的外部类对象
普通的内部类的字段和方法只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段;也不能包含嵌套类
但是嵌套类就可以包含这些
public class Parcel{
private static class ParcelContents implements Contents{
private int i = 11;
public int value(return i;)
}
protected static class ParcelDestination implements Destination{
private String label;
private ParceDestination(String whereTo){
label = whereTo;
}
public String readLabel(){return label;}
public static void f(){
static int x = 10;
static class AnotherLevel{
public static void f(){}
static int x = 10;
}
}
public static Destination destination(String s){
return new ParcelContents();
}
public static Contents contents(){
return new ParcelContents();
}
public static void main(String args[]){
Contents c = contents();
Destination d = destination("Tasmania");
}
}
}
接口内部的类
用于进行测试
从多层嵌套类中访问外部类的成员
一个内部类无论被嵌套多少层,其依旧可以透明的访问所有它嵌入的外围类的所有成员
class MNA{
private void f(){}
class A{
private void g(){}
public class B{
void h(){
g();
f();
}
}
}
}
public class MultiNestingAccess{
public static void main(String args[]){
MNA mna = new MNA();
MNA.A mnaa = mna.new A();
MNA.A.B mnaab = mnaa.new B();
mnaab.h();
}
}
闭包和回调
package closure;
interface Incrementable{
void increment();
}
class MyIncrement{
public void increment(){System.out.println("Other operation");}
static void f(MyIncrement mi){mi.increment();}
}
class Callee1 implements Incrementable{
private int i = 0;
public void increment(){
i++;
System.out.println(i);
}
}
class Callee2 extends MyIncrement{
private int i = 0;
public void increment(){
super.increment();
i++;
System.out.println(i);
}
private class Closure implements Incrementable{
public void increment(){
Callee2.this.increment();
}
}
Incrementable getCallbackReference(){
return new Closure();
}
}
class Caller{
private Incrementable callbackReference;
Caller(Incrementable cbh){callbackReference = cbh;}
void go(){callbackReference.increment();}
}
public class Callbacks {
public static void main(String[] args){
Callee1 c1 = new Callee1();
Callee2 c2 = new Callee2();
MyIncrement.f(c2);
Caller caller1 = new Caller(c1);
Caller caller2 = new Caller(c2.getCallbackReference());
caller1.go();
caller1.go();
caller2.go();
caller2.go();
}
}
输出:
Other operation
1
1
2
Other operation
2
Other operation
3
内部类与控制框架
略
内部类的继承
eg:
class WithInner{
class Inner{}
}
public class InheritInner extends WithInner.Inner{
InheritInner(WithInner wi){
wi.super();//必须使用此句
}
public static void main(String args[]){
WithInner wi = new WithInner();
InheritInner ii = new InheritInner(wi);
}
}
内部类可以被覆盖吗
不能被覆盖的情况
class Egg{
private Yolk y;
protected class Yolk{
public Yolk(){
...
}
}
public Egg(){
...
y = new Yolk();
}
}
public class BigEgg extends Egg{
public class Yolk{
pubic Yolk(){...}
}
public static void main(String args[]){
new BigEgg();
}
}
能被覆盖的情况
必须使用extends
class Egg{
private Yolk y;
protected class Yolk{
public Yolk(){
...
}
}
public Egg(){
...
y = new Yolk();
}
}
public class BigEgg extends Egg{
public class Yolk extends Egg.Yolk{
pubic Yolk(){...}
}
public static void main(String args[]){
new BigEgg();
}
}
局部内部类与匿名类的区别
一个有名字一个没有名字
内部类标识符
Xxx&Xxx.java
资料:《Thking in java》