java学习日记20230325-内部类
内部类
基本介绍:
一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类(inner class),嵌套其他类的类车称为外部类(outer class),是我们类的第五大成员(属性,方法,构造器,代码块,内部类),内部类最大的特点就是可以直接访问私有属性,并且可以提现类与类之间的包含关系。内部类是学习的难点和重点,底层源码又大量的内部类
基本语法
class Outer{//外部类 class Inner{//内部类 } } class Other{//其他类 }
内部类的分类:
定义在外部类局部位置上(比如方法内):
1.局部内部类(有类名)
-
- 可以直接访问外部类的所有成员,包含私有的;
- 不能添加访问修饰符,因为他的地位就是一个局部变量,局部变量是不能使用修饰符的,但是 可以使用final修饰了因为局部变量也可以使用final
- 作用域,仅仅在定义他的方法或代码块中
- 局部内部类--访问--外部类的成员(直接访问)
- 外部类--访问--局部内部类的成员 访问方式:创建对象,再访问(必须在作用域内)
- 局部内部类定义在方法中/代码块
- 作用域在方法体和代码块中
- 本质是一个类
- 外部其他类--不能访问--局部内部类
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员 相当于调用方法的对象)去访问
-
public class InnerClass01 { public static void main(String[] args) { Outer outer = new Outer(100); outer.m1(); } } class Outer{ private int n1 =100; public Outer(int n1) { this.n1 = n1; } public void m1(){ System.out.println("m1"); //int n1 = 1000; class Inner{ //private int n1 = 10000; public void fun(){ System.out.println(n1 +"fun内部类调用"); } } Inner inner = new Inner(); inner.fun(); } { System.out.println("代码块"); } class Inner{//内部类 } }
2.匿名内部类(无类名)
匿名内部类的基本用法:
new 类或者接口(参数列表){类体};
本质是类,是个内部类,该类没有名字(名字由jvm分配),同时是一个对象
基于接口的代码案例: 参数列表会传递给构造器

public class AnonymousInterfaceClass { public static void main(String[] args) { Outer04 outer04 = new Outer04(); outer04.m2(); } } class Outer04 implements A{ private int n1 = 10; @Override public void cry() { System.out.println("老虎叫"); } public void m2(){ //tiger的编译类型是接口IA,tiger的运行类型是匿名类型 A tiger =new A(){ @Override public void cry() { System.out.println("老虎叫"); } }; //jdk底层创建匿名内部类Outer04$1,立马创建Outer04$1实例,并且把地址返回给tiger //匿名内部类使用一次就不能再使用 System.out.println(tiger.getClass());//class com.study.anonymousinterface.Outer04$1 tiger.cry(); tiger.cry(); tiger.cry(); } } interface A{ public void cry(); }
基于类的代码案例:

public class AnonymousInterfaceClass { public static void main(String[] args) { Outer04 outer04 = new Outer04(); outer04.m2(); } } class Outer04 implements A{ private int n1 = 10; @Override public void cry() { System.out.println("老虎叫"); } public void m2(){ //tiger的编译类型是接口IA,tiger的运行类型是匿名类型 A tiger =new A(){ @Override public void cry() { System.out.println("老虎叫"); } }; //jdk底层创建匿名内部类Outer04$1,立马创建Outer04$1实例,并且把地址返回给tiger //匿名内部类使用一次就不能再使用 System.out.println(tiger.getClass());//class com.study.anonymousinterface.Outer04$1 tiger.cry(); Father father = new Father("jack"){ @Override public void getSon() { super.getSon(); System.out.println("或者女儿"); } }; System.out.println(father.getClass());//class com.study.anonymousinterface.Outer04$2 father.getSon(); } } interface A{ public void cry(); } class Father{ private String name; public Father(String name) { this.name = name; } public void getSon(){ System.out.println("获取儿子"); } }
匿名内部类使用细节:
- 匿名内部类的语法比较奇特,因为匿名内部类即时一个类的定义,同时它本身也是一个对象爱过你,因此从语法上看,他既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法

public class AnonymousInnerInterfaceDetail { public static void main(String[] args) { Outer05 outer05 = new Outer05(); outer05.f1(); } } class Person{ public void hi(){ System.out.println("person hi()"); } public void ok(String str){ System.out.println("ok()"+str); } } class Outer05{ private int n1 =99; public void f1(){ Person person =new Person(){ @Override public void hi() { System.out.println("匿名内部类重写了hi方法"); } @Override public void ok(String str) { super.ok(str); } }; person.hi(); person.ok("123"); new Person(){ @Override public void hi() { System.out.println("匿名内部类重写了hi方法1"); } }.hi(); } }
- 匿名内部类可以直接访问外部类的所有成员,包含私有的
- 不能添加访问修饰符,因为他的地位就是一个局部变量
- 作用域,仅仅在定义他的方法或代码块中
- 匿名内部类--访问---外部类成员,直接访问
- 外部其他类不能访问匿名内部类
- 外部类和匿名内部类属性重名时,按照就近原则,如果需要访问外部类的属性,可以使用 类名.this.属性名
匿名内部类使用场景:
当做实参直接传递,高效简洁

public class InnerClassExercise02 { public static void main(String[] args) { Cellphone cellphone = new Cellphone(); //传递的是实现了bell接口的匿名内部类,重写了ring,bell接收了匿名内部类创建的对象 //利用动态绑定机制,执行重写的ring方法 cellphone.alarmclock(new Bell() { @Override public void ring() { System.out.println("懒猪起床了"); } }); } } interface Bell{ void ring(); } class Cellphone{ public void alarmclock(Bell bell){ bell.ring(); } }
定义在外部类的成员位置上:
1.成员内部类(没用static修饰)
成员内部类是定义在外部类的成员位置,并且没有static修饰
1.可以直接访问外部类的所有成员,包括私有的;
2.可以添加任意访问修饰符,因为他的地位是一个成员
3.和外部类的其他成员一样,在外部类的成员方法中创建成员内部类对象,在调用方法;
4.成员内部类--访问--外部类 直接访问
5.外部类--访问--内部类,创建对象,访问
6.外部其他类--访问--成员内部类
7.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问

public class MemberInnerClass { public static void main(String[] args) { Outer08 outer08 = new Outer08(); outer08.t1(); //外部其他类,使用成员内部类,第一种 Outer08.Inner8 outer081 = outer08.new Inner8(); outer081.say(); //第二种 outer08.getInner().say(); } } class Outer08{ private int n1 =100; public String name = "jack"; public class Inner8{ private int n1 = 10000; public void say(){ System.out.println(n1+name+Outer08.this.n1); } } public void t1(){ //创建成员内部类对象,使用对象属性和方法 Inner8 inner8 = new Inner8(); inner8.say(); System.out.println(inner8.n1); } public Inner8 getInner(){ return new Inner8(); } }
2.静态内部类(使用static修饰)
静态内部类是定义在外部类的成员位置,并且有static修饰
1.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员;
2.可以添加任意 访问修饰符
3.作用域同其他成员,为整个类体
4.静态内部类--访问--外部类 直接访问所有静态成员
5.外部类--访问--静态内部类。创建内部对象,再访问
6.外部其他类--访问--静态内部类
7.如果外部类和静态内部类的成员重名时,静态内部类访问遵循就近原则,如果想访问外部类的成员,则可以使用,外部类名.成员去访问

public class StaticMemberInnerClass { public static void main(String[] args) { Outer10 outer10 = new Outer10(); outer10.m1(); //外部类访问 Outer10.Inner10 inner10 = new Outer10.Inner10(); outer10.get(); } } class Outer10{ private int n1 =100; private static int n2 = 1000; private static void cry(){ System.out.println("cry"); } public static class Inner10{ public void say(){ System.out.println(n2); cry(); Outer10.cry(); } public void cry(){ System.out.println("内部类cry"); } } public void m1(){ Inner10 inner10 = new Inner10(); inner10.say(); } public Inner10 get(){ return new Inner10(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器