1.什么是内部类?
将一个类定义在另一个类里面或者一个方法里面,这样的类被称为内部类。
2.内部类的分类:
- 成员内部类
- 局部内部类
- 匿名内部类
- 静态内部类
各个内部类作用:
-
成员内部类: 定义在类的内部的成员位置上,但是和外部类不是继承关系,它能访问外部类的一切成员,创建方法上有点特殊,需要先创建外部成员类,之后再创建内部成员类
public class MemberInner { int memberData = 1; private int memberPrivateData = 2; private static int memberPrivateStaticData = 3; class InnerClass{ int memberInnerData = 2; public void innerFunction(){ System.out.println("memberData ========"+memberData); System.out.println("memberPrivateData ========"+memberPrivateData); System.out.println("memberPrivateStaticData ========"+memberPrivateStaticData); System.out.println("memberInnerData ========"+memberInnerData); } } } public class Main { public static void main(String[] args) { MemberInner.InnerClass inner= new MemberInner().new InnerClass(); inner.innerFunction(); } }
打印结果为:
memberData ========1 memberPrivateData ========2 memberPrivateStaticData ========3 memberInnerData ========2
-
局部内部类: 和成员内部类不同的是,局部内部类定义在方法体内的位置,所以内部类不能被public、private、static修饰;
/** * 局部内部类 * */ public class PartInner { private String outMember1 = "outMember1"; private String outMethod(){ return "this is outMethod"; } public void functionData(){ String innerMember1 = "innerMember1"; final String innerMember2 = "innerMember2"; class InnerClass{ private String partInnerMember = "partInnerMember"; public void innerFunction(){ System.out.println("partInnerMember======"+partInnerMember); System.out.println("innerMember1======"+innerMember1);//这个没被final修饰,为什么也能过?一会儿解答 System.out.println("innerMember2======"+innerMember2); // 内部类访问外部方法的变量,需要有final修饰 } } InnerClass innerClass = new InnerClass(); innerClass.innerFunction(); } } public class Main { public static void main(String[] args) { // MemberInner.InnerClass inner= new MemberInner().new InnerClass(); // inner.innerFunction(); PartInner partInner = new PartInner(); partInner.functionData(); } }
打印结果
partInnerMember======partInnerMember innerMember1======innerMember1 innerMember2======innerMember2
对了,这个测试环境是jdk1.8
先说为什么访问内部成员必须要用final修饰? 内部类对象的生命周期会超过局部变量的生命周期,所以会出现访问的局部变量已经消亡,匿名内部类却还在活着,定义final后,修饰的局部变量会被拷贝一份,所访问的也是拷贝的内容,所以即使原来的局部变量已经被销毁,因为拷贝了一份与原来局部变量相同的值得数据,所以依然可以被调用。还有就是,正因为是被拷贝了,所以final修饰的数据是不允许做更改的。上面测试环境jdk1.8下,默认给局部变量添加了final修饰,修改是会报错的,也就是说,在jdk1.8的情况下,所访问局部变量依然是被final修饰的。代码如下:
明显可以看出,即使不被final修饰,在修改时也是被编辑器报错的。 -
匿名内部类: 正如其名,没有名字,且在内部呈现的特殊的类。一般适用于只需要使用一次,代码更简洁。
匿名内部类一般的写法有两种,1.继承父类,2.实现某一个接口,后者实际使用的比较多。还是用代码说话吧。
1.继承方式public class AnonymousClass { private final String SCHOOL = "中心学校"; public void accessTest(){ System.out.println("匿名内部类访问外部类的方法"); } class SCHOOL{ private String className ; public SCHOOL(String className){ this.className = className; } public void printClassName(){ System.out.println(school.className); } } SCHOOL school = new SCHOOL("二年级"){ @Override public void printClassName() { accessTest(); System.out.println(SCHOOL); super.printClassName(); } }; public void print(){ school.printClassName(); } } public class Main { public static void main(String[] args) { // MemberInner.InnerClass inner= new MemberInner().new InnerClass(); // inner.innerFunction(); // PartInner partInner = new PartInner(); // partInner.functionData(); AnonymousClass anonymousClass = new AnonymousClass(); anonymousClass.print(); } }
输出结果:
匿名内部类访问外部类的方法 中心学校 二年级
2.实现接口方式(常用)
public class AnonymousInter { interface AnnoymousInterface{ void printData(); } public void method(){ //匿名内部类实现接口 AnnoymousInterface annoymousInterface = new AnnoymousInterface() { @Override public void printData() { System.out.println("匿名内部类实现接口"); } }; annoymousInterface.printData(); } } ---------------------------------------------------- public class Main { public static void main(String[] args) { // MemberInner.InnerClass inner= new MemberInner().new InnerClass(); // inner.innerFunction(); // PartInner partInner = new PartInner(); // partInner.functionData(); // AnonymousClass anonymousClass = new AnonymousClass(); // anonymousClass.print(); AnonymousInter anonymousInter = new AnonymousInter(); anonymousInter.method(); } }
输出结果:
匿名内部类实现接口
匿名内部类可以访问外部的所有成员,但不能访问未加final(jdk1.8的除外,上面已经说过),另外,匿名内部类中不能定义静态的属性和方法
-
静态内部类: 和成员内部类不同的是,静态内部类最大的特点就是内部类用static修饰, 这也就限定了它的访问权限,只能访问外部被static修饰的属性和成员,也是和生命周期有关,static修饰的是早于它所属的非静态修饰的对象的。
public class StaticInner { private int memberData = 1; private static int staticMemberData = 2; public static class StaticInnerClass{ private int memberData = 3; private static int staticMemberData = 4; public void printData(){ System.out.println("memberData========"+memberData); System.out.println("staticMemberData========"+staticMemberData); System.out.println("StaticInner.staticMemberData========"+StaticInner.staticMemberData); } } } -------------------------- public class Main { public static void main(String[] args) { // MemberInner.InnerClass inner= new MemberInner().new InnerClass(); // inner.innerFunction(); // PartInner partInner = new PartInner(); // partInner.functionData(); // AnonymousClass anonymousClass = new AnonymousClass(); // anonymousClass.print(); // AnonymousInter anonymousInter = new AnonymousInter(); // anonymousInter.method(); StaticInner.StaticInnerClass staticInnerClass = new StaticInner.StaticInnerClass(); staticInnerClass.printData(); } }
输出结果:
memberData========3 staticMemberData========4 StaticInner.staticMemberData========2
可以看到很明显的区别在于,静态内部类的生成方式是
StaticInner.StaticInnerClass staticInnerClass = new StaticInner.StaticInnerClass();
staticInnerClass.printData();`
这不同于其他的,先new 出对象后,在进行内部类对象的创建,这也就是说 静态内部类属于外部类,而不是属于外部类的对象