内部类
在一个类中定义一个类
特点: 内部类可以访问外部类的成员,包括私有修饰的
分类:
- 成员内部类:在类中的成员位置
- 局部内部类:在方法的局部位置
成员内部类访问特点(非静态):
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inter oi = new Outer().new Inter();
(静态)
外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inter oi = new Outer.Inter();
成员内部类的修饰符:
- private:被private修饰,保证数据的安全性
- static:静态的成员内部类只能访问外部类的静态数据,静态的成员内部类要访问成员
举例:
class Outer{ //外部类
private int num = 0;
class Inter{ //内部类
public void show(){ //成员方法
System.out.println(num);
}
//在外部类的成员位置访问内部类成员,必须创建内部类对象
public void method(){
//show(); //错误的!!!
Inter i = new Inter(); //创建内部类对象
i.show();
}
}
}
//测试类
class OuterDemo{
public static void main (String[] args){
Outer o = new Outer(); //创建外部类对象
o.method(); //调用method方法输出10
}
}
局部内部类
- 可以访问外部类成员,包括私有
- 在外部类局部位置可以去访问局部内部类成员,创建该内部类对象,使用对象访问
jdk 1.7包含1.7,局部内部类访问局部变量,局部变量必须使用final修饰,
jdk1.8处理掉了编译错误
面试题:为什么在内存中使用final修饰?
因为局部变量会随着方法的调用完毕而消失,这个时候局部对象并没有立马从堆内存中消失,还要使用那个变量,
为了让数据还能继续使用,就用final修饰,这样,在堆内存里面存储的其实是一个常量。
匿名内部类
前提条件:存在一个类或者接口,可以是具体类,也可以是抽象类
格式:new 类名或者接口名(){ 重写方法; };
本质:是一个继承了类或者实现了接口的子类匿名对象
看程序,写结果:控制台输出:30,20,10
class Outer{ //外部类
public int num = 10;
class Inter{ //内部类
int num = 20;
public void show(){
int num = 30;
System.out.println(num); //访问内部类中局部变量
System.out.println(this.num); //访问内部类中的成员变量
System.out.println(Outer.this.num); //外部类的this限定
}
}
}
//测试类
class Test{
public static void main(String[] args){
Outer.Inter oi = new Outer().new Inter();
oi.show();
}
}
按照要求,补齐代码,在控制台输出“HelloWorld”
Interface Inter{ //接口
public void show();
}
class Outer{ //外部类
//补齐代码
public static Inter method(){
return new Inter(){ //返回匿名内部类
public void show(){
System.out.println("HelloWorld");
}
};
}
}
class Test{ //测试类
public static void main(String[] args){
Outer.method().show();
}
}
解析:
Outer.method()
用类名调用方法,所以method()是静态的
Outer.method()能够调用show(),说明前面部分可以返回一个对象,并且该对象能访问接口中的show();