一、 内部类的概念
1) 在一个类中定义另外一个类,这个类就叫做内部类或内置类(innerclass)。
2) 内部类可以让我们将逻辑上相关的一组类组织起来,并由外部类(outerclass)来控制内部类的可见性。
3) 当我们建立一个innerclass时,其对象就拥有了与外部类对象之间的一种关系,这是通过一个特殊的thisreference形成的,使得内部类对象可以随意的访问外部类中所有的成员。
二、 内部类的分类
1) 内部类包括成员内部类与局部内部类,成员内部类又分为实例内部类与静态内部类
2) 实例内部类
a) 在创建实例内部类时,外部类的实例必须已经存在。
参考代码:
classTestInstanceInner
{
classTestInner
{
publicintadd(inta,intb)
{
returna+b;
}
};
publicstaticvoidmain(String[]args)
{
TestInnerinner=newTestInstanceInner().newTestInner();
intresult=inner.add(3,5);
System.out.println(result);
}
1) 在一个类中定义另外一个类,这个类就叫做内部类或内置类(innerclass)。
2) 内部类可以让我们将逻辑上相关的一组类组织起来,并由外部类(outerclass)来控制内部类的可见性。
3) 当我们建立一个innerclass时,其对象就拥有了与外部类对象之间的一种关系,这是通过一个特殊的thisreference形成的,使得内部类对象可以随意的访问外部类中所有的成员。
二、 内部类的分类
1) 内部类包括成员内部类与局部内部类,成员内部类又分为实例内部类与静态内部类
2) 实例内部类
a) 在创建实例内部类时,外部类的实例必须已经存在。
参考代码:
classTestInstanceInner
{
classTestInner
{
publicintadd(inta,intb)
{
returna+b;
}
};
publicstaticvoidmain(String[]args)
{
TestInnerinner=newTestInstanceInner().newTestInner();
intresult=inner.add(3,5);
System.out.println(result);
}
}
b) 实例内部类的实例自动持有外部类的实例的引用
publicclass TestInstanceInner2
{
privateinta1=3;
publicinta2=5;
staticinta3=7;
publicintadd(inta,intb)
{
returna+b;
}
classTestInner2
{
intb1=a1;
intb2=a2;
intb3=a3;
intb4=newTestInstanceInner2().add(3,5);
intb5=newTestInstanceInner2().a1;
b) 实例内部类的实例自动持有外部类的实例的引用
publicclass TestInstanceInner2
{
privateinta1=3;
publicinta2=5;
staticinta3=7;
publicintadd(inta,intb)
{
returna+b;
}
classTestInner2
{
intb1=a1;
intb2=a2;
intb3=a3;
intb4=newTestInstanceInner2().add(3,5);
intb5=newTestInstanceInner2().a1;
}
publicstaticvoidmain(String[]args)
{
TestInstanceInner2.TestInner2inner2=newTestInstanceInner2().newTestInner2();
System.out.println(inner2.b1);
System.out.println(inner2.b2);
System.out.println(inner2.b3);
System.out.println(inner2.b4);
System.out.println(inner2.b5);
}
}
c) 外部类实例与内部类实例之间是一对多的关系,一个内部类实例只会引用一个外部类实例,一个外部类实例可以对应多个内部类实例
publicclassA
{
classB
{
privateintb1=1;
publicintb2=2;
classC{};
};
publicvoidtest()
{
//intv1=b1;
// intv2=b2;
// B.Cc1=newC();
Bb=newB();
intv1=b.b1;
B.Cc1=b.newC();
B.Cc2=newB().newC();
publicstaticvoidmain(String[]args)
{
TestInstanceInner2.TestInner2inner2=newTestInstanceInner2().newTestInner2();
System.out.println(inner2.b1);
System.out.println(inner2.b2);
System.out.println(inner2.b3);
System.out.println(inner2.b4);
System.out.println(inner2.b5);
}
}
c) 外部类实例与内部类实例之间是一对多的关系,一个内部类实例只会引用一个外部类实例,一个外部类实例可以对应多个内部类实例
publicclassA
{
classB
{
privateintb1=1;
publicintb2=2;
classC{};
};
publicvoidtest()
{
//intv1=b1;
// intv2=b2;
// B.Cc1=newC();
Bb=newB();
intv1=b.b1;
B.Cc1=b.newC();
B.Cc2=newB().newC();
}
publicstaticvoidmain(String[]args)
{
Aa=newA();
a.test();
}
}
d) 在实例内部类中不能定义静态成员,而只能定义实例成员。
publicstaticvoidmain(String[]args)
{
Aa=newA();
a.test();
}
}
d) 在实例内部类中不能定义静态成员,而只能定义实例成员。
e) 如果实例内部类B与外部类A包括同名的成员(比如成员变量v),那么在类B中,this.v表示类B的成员,a.this.v表示类A的成员。
3) 静态内部类
a) 静态内部类实例不会自动持有外部类的特定实例的引用,在创建内部类的实例时不必创建外部类的实例
classA2
{
publicstaticclassB2
{
intv=3;
}
publicstaticvoidmain(String[]args)
{
A2.B2b2=newA2.B2();
System.out.println(b2.v);
}
}
b) 静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,就必须通过外部类的实例去访问。
classA3
{
privateinta=3;
privatestaticintb=5;
publicstaticclassB3
{
//intv=a;
intv1=b;
}
publicstaticvoidmain(String[]args)
{
A3.B3b3=newA3.B3();
System.out.println(b3.v1);
}
}
c) 在静态内部类中可以定义静态成员和实例成员
d) 客户类可以通过完整的类名直接访问静态内部类的静态成员。
4) 局部内部类
a) 局部内部类是在方法中定义的内部类,它的可见范围是当前方法,不能有访问修饰符(public,private,protected,static)
b) 局部内部类只能在当前方法中使用
classA4
{
//Bb=newB();
publicvoidmethod()
{
classB
{
intv1;
intv2;
}
Bb1=newB();
}
3) 静态内部类
a) 静态内部类实例不会自动持有外部类的特定实例的引用,在创建内部类的实例时不必创建外部类的实例
classA2
{
publicstaticclassB2
{
intv=3;
}
publicstaticvoidmain(String[]args)
{
A2.B2b2=newA2.B2();
System.out.println(b2.v);
}
}
b) 静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,就必须通过外部类的实例去访问。
classA3
{
privateinta=3;
privatestaticintb=5;
publicstaticclassB3
{
//intv=a;
intv1=b;
}
publicstaticvoidmain(String[]args)
{
A3.B3b3=newA3.B3();
System.out.println(b3.v1);
}
}
c) 在静态内部类中可以定义静态成员和实例成员
d) 客户类可以通过完整的类名直接访问静态内部类的静态成员。
4) 局部内部类
a) 局部内部类是在方法中定义的内部类,它的可见范围是当前方法,不能有访问修饰符(public,private,protected,static)
b) 局部内部类只能在当前方法中使用
classA4
{
//Bb=newB();
publicvoidmethod()
{
classB
{
intv1;
intv2;
}
Bb1=newB();
}
}
c) 局部内部类同实例内部类一样,不能包含静态成员。
d) 局部内部类同实例内部类一样,可以访问外部类的所有成员,此外,局部内部类还可以访问所在方法中的final类型的参数和变量。
classA5
{
c) 局部内部类同实例内部类一样,不能包含静态成员。
d) 局部内部类同实例内部类一样,可以访问外部类的所有成员,此外,局部内部类还可以访问所在方法中的final类型的参数和变量。
classA5
{
publicvoidmethod(finalinta,intb)
{
intp1=3;
finalintp2=6;
classB
{
intv1=a;
//intv2=b;
//intv3=p1;
intv4=p2;
}
Bb1=newB();
}
{
intp1=3;
finalintp2=6;
classB
{
intv1=a;
//intv2=b;
//intv3=p1;
intv4=p2;
}
Bb1=newB();
}
}
三、 匿名内部类
a) 匿名内部类没有构造方法,但是会调用父类的构造方法。
classA6
{
三、 匿名内部类
a) 匿名内部类没有构造方法,但是会调用父类的构造方法。
classA6
{
A6()
{
System.out.println("defaultconstructor");
}
voidmethod()
{
System.out.println("fromA");
}
publicstaticvoidmain(String[]args)
{
A6a6=newA6()
{
voidmethod()
{
System.out.println("fromanonymous");
}
};
a6.method();
}
}
b) 匿名内部类虽然没有构造函数但是可以在匿名内部类中提供一段实例初始化代码,Java虚拟机在调用父类构造函数之后调用它。
c) 除了可以在外部类的方法内定义匿名类以外,还可以在声明一个成员变量时定义内部类。
abstractclassA7
{
A7a7=newA7()
{
voidmethod()
{
System.out.println("inner");
}
};
abstractvoidmethod();
}
d) 匿名类除了可以继承类以外还可以实现接口。
四、 内部类的继承
一个外部类继承了另外一外部类的内部类,每个外部类的实例必须自动引用这个外部类的实例
publicclassTest
{
inta=5;
classInner
{
publicvoidprint()
{
System.out.println(a);
}
};
publicstaticvoidmain(String[]args)
{
Testtest=newTest();
Samplesample=newSample(test);
sample.print();
}
};
//一个外部类继承了另外一外部类的内部类,每个外部类的实例必须自动引用这个外部类的实例
classSampleextendsTest.Inner
{
publicSample(Testt)
{
t.super();
}
};
五、 子类与父类的内部类同名
publicclassOuter
{
Innerinner;
Outer()
{
inner=newInner();
}
publicclassInner
{
publicInner()
{
System.out.println("Outer'sInner");
}
};
publicstaticvoidmain(String[]args)
{
SubOuter.InnersubOuterInner=newSubOuter().newInner();
Outer.InnerouterInner=newOuter().newInner();
}
};
classSubOuterextendsOuter
{
classInner
{
publicInner()
{
System.out.println("subOuter'sInner");
}
};
};
六、 为什么使用内部类
1)在内部类(innerclass)中,可以随意的访问外部类的成员,这可以让我们更好地组织管理我们的代码,增强代码的可读性。
2)内部类可以用于创建适配器类,适配器类是用于实现接口的类。使用内部类来实现接口,可以更好地定位与接口关联的方法在代码中的位置。
{
System.out.println("defaultconstructor");
}
voidmethod()
{
System.out.println("fromA");
}
publicstaticvoidmain(String[]args)
{
A6a6=newA6()
{
voidmethod()
{
System.out.println("fromanonymous");
}
};
a6.method();
}
}
b) 匿名内部类虽然没有构造函数但是可以在匿名内部类中提供一段实例初始化代码,Java虚拟机在调用父类构造函数之后调用它。
c) 除了可以在外部类的方法内定义匿名类以外,还可以在声明一个成员变量时定义内部类。
abstractclassA7
{
A7a7=newA7()
{
voidmethod()
{
System.out.println("inner");
}
};
abstractvoidmethod();
}
d) 匿名类除了可以继承类以外还可以实现接口。
四、 内部类的继承
一个外部类继承了另外一外部类的内部类,每个外部类的实例必须自动引用这个外部类的实例
publicclassTest
{
inta=5;
classInner
{
publicvoidprint()
{
System.out.println(a);
}
};
publicstaticvoidmain(String[]args)
{
Testtest=newTest();
Samplesample=newSample(test);
sample.print();
}
};
//一个外部类继承了另外一外部类的内部类,每个外部类的实例必须自动引用这个外部类的实例
classSampleextendsTest.Inner
{
publicSample(Testt)
{
t.super();
}
};
五、 子类与父类的内部类同名
publicclassOuter
{
Innerinner;
Outer()
{
inner=newInner();
}
publicclassInner
{
publicInner()
{
System.out.println("Outer'sInner");
}
};
publicstaticvoidmain(String[]args)
{
SubOuter.InnersubOuterInner=newSubOuter().newInner();
Outer.InnerouterInner=newOuter().newInner();
}
};
classSubOuterextendsOuter
{
classInner
{
publicInner()
{
System.out.println("subOuter'sInner");
}
};
};
六、 为什么使用内部类
1)在内部类(innerclass)中,可以随意的访问外部类的成员,这可以让我们更好地组织管理我们的代码,增强代码的可读性。
2)内部类可以用于创建适配器类,适配器类是用于实现接口的类。使用内部类来实现接口,可以更好地定位与接口关联的方法在代码中的位置。
【知识点】接口的规范
【知识点】接口的规范
1) 接口中所有的方法都是public abstract。
2) 在接口中声明方法时,不能使用native、static、final、synchronized、private、 protected等修饰符。
3) 和public类一样,public接口也必须定义在与接口同名的文件中。
4) 接口中可以有数据成员,这些成员默认都是public static final。
5) 一个接口可以继承自另一个接口。
6) Java中不允许类的多继承,但允许接口的多继承。
7) 在Java中,一个类可以实现多个接口。
8) 一个类在继承另外一个类的同时,可以实现多个接口。