Java基础 -- 内部类

1、内部类

内部类是定义在一个类的内部的类,内部类 不能定义静态变量和方法。接口内也可以使用内部类,但没必要

  • 更好的实现隐藏:内部类可以被 private 与 protected 修饰
  • 内部类拥有外部类的所有元素的访问权限:可以直接调用所有外部类的成员,包括 private 修饰的变量和方法、非静态变量和方法等
  • 可以间接的实现多重继承:一个类中可以写多个内部类,分别继承不同的类
  • 可以避免实现的接口或继承的类中有同名的方法
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷

1.1 内部类区别

20200917192926

1.2 成员内部类

public class Test { public int x = 1; private static int y = 10; String str = "Test"; public void m1() { System.out.println("Test m1"); } private static void m2() { System.out.println("Test m2"); } void str() { System.out.println("Test str"); } // 成员内部类 class InnerClass { String str = "InnerClass"; void method() { // 外部类成员变量 System.out.println(x); // 外部类静态变量 System.out.println(y); // 同名变量,优先调用内部类变量 System.out.println(str); // 外部类同名变量 System.out.println(Test.this.str); // 外部类方法 m1(); // 外部类静态方法 m2(); // 同名方法,优先调用内部类方法 str(); // 外部类同名方法 Test.this.str(); } void str() { System.out.println("InnerClass str"); } } public static void main(String[] args) { // 先创建外部类对象 Test test = new Test(); // 通过外部类对象创建内部类对象 Test.InnerClass inner = test.new InnerClass(); // 调用内部类方法 inner.method(); // 调用内部类成员变量 System.out.println(inner.str); } }

1.3 静态内部类

被 static 修饰的成员内部类,不需要依赖于外部类的,可以看做静态变量,不能直接使用外部类的非静态变量或方法

public class Test { public int x = 1; private static int y = 10; String str = "Test"; public void m1() { System.out.println("Test m1"); } private static void m2() { System.out.println("Test m2"); } void str() { System.out.println("Test str"); } static class InnerClass { private String str = "InnerClass"; static int i = 10; void method() { // 外部类成员变量 System.out.println(new Test().x); // 外部类静态变量 System.out.println(y); // 同名变量,优先调用内部类变量 System.out.println(str); // 外部类同名变量 System.out.println(new Test().str); // 外部类方法 new Test().m1(); // 外部类静态方法 m2(); // 同名方法,优先调用内部类方法 str(); // 外部类同名方法 new Test().str(); } static void staticMethod() { // 同名变量,优先调用内部类变量 System.out.println(new InnerClass().str); // 外部类同名变量 System.out.println(new Test().str); // 同名方法,优先调用内部类方法 new InnerClass().str(); // 外部类同名方法 new Test().str(); } void str() { System.out.println("InnerClass str"); } } public static void main(String[] args) { // 与成员内部类相比,无需创建外部类对象 InnerClass inner = new InnerClass(); // 调用内部类方法 inner.method(); // 调用内部类静态方法 InnerClass.staticMethod(); // 调用内部类成员变量 System.out.println(inner.str); // 调用内部类静态成员变量 System.out.println(InnerClass.i); } }

1.4 局部内部类

public class Test { public int x = 1; private static int y = 10; String str = "Test"; public void m1() { System.out.println("Test m1"); } private static void m2() { System.out.println("Test m2"); } void str() { System.out.println("Test str"); } public static void main(String[] args) { class InnerClass { private String str = "InnerClass"; void method() { // 外部类成员变量 System.out.println(new Test().x); // 外部类静态变量 System.out.println(y); // 同名变量,优先调用内部类变量 System.out.println(str); // 外部类同名变量 System.out.println(new Test().str); // 外部类方法 new Test().m1(); // 外部类静态方法 m2(); // 同名方法,优先调用内部类方法 str(); // 外部类同名方法 new Test().str(); } void str() { System.out.println("InnerClass str"); } } // 创建内部类对象 InnerClass inner = new InnerClass(); // 调用内部类方法 inner.method(); // 调用内部类成员变量 System.out.println(inner.str); } }

1.5 匿名内部类

没有名称的类,利用父类的构造函数和自身类体构造成一个类,其他地方不能引用,没有构造器,不能实例化,只能使用一次

public class Test { int i = 10; One o1 = new One() { int i = 1; @Override void show() { System.out.println("o1 show"); } }; void say() { System.out.println("Test say"); } public static void main(String[] args) { One o2 = new One() { @Override void show() { System.out.println("o2 show"); } void say() { System.out.println("o2 say"); } }; // 定义在方法体外,则需要创建外部类对象 Test test = new Test(); // 调用内部类方法,o1重写后的方法 test.o1.show(); // o1 show // 调用内部类成员变量 System.out.println(test.o1.i); // 0 // 定义在方法体内,可以直接使用 o2.show(); // o2 show // 只能调用One中包含的方法及变量 o2.say(); // 编译错误 } } class One { int i = 0; void show() { System.out.println("one show"); } }

1.6 小伙汁,你见过内部内部内部内部内部内部类吗

public class Test { class InnerClass { class InnerInnerClass { class InnerInnerInnerClass { class InnerInnerInnerInnerClass { class InnerInnerInnerInnerInnerClass { class InnerInnerInnerInnerInnerInnerClass { void show() { System.out.println("内部内部内部内部内部内部类"); } } } } } } } public static void main(String[] args) { Test test = new Test(); Test.InnerClass.InnerInnerClass.InnerInnerInnerClass.InnerInnerInnerInnerClass.InnerInnerInnerInnerInnerClass.InnerInnerInnerInnerInnerInnerClass inner = test.new InnerClass().new InnerInnerClass().new InnerInnerInnerClass().new InnerInnerInnerInnerClass().new InnerInnerInnerInnerInnerClass().new InnerInnerInnerInnerInnerInnerClass(); inner.show(); } }

__EOF__

本文作者holyholic704
本文链接https://www.cnblogs.com/holyholic/p/13687271.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   holyholic704  阅读(185)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示