内部类
内部类:一个类中嵌套(包含)另外一个类。包含的类叫内部类,外层类叫外部类
分类:
- 成员内部类
- 局部内部类
- 静态内部类
- 匿名内部类
成员内部类
作为外部类的成员存在,与成员变量和成员方法平级
声明格式:
public class Out{
//成员变量
//成员方法
//成员内部类
访问权限 class In{
//成员变量
//成员方法
}
}
语法说明:
成员内部类的访问权限:
任意的(因为跟成员变量,成员方法平级)
如何创建成员内部类的对象:
由于成员内部类作为外部类的成员存在,若想访问类成员,则需要通过对象,所以成员内部类对象需要通过外部类来创建
语法:
//创建外部类对象
Out out = new Out();
//通过外部类对象,创建内部类对象
Out.in in = out.new In();
//一步完成
Out.In in = new Outer().new In();
如何在成员内部类中访问外部类的成员:
1.当外部类的属性和内部类的属性不相同时,可直接访问
2.当外部类属性与内部类属性同名时,格式:
外部类名.this.属性名
3.成员内部类中不能包含静态成员,可以包含静态常量(static final修饰的)
成员内部类的字节码文件:
外部类名$内部类名.class
局部内部类
作为局部成员存在,与局部变量平级
声明:
public class Outer{
//成员变量
//成员方法
//局部内部类所在的方法
public void fun(){
//功能代码
//局部内部类
class Inner{
//局部内部类的成员变量
//局部内部类的成员方法
}
}
}
语法说明:
局部内部类的访问权限:
只能是默认的
如何创建局部内部类对象:
直接在局部内部类所在的方法中(局部内部类的下面,因为代码顺序运行的)创建对象,并调用方法
如何在局部内部类中访问外部类的属性:
1.不同名,直接访问
2.同名,外部类名.this.属性名
3.局部内部类中不能包含静态成员,可以包含静态常量(static final修饰的)
4.局部内部类中访问局部变量(所在的方法中的变量),局部变量必须是final常量,从jdk1.8之后final可以省略
局部内部类字节码文件:
外部内部类$编号内部类名.class
注意:
在外部类调用内部类所在的方法时,会声明局部内部类,并创建对象,调用方法(顺序执行)
静态内部类
static关键字的用法:修饰成员变量,成员方法,代码块
static关键字的第四个用法,修饰成员内部类(静态内部类),不能修饰局部内部类
声明:
public class Out{
访问权限 static class In{
}
}
语法说明:
权限访问:任意的,一般使用public
使用static修饰的内部类,自动提升为普通类,相当于一个独立的类,和外部类级别相同
创建对象:
应为是静态的,所以不需要外部类对象,就可以直接创建静态内部类的对象
格式:
外部类.内部类 标识符 = new 外部类.内部类构造方法;
访问外部类的成员:
1.静态内部类能直接访问外部类的静态成员
2.非静态的成员只能通过创建外部类对象访问
3.静态内部类中可以包含静态成员
字节码文件格式:
外部类名$内部类名.class(与成员内部类一样)
匿名内部类
什么是匿名内部类?
没有名字的内部类
原理产生原因:
由于接口和抽象类不能创建对象,若一个接口的实现类只需要使用一次,或者一个抽象类的子类只需要使用一次,可以使用匿名内部类,匿名内部类只能创建一个对象
例:
public interface I {
public abstract void fun();
}
public class Test{
public static void main(Strng[]args){
I i = new I(){
public void fun(){
//功能代码
}
};
i.fun1();//使用匿名内部类的对象(接口引用)调用匿名内部类中重写的接口中的方法
}
}
匿名内部类的注意事项:
1.匿名内部类中必须把抽象方法全部实现
2.匿名内部类中可以声明独有的属性和方法,但是由于接口引用不能访问实现类中的独有属性和方法,所以一般不在匿名内部类中声明独有的属性和方法
3.匿名对象:若在匿名内部类中声明了独有的方法或属性,可以使用匿名对象访问,不能通过对象名.方法名()访问
匿名内部类的字节码文件格式:
测试类$编号.class
匿名内部类只能使用一次,即便两次声明内部类完全一致,也是两个匿名内部类