🔥作者主页:小林同学的学习笔录
🔥小林同学的专栏:JAVA之基础专栏
目录
1.内部类
1.1 概述
1.1.1 什么是内部类
1.1.2 什么时候使用内部类
1.2 内部类的分类
1.3 成员内部类
1.3.1 获取成员内部类对象的两种方式
1.3.2 经典面试题
1.4 静态内部类
1.4.1 静态内部类对象的创建格式
1.5 局部内部类
1.6 匿名内部类
1.6.1 引出匿名内部类
1.6.2 匿名内部类用处
1.6.3 匿名内部类的使用场景
1.内部类
1.1 概述
1.1.1 什么是内部类
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类,其他称为外部其他类。可以把内部类理解成寄生,外部类理解成宿主。
1.1.2 什么时候使用内部类
一个事物内部还有一个独立的事物,内部的事物脱离外部的事物无法独立使用
-
人里面有一颗心脏。
-
汽车内部有一个发动机。
-
目的为了实现更好的封装性。
1.2 内部类的分类
按定义的位置来分
-
成员内部内,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)
-
静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)
-
局部内部类,类定义在方法内
-
匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。
1.3 成员内部类
类定义在成员位置上
1.3.1 获取成员内部类对象的两种方式
- 方式一:外部直接创建成员内部类的对象
- 外部类.内部类 变量 = new 外部类().new 内部类();
- 方式二:在外部类中定义一个方法提供内部类的对象(一般用在内部类用private修饰才用到)
代码演示:
方式一:
public class Test {public static void main(String[] args) {// 宿主:外部类对象。// Outer out = new Outer();// 创建内部类对象。Outer.Inner oi = new Outer().new Inner();oi.method();}
}class Outer {// 成员内部类,属于外部类对象的。// 拓展:成员内部类不能定义静态成员。public class Inner{// 这里面的东西与类是完全一样的。public void method(){System.out.println("内部类中的方法被调用了");}}
}方式二:
public class Outer {String name;private class Inner{static int a = 10;}public Inner getInstance(){return new Inner();}
}public class Test {public static void main(String[] args) {Outer o = new Outer();System.out.println(o.getInstance());}
}
1.3.2 经典面试题
public class Test {public static void main(String[] args) {Outer.inner oi = new Outer().new inner();oi.method();}
}class Outer { // 外部类private int a = 30;// 在成员位置定义一个类class inner {private int a = 20;public void method() {int a = 10;System.out.println(???); // 10 答案:aSystem.out.println(???); // 20 答案:this.aSystem.out.println(???); // 30 答案:Outer.this.a}}
}
执行原理:
1.4 静态内部类
静态内部类可以直接访问外部类的静态成员。
静态内部类不可以直接访问外部类的非静态成员,如果要访问需要创建外部类的对象。
静态内部类中没有虚拟机所创建的Outer.this
如何调用静态内部类的方法?
- 非静态方法:创建对象,并调用方法
- 静态方法:外部类名.内部类名.方法名()
1.4.1 静态内部类对象的创建格式
外部类.内部类 变量 = new 外部类.内部类构造器;
代码演示:
// 外部类:Outer01
class Outer01{private static String sc_name = "小白";private String sc_age = 24;// 内部类: Inner01public static class Inner01{// 这里面的东西与类是完全一样的。private String name;public Inner01(String name) {this.name = name;}public void showName(){System.out.println(this.name);// 拓展:静态内部类可以直接访问外部类的静态成员。System.out.println(sc_name);//访问外部类的非静态的变量需要创建外部类的对象Outer01 outer01 = new Outer01();System.out.println(outer.sc_age);}}
}public class InnerClassDemo01 {public static void main(String[] args) {// 创建静态内部类对象。// 外部类.内部类 变量 = new 外部类.内部类构造器;Outer01.Inner01 in = new Outer01.Inner01("张三");in.showName();}
1.5 局部内部类
将内部类定义在方法里面就叫做局部内部类,类似于方法中的局部变量
外部类是无法直接获取局部内部类的,需要创建该类的对象,然后再进行使用
该类可以直接访问外部类的成员,也可以访问方法内的局部变量
public class Outer {private int outerField = 10;public void outerMethod() {final int localVar = 20;//局部内部类class LocalInner {void display() {System.out.println("Outer Field: " + outerField);System.out.println("Local Variable: " + localVar);}}//外部类获取内部类信息,需要创建对象LocalInner inner = new LocalInner();inner.display();}public static void main(String[] args) {Outer outer = new Outer();outer.outerMethod();}
}
1.6 匿名内部类
1.6.1 引出匿名内部类
正常类:
匿名内部类(Student被匿名):
代码演示:
interface Swim {public abstract void swimming();
}public class Demo07 {public static void main(String[] args) {// 使用匿名内部类对象,并且调用匿名内部类里面的方法new Swim() {@Overridepublic void swimming() {System.out.println("自由泳...");}}.swimming();// 接口 变量 = new 实现类(); // 多态,走子类的重写方法Swim s2 = new Swim() {@Overridepublic void swimming() {System.out.println("蛙泳...");}};s2.swimming();s2.swimming();}
}
注意:
new Swim(){@Overridepublic void swim() {System.out.println("Demo01匿名内部类");} };
这样的话是不会有打印数据的,因为整体只是一个匿名内部类对象,需要再去调用相应的成员
匿名内部类字节码文件反编译看到的效果
实际案例:
public class Test01 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("11");list.add("12");list.add("13");//下面就是一个匿名内部类list.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});}
}
反编译之后
1.6.2 匿名内部类用处
匿名内部类在Java中有着一些重要的用途,其中包括:
-
简化代码:使用匿名内部类可以减少代码量,避免编写大量的类定义。
-
事件处理器:在GUI编程中常常使用匿名内部类来实现事件处理器,如按钮点击事件、菜单项选择等。
-
回调函数:匿名内部类也可以用作回调函数的实现,例如对异步任务的处理。
-
接口实现:如果只需要使用接口的一次实例,可以直接使用匿名内部类来实现接口的抽象方法。
-
方法重写:可以在匿名内部类中重写父类或接口的方法,以实现特定的逻辑。
总之,匿名内部类提供了一种简洁、灵活的方式来实现某些具体功能,通常用于临时、一次性的场景中。
1.6.3 匿名内部类的使用场景
interface Swim {public abstract void swimming();
}public class Demo07 {public static void main(String[] args) {// 普通方式传入对象// 创建实现类对象Student s = new Student();goSwimming(s);// 匿名内部类使用场景:作为方法参数传递Swim s3 = new Swim() {@Overridepublic void swimming() {System.out.println("蝶泳...");}};// 传入匿名内部类goSwimming(s3);// 完美方案: 一步到位goSwimming(new Swim() {public void swimming() {System.out.println("大学生, 蛙泳...");}});goSwimming(new Swim() {public void swimming() {System.out.println("小学生, 自由泳...");}});}// 定义一个方法,模拟请一些人去游泳public static void goSwimming(Swim s) {s.swimming();}
}
总结: