1. 内部类结束
内部类具有封装型,隐藏程序细节。主要有非静态内部类,静态内部类,匿名内部类几种。
2. 非静态内部类
可用把内部类当作外部类的成员变量/方法来使用,需要依赖外部类对象来使用
public class OutClass { private String outStr; public void display(){ System.out.println(outStr); } //内部类 public class InnerClass{ private String innerStr; public InnerClass() { innerStr = "innner class"; } public void display(){ System.out.println("Inner class"); System.out.println(innerStr); } } public static void main(String[] args) { OutClass outClass = new OutClass(); outClass.display(); OutClass.InnerClass innerClass = outClass.new InnerClass(); //创建内部类需要外部类对象调用 innerClass.display(); } }
非静态内部类还可以定义在方法内
public class OutClass02 { private String outStr; public void display(){ class InnerClass{ private String innerStr; public InnerClass() { innerStr = "innner class"; } public void display(){ System.out.println("Inner class"); System.out.println(innerStr); } } InnerClass innerClass = new InnerClass(); //可以直接创建内部类 innerClass.display(); } public static void main(String[] args) { OutClass02 outClass02 = new OutClass02(); outClass02.display(); } }
2. 静态内部类
静态内部类使用不需要依赖外部对象
public class OutClass03 { private String outStr; public void display(){ System.out.println(outStr); } public static class InnerClass03{ private String innerStr; public InnerClass03() { innerStr = "innner class"; } public void display03(){ System.out.println("Inner class"); System.out.println(innerStr); } } public static void main(String[] args) { OutClass03 outClass03 = new OutClass03(); outClass03.display(); InnerClass03 innerClass03 = new InnerClass03(); //创建内部类不需要外部类对象调用 innerClass03.display03(); } }
3. 匿名内部类
可用直接实现接口创建对象,还可以直接"new 接口名“,重写接口中方法
public interface InnerInterface { void inner(); }
public class InnerInterfaceImpl implements InnerInterface { @Override public void inner() { System.out.println("test"); } }
public class MyApp { public static void main(String[] args) { //(1)创建对象 InnerInterface innerInterface = new InnerInterfaceImpl(); innerInterface.inner(); //(2)匿名内部类 InnerInterface innerInterface1 = new InnerInterface() { @Override public void inner() { System.out.println("test1"); } }; innerInterface1.inner(); } }
还可用把接口的实现放在类里面,这样就相当于一个内部类,所以调用就需要依赖外部类对象来调用
public class MyApp2 { public class InnerInterfaceImpl implements InnerInterface{ @Override public void inner() { System.out.println("test2"); } } public static void main(String[] args) { MyApp2 myApp2 = new MyApp2(); MyApp2.InnerInterfaceImpl innerInterface = myApp2.new InnerInterfaceImpl(); innerInterface.inner(); } }
3. 局部内部类和匿名内部类访问局部变量
(1)局部内部类访问局部变量
public class Test01 { public static void main(String[] args) { new Test01().test(6); } public void test(int b){ int a = 10; new Thread(new Runnable() { @Override public void run() { System.out.println(a); System.out.println(b); // System.out.println(a++); 提示错误,变量被final修饰 // System.out.println(b++); } }).start(); } }
(2)匿名内部类访问局部变量
public class Test03 { private int age = 12; public static void main(String[] args) { new Test03().test(20); } public void test(int x){ class InnerClass{ public void InPrint(){ // System.out.println(x++); 提示错误,变量被final修饰 System.out.println(x); System.out.println(age++); //可以访问成员变量 } } new InnerClass().InPrint(); } }
总结:
在Java 1.8后虽然在类中不用直接在变量前使用final修饰,但是也不能修改变量的值,对变量进行++会有编译报错。通过反编译.class文件后,也能看到变量会被final修饰
所以局部内部类和匿名内部类访问局部变量时会被final修饰。
内部类和外部类是处于同一级别的,内部类不会因为定义在方法中就会随着方法的执行完毕被销毁。
所以当外部类的方法结束后,局部变量就应该被销毁了,但是内部类可能还会存在,这样内部类就会引用了不存在的变量。此时就需要将局部变量复制一份作为内部类的成员变量,这样局部变量死亡后,内部类依然可以访问它,实际访问的是局部变量的“copy”,相当于延长了局部变量的生命周期。
将局部变量复制作为内部类的成员变量时,就必须要保证两个变量是一致的,如果在内部类修改了成员变量,方法中也就要改变,所以可以把局部变量设置为final,对它初始化后,就不再改变这个变量了,就可以保证内部类的成员变量和方法的局部变量的一致性了,这实际上也是一种妥协,使得局部变量和内部类的建立的拷贝保持一致。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)