概述
在类中定义类,类中的这个类就是内部类
内部类的访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象:格式如下
外部类名.内部类名 对象名 = 外部类对象.内部类对象
Outer.Inner oi = new Outer().new Inner();//创建内部类对象
成员内部类私有使用
对外提供公共的访问方法,在这个公共的访问方法中创建内部类对象
静态成员内部类
成员内部类被静态修饰后访问的方式是:外部类名.内部类名 对象名 = 外部类名.内部类对象;
成员内部类面试题
内部类之所以能获取到的成员,是因为它能获取到外部类的引用:外部类名.this
局部内部类访问局部变量的问题
局部内部类:在方法中定义的内部类
- 局部内部类访问局部变量必须使用final修饰
- 局部内部类在访问它所在方法中的局部变量必须用final修饰,为什么?
因为当调用这个方法时,局部变量如果没有final修饰,它的声明周期和方法的声明周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失,想用这个局部变量就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用
但是JDK1.8取消了这个事情,所以认为是一个bug
匿名内部类
就是内部类的简化写法
匿名内部类值针对重写一个方法适合使用
前提:存在一个类或者接口。这里的类可以是具体的类,也可以是抽象类
格式:
new 类名或者接口名(){
重写方法;
}
本质:是一个继承了该类或者实现了该接口的子类匿名对象
public class TestJavaSE {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
interface Ser{
public void print();
}
class Outer {
public void method(){
//实现Inners接口
/* 整个一块代表Ser的子类对象
* new Ser(){
@Override
public void print() {
System.out.println("匿名内部类");
}
}*/
new Ser(){
@Override
public void print() {
System.out.println("匿名内部类");
}
}.print();
}
}
匿名内部类在开发中的应用
匿名内部类当做参数传递,本质把匿名内部类看作一个对象
public class TestJavaSE {
public static void main(String[] args) {
//如何调用PersonDemo中的method方法
PersonDemo pd = new PersonDemo();
Person p = new Person(){
@Override
public void show() {
System.out.println("被调用了");
}
};
pd.method(p);
}
}
abstract class Person{
public abstract void show();
}
class PersonDemo {
public void method(Person p){
p.show();
}
}
面试题:按照要求,补齐代码,要求在控制台输出“HelloWorld”
public class TestJavaSE {
public static void main(String[] args) {
Outer.method().show();
}
}
interface Inter{ void show();}
class Outer {
//补齐代码
}
答案如下:
public class TestJavaSE {
public static void main(String[] args) {
Outer.method().show();//链式编程,每次调用方法后还能调用,证明前面一次调用方法返回的是一个对象
}
}
interface Inter{ void show();}
class Outer {
//补齐代码
//分析:Outer.method()说明method是静态的,
//.show()说明Outer.method()返回的是一个对象/子类对象
public static Inter method(){
Inter i = new Inter() {
@Override
public void show() {
System.out.println("HelloWorld");
}
};
return i;
}
}