欢迎来到我的主页:【一只认真写代码的程序猿】
本篇文章收录于专栏【小小爪哇】
如果这篇文章对你有帮助,希望点赞收藏加关注啦~
目录
1 内部类Inner Class
1.1 局部内部类
1.2 匿名内部类(※※)
1.3 匿名类最佳实践(当成实参传)
1.4 成员内部类
1.5 静态内部类
1 内部类Inner Class
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class);嵌套其他类的类称为外部类(outer class)。是我们类的第五大成员。
【类的五大成员是哪些?1属性 2方法 3构造器 4代码块 5内部类]】
内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。
class OuterClass{//外部类class InnerClass{//内部类}
}
class OuterOtherClass{//其他内部类}
1.1 局部内部类
/*** 演示局部内部类的使用*/
public class LocalInnerClass {public static void main(String[] args) {Outer02 outer02 = new Outer02();outer02.m1();System.out.println("outer02 的 hashcode=" + outer02);}
}class Outer02 {//外部类private int n1 = 100;private void m2() {System.out.println("Outer02 m2()");}public void m1() {//方法//1.局部内部类是定义在外部类的局部位置,通常在方法//3.不能添加访问修饰符,但是可以使用 final 修饰//4.作用域 : 仅仅在定义它的方法或代码块中final class Inner02 {//局部内部类(本质仍然是一个类)//2.可以直接访问外部类的所有成员, 包含私有的private int n1 = 800;public void f1() {5. 局部内部类可以直接访问外部类的成员, 比如下面 外部类 n1 和 m2()7. 如果外部类和局部内部类的成员重名时, 默认遵循就近原则, 如果想访问外部类的成员,使用 外部类名.this.成员) 去访问老韩解读 Outer02.this 本质就是外部类的对象, 即哪个对象调用了 m1, Outer02.this 就是哪个对象System.out.println("n1=" + n1 + " 外部类的 n1=" + Outer02.this.n1);System.out.println("Outer02.this hashcode=" + Outer02.this);m2();}}//6. 外部类在方法中, 可以创建 Inner02 对象, 然后调用方法即可Inner02 inner02 = new Inner02();inner02.f1();}
}
1.2 匿名内部类(※※)
特点:本质上还是类,内部类,没有名字的类,同时还是个对象。
参考官方文档:oracle英文文档
Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.
以下是官方代码,注释由GPT生成。
public class HelloWorldAnonymousClasses {// 定义一个 HelloWorld 接口,包含两个方法:greet() 和 greetSomeone(String someone)interface HelloWorld {public void greet();public void greetSomeone(String someone);}public void sayHello() {// 定义一个 EnglishGreeting 类,实现 HelloWorld 接口class EnglishGreeting implements HelloWorld {String name = "world"; // 默认问候对象为 "world"public void greet() {greetSomeone("world"); // 调用 greetSomeone 方法,传入默认问候对象}public void greetSomeone(String someone) {name = someone; // 更新问候对象System.out.println("Hello " + name); // 打印问候信息}}// 创建 EnglishGreeting 的实例,并调用 greet 方法HelloWorld englishGreeting = new EnglishGreeting();// 使用匿名内部类创建一个 HelloWorld 的实例,实现法语问候HelloWorld frenchGreeting = new HelloWorld() {String name = "tout le monde"; // 默认问候对象为 "tout le monde"public void greet() {greetSomeone("tout le monde"); // 调用 greetSomeone 方法,传入默认问候对象}public void greetSomeone(String someone) {name = someone; // 更新问候对象System.out.println("Salut " + name); // 打印问候信息}};// 使用匿名内部类创建一个 HelloWorld 的实例,实现西班牙语问候HelloWorld spanishGreeting = new HelloWorld() {String name = "mundo"; // 默认问候对象为 "mundo"public void greet() {greetSomeone("mundo"); // 调用 greetSomeone 方法,传入默认问候对象}public void greetSomeone(String someone) {name = someone; // 更新问候对象System.out.println("Hola, " + name); // 打印问候信息}};// 执行英语问候englishGreeting.greet();// 执行法语问候,传入特定对象 "Fred"frenchGreeting.greetSomeone("Fred");// 执行西班牙语问候spanishGreeting.greet();}public static void main(String... args) {HelloWorldAnonymousClasses myApp = // 创建 HelloWorldAnonymousClasses 类的实例new HelloWorldAnonymousClasses();myApp.sayHello(); // 调用 sayHello 方法,展示不同语言的问候}
}
上述代码中分别用局部类来初始化变量英语,用匿名类来初始化变量法语和西班牙,两种实现之间有明显的区别:
1)局部类English实现接口后,有自己的类名,定义完成之后要再new一下
2)french和spanish在定义的时候就实例化,定义完了就可以直接使用
3)匿名类是表达式,最后用分号结尾
1.3 匿名类最佳实践(当成实参传)
/*** @ClassName InnerClassTest* @Description 匿名内部类当做实参传递小demo* @Date 2024/11/27 17:13* @Version V1.0*/
public class InnerClassTest {public static void main(String[] args) {//当做实参直接传递, 简洁高效f1(new IL() {@Overridepublic void show() {System.out.println("匿名类的show方法");}});//传统方法f1(new Picture());}//静态方法,形参是接口类型public static void f1(IL il) {il.show();}
}
//接口
interface IL {void show();
} //类->实现 IL => 编程领域 (硬编码)
class Picture implements IL {@Overridepublic void show() {System.out.println("调用Picture的show方法");}
}
一个匿名类的小练习:
package day111;/*** @ClassName BellTest* @Description 匿名内部类的小练习* 1、一个铃声接口Bell,里面有ring方法。* 2、一个手机类cellphone,有闹钟功能alarmClock,参数是Bell类型* 3、测试手机的闹钟功能,分别打印:A起床了;B起床了* @Author 聂宇旋* @Date 2024/11/27 17:25* @Version V1.0*/
public class BellTest {public static void main(String[] args) {CellPhone cellPhone = new CellPhone();cellPhone.alarmClock(new Bell() {@Overridepublic void ring() {System.out.println("A起床了");}});cellPhone.alarmClock(new Bell() {@Overridepublic void ring() {System.out.println("B起床了");}});}
}
interface Bell{void ring();
}
class CellPhone{public void alarmClock(Bell bell){System.out.println(bell.getClass());bell.ring();}
}
1.4 成员内部类
成员内部类是定义在外部类的成员位置,没有static修饰。
- 可以直接访问外部类的所有成员(包含private)
- 可以任意添加访问修饰符(因为他就是一个成员)
- 可以在外部类中写一个getInner方法来获得内部类对象
- 如果内部类和外部类成员重名,就近原则。
/*** @ClassName MemberInnerClass* @Description 成员内部类学习* @Date 2024/11/27 19:21* @Version V1.0*/
public class MemberInnerClass {public static void main(String[] args) {Outer outer = new Outer();outer.t1();Outer.Inner inner = outer.new Inner();inner.hi();Outer.Inner inner1 = outer.getInner();inner1.hi();}}
class Outer{//外部类private int n1=10;public String name = "外部类";public void hi(){System.out.println("外部类hello");}//1.注意: 成员内部类, 是定义在外部内的成员位置上//2.可以添加任意访问修饰符(public、 protected 、 默认、 private),因为它的地位就是一个成员public class Inner{public int n1=11;private int n2 = 20;public void hi(){//可以直接访问外部类的所有成员, 包含私有的//如果成员内部类的成员和外部类的成员重名, 会遵守就近原则.,可以通过 外部类名.this.属性 来访问外部类的成员System.out.println("内部类hello;"+hashCode()+";n1 = "+n1+" ;外部类n1="+Outer.this.n1);}}//可以写一个get内部类的方法public Inner getInner(){return new Inner();}public void t1(){//使用成员内部类,创建对象,用相关方法Inner inner = new Inner();inner.hi();System.out.println("n2="+inner.n2);}
}
1.5 静态内部类
静态内部类是定义在外部类的成员位置,并且有static修饰
- 可以直接访问外部类的所有静态成员,包含private,但不能直接访问非静态成员。
- 可以添加任意访问修饰符,因为它的地位就是一个成员。
- 作用域:同其他的成员,为整个类体。
- 和前面的成员内部类类似了,只是静态内部类可以通过Outer.Inner oi = new Outer.Inner();而成员内部类需要先new出来一个outer,再Outer.Inner oi = outer.newInner();当然也可以写get方法。
package day111;/*** @ClassName MemberInnerClass* @Description 成员内部类学习* @Author 聂宇旋* @Date 2024/11/27 19:21* @Version V1.0*/
public class MemberInnerClass {public static void main(String[] args) {Outer outer = new Outer();outer.t1();Outer.Inner inner = outer.new Inner();inner.hi();Outer.Inner inner1 = outer.getInner();inner1.hi();Outer.StaticInner staticInner = new Outer.StaticInner();staticInner.hiStatic();}}
class Outer{//外部类private int n1=10;public String name = "外部类";public void hi(){System.out.println("外部类hello");}//1.注意: 成员内部类, 是定义在外部内的成员位置上//2.可以添加任意访问修饰符(public、 protected 、 默认、 private),因为它的地位就是一个成员public class Inner{public int n1=11;private int n2 = 20;public void hi(){//可以直接访问外部类的所有成员, 包含私有的//如果成员内部类的成员和外部类的成员重名, 会遵守就近原则.,可以通过 外部类名.this.属性 来访问外部类的成员System.out.println("内部类hello;"+hashCode()+";n1 = "+n1+" ;外部类n1="+Outer.this.n1);}}public static class StaticInner{private static int nStatic = 22;public void hiStatic(){System.out.println("静态内部类的hello");}}//可以写一个get内部类的方法public Inner getInner(){return new Inner();}public void t1(){//使用成员内部类,创建对象,用相关方法Inner inner = new Inner();inner.hi();System.out.println("n2="+inner.n2);}
}