一、 Introduction
如果一个类中包含了另一个类,这个被包含的类就叫做内部类,包含了另一个类的类叫做外部类。根据内部类的出现的位置,可分为成员内部类和局部内部类。写在类的成员位置的类是成员内部类。成员内部类根据是否使用static,分为静态内部类和非静态内部类。
二、 非静态成员内部类
在内部类中,定义静态成员变量,要加final关键字。在内部类中,成员方法不能使用static修饰。在外部类的成员方法中,使用内部类。如果要使用内部类的成员,需要先先创外部类的对象,再去创建内部类的对象。如果是外部类的非静态成员方法使用内部类,说明已经创建了外部类的对象,所以可以直接使用内部类的对象。如果是静态成员方法,由于调用静态成员方法通过类名而不是外部类对象,所以在使用内部类的时候,需要先创建外部类的对象。
例子:
创建外部类及其内部类
public class Outer {
int a=1000;
class Inner{
int a=100;
static final int B=10;
public void show(){
int a=10;
System.out.println(a);
System.out.println(this.a);
System.out.println(Outer.this.a);
}
}
public voidfunc(){
Inner in=new Inner();
in.show();
}
public staticvoidfunc2(){
Outer o=new Outer();
Inner in=o.newInner();
//Inner in2=newOuter.new Inner();
System.out.println(in.a);
in.show();
}
}
测试内部类
public voidtest1(){
Outer o=new Outer();
Outer.Inner in=o.newInner();
System.out.println(in.a);
in.show();
o.func();
Outer.func2();
}
三、 静态成员内部类
静态成员内部类和外部类的对象无关,在调用上不需要先创建外部类的对象,在外部类的静态或者非静态成员方法中调用内部类上没有区别。在非外部类中,访问静态成员内部类的静态成员同普通类一样,直接通过类名访问,访问静态成员内部类的非静态成员,需要先创建静态成员内部类的对象。
创建静态成员内部类
public class Outer2 {
int a=1000;
static intb=100;
static classInner{
int a=100;
static int b=10;
void show(){
Outer o=new Outer();
System.out.println(o.a);
}
static void show2(){
System.out.println("bb");
}
}
static voidshow(){
//调用静态成员内部类中的静态成员属性
System.out.println(Inner.b);
//调用静态成员内部类中的静态成员方法
Inner.show2();
//调用静态成员内部类中的非静态成员属性或者方法
Inner in=new Inner();
System.out.println(in.a);
in.show();
}
void show2(){
//调用静态成员内部类中的静态成员属性
System.out.println(Inner.b);
//调用静态成员内部类中的静态成员方法
Inner.show2();
//调用静态成员内部类中的非静态成员属性或者方法
Inner in=new Inner();
System.out.println(in.a);
in.show();
}
}
测试静态成员内部类
public voidtest2(){
System.out.println(Outer2.Inner.b);
Outer2.Inner.show2();
Outer2.Inner in=new Outer2.Inner();
System.out.println(in.a);
in.show();
Outer2.show();
new Outer2().show2();
}
四、 私有成员内部类
使用private关键字修饰的内部类叫做私有成员内部类,私有成员内部类,只能在外部类里面使用。一般情况下,成员内部类都会私有化。
创建私有成员内部类
public class Outer3 {
private classInner{
int a=10;
}
public voidshow(){
System.out.println(new Inner().a);
}
}
测试
public voidtest3(){
Outer3 o=new Outer3();
o.show();
}
五、 局部内部类
定义在外部类的方法中的类,叫做局部内部类。局部内部类只能在这个包含这个局部内部类的方法中使用。
创建局部内部类
public class Outer4 {
int a=100;
static intb=10;
void show(){
int a=10;
final int c=100;
class Inner{
int a=1;
final static intb=100;
void show2(){
int a=1000;
System.out.println(a);
System.out.println(this.a);
System.out.println(new Outer4().a);
}
//在局部内部类中不能定义静态的成员方法。
/*static void show3(){
}*/
}
Inner i=new Inner();
System.out.println(i.a);
i.show2();
}
}
测试
public voidtest4(){
new Outer4().show();
}
六、 内部类的继承与实现,以及匿名内部类
比如Fu是一个类。newFu(){}就是表示创建父类的子类的对象。由于这个子类没有名字就称之为匿名内部类。然后.show();调用了匿名内部类的方法。
1. 创建一个父类
public class Fu {
public voidshow(){
System.out.println("这是父类");
}
}
创建一个带有继承的内部类和使用匿名内部类的类
public class Outer5 {
void show(){
class Inner extends Fu{
public void show() {
System.out.println("重新父类的方法");
}
}
Inner in=new Inner();
in.show();
//newInner().show();
new Fu(){
@Override
public void show() {
System.out.println("匿名内部类重写父类的方法");
}
}.show();
/*上述三种都调用了局部内部类,其中new Fu(){}采用的是匿名内部类的方式。
new Fu(){}就是表示创建父类的子类的对象。由于这个子类没有名字就称之为匿名内部类。
然后.show();调用了匿名内部类的方法。*/
}
}
测试
public voidtest5(){
new Outer5().show();
}
2. 使用抽象父类的子类的方法
创建一个抽象父类及其子类
public abstract class Fu2 {
public abstractvoidshow();
}
public class Zi extends Fu2{
public voidshow() {
System.out.println("实现抽象类");
}
}
3种方法调用抽象父类的子类
public voidtest6(){
//通过外部方法,使用父类的子类
test(new Zi());
//通过外部方法,使用父类的匿名内部类
test(new Fu2(){
public void show() {
System.out.println("使用父类的匿名内部类");
}
});
new Fu2(){
public void show() {
System.out.println("使用父类的匿名内部类.方法");
};
}.show();
}
public staticvoidtest(Fu2 f){
f.show();
}
3. 使用接口的实现类的方法
同样可以通过匿名内部类的方式,使用接口的实现类。
创建一个接口及其实现类。
public interface Inter {
public voidshow();
}
public class HH implements Inter{
public voidshow() {
System.out.println("实现了接口");
}
}
同样是3种方式实现对接口的实现类的使用
public voidtest7(){
//通过外部方法,直接创建接口的实现类的实例
testInter(new HH());
//通过接口的匿名内部类的方式
testInter(new Inter(){
public void show() {
System.out.println("通过接口的匿名内部类的方式");
}
});
new Inter(){
public void show() {
System.out.println("通过接口的匿名内部类的方式");
}
}.show();
}
public staticvoidtestInter(Inter i){
i.show();
}