一、内部类的概念
所谓内部类(Inner Class),顾名思义,就是将一个类定义在另一个类的内部。
内部的类称之为内部类
pubic class Outer{
class Inner{
//省略
}
}
内部类的主要特点:
内部类可以很好的实现隐蔽,可以使用protected private修饰符
内部类可以直接访问外部类的所有成员,包括私有成员
外部类不能直接访问内部类的成员,必须首先建立内部类的对象才能访问
内部类可以很好的实现隐蔽,可以使用protected private修饰符:
里面的类可以做成private供外面的类使用
成员内部类及应用
成员内部类属于外部类的实例成员,成员内部类可以有public private default protected权限修饰符。在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方法” 和 “外部类名.this.成员属性”的形式
创建成员内部类的实例使用“外部类名.内部类名 实例 = 外部类实例名.new 内部类构造方法(参数)” 的形式
(内部类其实也分好几种,成员内部类其实是其中经常用的一种使用方式)
新建一个工程
那我们做一个内部类,一个类里面又有一个类
那我们如何使用呢?比如我现在要调用System.out.println("内部类打印");如何调用
创建成员内部类的实例使用“外部类名.内部类名 实例 = 外部类实例名.new 内部类构造方法(参数)” 的形式
先要把外部化实例出来
Outer o = new Outer();
外部类名.内部类名 实例 = 外部类实例名.new 内部类构造方法(参数)
Outer. Inner test = o .new Inner();
这样才能调用test 里面的InnerPrint();
运行结果
也就是说你调用内部类里面的某个方法,必须先提供一个外部类的对象,先实例化一个外部类的对象,然后通过已经存在的对象调用new,通过已经存在的对象,来创建一个内部类的实例
所以先要有外部类的对象,才能有内部类的对象
最终才能调用内部类对象的函数去做一些事情
成员内部类属于外部类的实例成员,成员内部类可以有public private default protected权限修饰符。在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方法” 和 “外部类名.this.成员属性”的形式
我们看一下能不能在void InnerPrint() 调用 void printData()
外部类名.this.成员方法
Outer .this. printData();
运行结果
那我能不能在内部类访问外部类的变量 第12行
我实例化的时候给data加上一个初值 o.data=100;
运行结果
那么外部类可不可以访问内部类里面的东西呢?
外部类不能直接访问内部类的成员,必须首先建立内部类的对象才能访问
不可以上面这样用,需要先建立内部类的对象才能访问
Inner i = new Inner();
运行结果
修改一下
运行结果
一般来说在内部类去访问外部类的变量或函数 多一点
外部类访问内部类没什么特别大的意义
二、匿名内部类及应用
匿名内部类的特点:
· 匿名内部类是没有名称的内部类,没有办法引用他们。必须在创建的时,作为new语句的一部分来声明并创建他们的实例
· 匿名内部类必须继承一个类(抽象的,非抽象的都可以)或者实现一个接口,所有父类(或者父接口)是抽象类,则匿名内部类必须实现其所有抽象方法
语法:实例
new interface/superclass(){类体}
这种形式的new 语句声明一个新的匿名类,它对一个给定的类进行拓展,或者实现一个给定的接口,并同时创建改匿名类的一个新实例
’
我们前面写的内部类有个Inner和Outer,Inner就是内部类的名称,匿名内部类是没有这个东西的
那匿名内部类是干什么的?没办法给他赋个属性
int data;
没办法实现里面的方法体
void InnerPrint(){
System.out.println("内部类打印");
Outer.this.printData();
System.out.println("外部类data="+Outer.this.data);
}
新建一个工程,匿名内部类其中的一个用法就是一个抽象类
我们new 一个Demo1它会有错误
Cannot instantiate the type Demo1
不能初始化Demo1
什么时候可以呢?我们即初始化它,又实现里面的方法
这就不是我们说的真正意义上的实例化Demo1,而是创建了一个匿名的内部类,同时给匿名内部类做了一个实例
那我么如何执行里面的 printInfo()
直接.
因为new Demo1() 的返回值就是一个对象嘛
对象的尾巴这面可以直接调用printInfo();
这就是做了一个匿名内部类,同时创建了一个匿名内部类的实例,实例可以调用
还有一种方法就是用多态的方式了
new Demo1() 是一个对象 我可以把他的父对象的声明给他
Demo1 d = new Demo1()
这样看下去像是实例化了一个Demo1 ,其实不是的,这个new Demo1 实际上是它的子类,是一个匿名内部类,属于抽象类的子类
d.printInfo为什么可以呢?这是多态的东西
运行结果
同样的我们定义一个接口也是一样的
你去new 一个接口的时候也是一样的,也是做了一个匿名内部类,去实现里面的interprint
同样的我们可以通过.来调用
运行结果
注意:匿名内部类是new 了一个抽象或者new 了一个接口,
我们在新创建了一个匿名内部类的时候,也创建了一个实例