文章目录
- 1.基本介绍
- 1.定义:
- 2.基本语法:
- 3.内部类的分类
- 2.局部内部类
- 1.快速入门
- 2.局部内部类的使用
- 3.匿名内部类
- 1.匿名内部类实现接口
- 2.匿名内部类继承抽象类
- 3.匿名内部类细节
- 4.匿名内部类最佳实践
- 1.匿名内部类作为实参传入函数
- 2.匿名内部类课堂练习
- 4.成员内部类
- 成员内部类的使用
- 5.静态内部类
- 静态内部类的使用
1.基本介绍
1.定义:
一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其他类的类被称为外部类。
2.基本语法:
3.内部类的分类
- 定义在外部局部位置上(比如方法内):
- 局部内部类(有类名)
- 匿名内部类(没有类名)
- 定义在外部类的成员位置上
- 成员内部类(没用static修饰)
- 静态内部类(使用static修饰)
2.局部内部类
1.快速入门
package innerclass;public class LocalInnerClass {public static void main(String[] args) {new Outer02().m1();}
}class Outer02 { //外部类private int n1 = 100;private void m2() { //私有方法System.out.println("这是外部类的私有方法");}public void m1() {class Inner02 { //局部内部类,是放在代码块或者方法中(本质仍然是一个类)public void f1() {System.out.println("外部类的私有属性:" + n1); //局部内部类可以直接访问外部类的所有私有成员}}class Inner03 extends Inner02 { //局部内部类可以被继承public void f2() {super.f1(); //可以访问父类的方法m2();//还可以访问外部类的私有方法}}new Inner03().f2(); //在方法中创建局部内部类的对象然后调用方法}}
2.局部内部类的使用
-
局部内部类既是一个局部变量又是一个类
-
局部内部类可以访问外部类的所有成员,包括私有的
-
不能添加访问修饰符,因为他的地位是一个局部变量,但是可以使用final修饰
-
作用域:仅仅在定义他的方法或者代码块中
-
外部类访问局部内部类的方式,在方法或者代码块中声明局部内部类的对象然后调用
-
外部其他类不能访问局部内部类,因为局部内部类地位是一个局部变量
-
如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用
外部类名.this.成员
外部类名.this的意思是外部类的一个对象,就相当于普通类中的this,谁调用的这个方法,则这个对象就是谁
-
代码实例
package innerclass;public class LocalInnerClass {public static void main(String[] args) {new Outer02().m1();} }class Outer02 { //外部类private int n1 = 100;public void m1() {class Inner02 { //局部内部类,是放在代码块或者方法中(本质仍然是一个类)int n1 = 200; //与外部类中的属性重名,默认遵循就近原则public void f1() {System.out.println("局部内部类中的n1 = " + n1); //根据就近原则,访问了局部内部类中的n1System.out.println("外部类中的n1 = " + Outer02.this.n1);}}new Inner02().f1();} }
3.匿名内部类
1.匿名内部类实现接口
-
需求:想使用一个接口,并创建对象,但是只使用一次
-
传统方式:写一个类,实现接口,并创建对象
-
可以使用匿名内部类来简化开发
-
jdk底层:创建了一个匿名内部类,实现了接口,然后返回一个这个匿名内部类的对象
-
代码实例
package innerclass;public class AnonymousInnerClass {public static void main(String[] args) {new Out().method();} } interface IA {void cry(); } class Out { //外部类public void method() {IA tiger = new IA() { //编译类型是IA , 运行类型是匿名内部类Out$1@Overridepublic void cry() {System.out.println("老虎在哭");}}; //匿名内部类,底层进行了,写一个匿名内部类,实现了接口IA,然后返回了一个对象tiger.cry();System.out.println("匿名内部类的名字:" + tiger.getClass());} }
2.匿名内部类继承抽象类
-
匿名内部类可以继承普通类或者抽象类
-
jdk底层:创建一个匿名内部类,继承了抽象类,重写抽象类的抽象方法,返回一个匿名内部类的对象,如果有构造器相当于调用了父类的构造器
-
代码实例
package innerclass;public class AnonymousInnerClass {public static void main(String[] args) {new Out().method();} } abstract class Father1 {public Father1(String name) {}public abstract void cry(); //抽象方法 } class Out { //外部类public void method() {Father1 father = new Father1("父亲") { //匿名内部类整个过程相当于,1.创建一个匿名内部类 2.继承了Father类 3.返回一个匿名内部类的对象//这个匿名内部类继承了抽象类则需要重写抽象方法@Overridepublic void cry() {System.out.println("匿名内部类重写了父类的抽象方法");}};father.cry();} }
3.匿名内部类细节
-
匿名内部类是以一个类似于类的形式展示,但是其实他是这个类返回的一个对象,所以可以直接使用这个匿名内部类对象来访问里面的成员
-
匿名内部类可以直接访问外部类的所有成员,包括私有的
-
不能给匿名内部类直接添加访问修饰符,因为匿名内部类本身也是一个局部变量
-
匿名内部类的作用域:仅仅在定义它的方法或代码块中
-
匿名内部类访问外部类的成员的方式是直接访问
-
如果内部类的属性跟外部类的属性冲突,则可以使用类名.this.属性名的方式访问外部类的属性
-
其他外部类不能访问匿名内部类,因为匿名内部类只是一个局部变量
-
代码实例
package innerclass;public class AnonymousInnerClassDetail {public static void main(String[] args) {new Outer05().f1();} } class Person {public void hi(String name) {System.out.println("你好:" + name);} } class Outer05 {private int n1 = 99;public void f1() {new Person() { //匿名内部类继承了Person类@Overridepublic void hi(String name) { //重写了hi方法super.hi(name);}}.hi("小明");//这相当于匿名内部类的一个对象可以直接调用方法new Person() {int n1 = 100; //这里的属性跟外部类的属性重名了public void printn1() {System.out.println("外部类的n1:" + Outer05.this.n1); //使用外部类名.this.属性名来访问与内部类重名的外部属性System.out.println("内部类的n1:" + n1);}}.printn1();} }
4.匿名内部类最佳实践
1.匿名内部类作为实参传入函数
package innerclass;public class InnerclassExercise01 {public static void main(String[] args) {f1(new IL() {@Overridepublic void show() {System.out.println("我实现了接口的IL方法");}}); //使用匿名内部类直接作为实参传入函数}public static void f1(IL li) {li.show();}
}
interface IL {void show();
}
2.匿名内部类课堂练习
-
代码
package innerclass;public class InnerclassExercise02 {public static void main(String[] args) {new CellPhone().alarmclock(new Bell() {@Overridepublic void ring() {System.out.println("懒猪起床了");}});new CellPhone().alarmclock(new Bell() {@Overridepublic void ring() {System.out.println("小伙伴上课了");}});} } interface Bell {void ring(); } class CellPhone {public void alarmclock(Bell bell) {bell.ring();} }
-
结果
4.成员内部类
成员内部类的使用
-
说明:成员内部类是定义在外部类的成员位置,并且没有static修饰
-
可以直接访问外部类的所有成员,包括私有的
-
可以添加任何访问修饰符,因为他的定位就是一个成员
-
作用域:和外部类的其他成员一样
-
成员内部类访问外部类的成员可以直接访问,当成员内部类的成员跟外部类的成员重名的时候,使用外部类名.this.成员名来访问
-
外部类访问成员内部类,创建对象访问
-
代码实例
package innerclass;public class MemberInnerClass01 {public static void main(String[] args) {new Outer01().f1();Outer01 outer01 = new Outer01();} } class Outer01 { //外部类private int n1 = 10;public String name = "张三";public class Innter01 { //成员内部类public String name = "李四"; //成员内部类的属性跟外部类重名public void say() {System.out.println("Outer01的n1:" + n1 + " Outer01的name:" + Outer01.this.name); //成员内部类可以访问外部类的所有成员,当重名的时候需要使用外部类名.this.属性名来访问}}public void f1() {//使用成员内部类Innter01 innter01 = new Innter01(); //外部类访问成员内部类,创建对象访问innter01.say();} }
-
外部其他类访问成员内部类有两种方式
- 通过外部类的实例来访问并创建一个成员内部类的实例
- 在外部类中暴露一个方法返回成员内部类的实例
package innerclass;public class MemberInnerClass02 {public static void main(String[] args) {//外部其他类访问成员内部类的第一种方式,使用外部类的实例来访问内部类并创建对象Outer06.Innter innter = new Outer06().new Innter();innter.method();//第二种方式,在外部类中写一个方法直接返回成员内部类的对象Outer06.Innter innter1 = new Outer06().getInnter();innter1.method();} } class Outer06 { //外部类public class Innter { //成员内部类public void method() {System.out.println("我是成员内部类");}}public Innter getInnter() { //向外暴露一个方法来获得成员内部类的对象return new Innter();} }
5.静态内部类
静态内部类的使用
-
说明:静态内部类是有static的在成员位置的内部类
-
可以直接访问外部类的所有静态成员,包括私有的,但是不能直接访问非静态成员
-
可以添加任何访问修饰符,因为他的地位是一个成员
-
作用域:同其他的成员
-
静态内部类访问外部类的静态成员可以直接访问,如果重名,则使用外部类名.成员名来访问(不加this的原因静态内部类只能访问静态成员,所以就没有加this的必要)
-
外部类访问静态内部类 创建对象再访问
-
外部其他类访问静态内部类有三种方式
package innerclass;public class StaticInnerClass01 {public static void main(String[] args) {//外部其他类访问静态内部类的第一种方式,创建对象访问Outer07.Inner02 inner02 = new Outer07.Inner02(); //因为他是静态的所以是是属于类的可以直接用类名访问inner02.say();//外部其他类访问静态内部类的第二种方式,在外部类中暴露一个普通方法返回静态内部类的实例Outer07.Inner02 inner021 = new Outer07().getInner02();inner021.say();//外部其他类访问静态内部类的第三种方式,在外部类中暴露一个静态方法返回静态内部类的实例Outer07.Inner02 inner022 = Outer07.getInner02_();inner022.say();} } class Outer07 { //外部类public static class Inner02 {public void say() {System.out.println("我是静态内部类");}}public Inner02 getInner02() { //普通方法返回静态内部类实例return new Inner02();}public static Inner02 getInner02_() { //静态方法返回静态内部类实例return new Inner02();} }
-
练习