1、 内部类:
是类中五大成分之一(成员变量、方法、构造函数、内部类、代码块),如果一个类定义在另一个 类的内部,这个类就是内部类。
场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
内部类的四种形式:
成员内部类:了解
静态内部类:了解
局部内部类:了解
匿名内部类:重点
成员内部类:
就是类中的一个普通成员,类似前面我们学过的普通的成员变量、成员方法。
Outer类:
内含内部类:
package cn.ensource.d1_inner_class1;public class Outer {private int age = 99;public static String a;// 普通成员内部类public class Inner{private String name;private int age = 88;public static String schoolName; // JDK16才支持静态成员的public void test() {System.out.println(age);System.out.println(a);int age = 66;// 66System.out.println(age);// 88System.out.println(this.age);// 99System.out.println(Outer.this.age);}public String getName() {return name;}public void setName(String name) {this.name = name;}}
}
测试类:
package cn.ensource.d1_inner_class1;public class Test {public static void main(String[] args) {// 目标:了解成员内部类Outer.Inner in = new Outer().new Inner();in.test();}
}
注意:
JDK16之前,成员内部类中不能定义静态成员,JDK16开始也可以定义静态成员了。
创建对象的格式:
成员内部类中访问其他成员的特点:
1)和前面学过的实例方法一样,成员内部类的实例方法中,同样可以直接访问外部类的实例成员、静态成员。
2)可以在成员内部类的实例方法中,拿到当前外部类对象,格式: 外部类名.this
静态内部类:
所谓静态内部类,有static修饰符的内部类,属于外部类自己持有。
静态内部类是外部类持有的。
Outer类:包含静态内部类:
package cn.ensource.d1_inner_class2;public class Outer {private int age;public static String schoolName;// 静态内部类public static class Inner {private String name;public static int a;public void test() {
// System.out.println(age); // 只能通过外部类对象访问System.out.println(schoolName);}public String getName() {return name;}public void setName(String name) {this.name = name;}public static int getA() {return a;}public static void setA(int a) {Inner.a = a;}}public static void test2() {System.out.println(schoolName);
// System.out.println(age);}
}
测试类:
package cn.ensource.d1_inner_class2;public class Test {public static void main(String[] args) {// 目标:了解静态内部类Outer.Inner in = new Outer.Inner();in.getName();in.test();}
}
特别要注意的是:
可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员。
外部类的实例成员只能通过外部类对象来访问。
局部内部类:
局部内部类是定义在方法中,代码块中,构造器等执行体中。
匿名内部类:(重点)
就是一种特殊的局部内部类;所谓匿名:指的是程序员不需要为这个类声明名字。
package d3_inner_class3;public class Test {public static void main(String[] args) {// 目标:掌握匿名内部类,并掌握其作用Animal a = new Cat(); // 创建子类对象a.cry();}
}class Cat extends Animal {@Overridepublic void cry() {System.out.println("喵喵~");}
}abstract class Animal {public abstract void cry();
}
进化:
package d3_inner_class3;public class Test {public static void main(String[] args) {// 目标:掌握匿名内部类,并掌握其作用
// Animal a = new Cat(); // 创建子类对象
// a.cry();// 我们只要创建一下子类对象就可以了,不需要经常性的创建子类// 匿名内部类// 把这个匿名内部类编译成一个子类,然后会立即创建一个子类出来Animal a = new Animal() {@Overridepublic void cry() {System.out.println("喵喵~");}};a.cry();}
}class Cat extends Animal {@Overridepublic void cry() {System.out.println("喵喵~");}
}abstract class Animal {public abstract void cry();
}
匿名内部类的概念。
匿名内部类本质上是不是一个子类呢?
反编译可以看到这个匿名类是Animal的子类。
编译生成一个匿名的构造方法。
并且有内部方法cry方法。
特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
作用:用于更方便地创建一个子类对象。
匿名内部类的常见使用场景:
通常作为一个参数传递给方法。
package d3_inner_class3;public class Test2 {public static void main(String[] args) {// 目标:掌握匿名内部类的使用场景:Swimming s1 = new Swimming(){@Overridepublic void swim() {System.out.println("狗游泳!");}};go(s1);Swimming s2 = new Swimming() {@Overridepublic void swim() {System.out.println("猫游泳!");}};go(s2);}// 设计一个方法,可以接收swimming接口的一切实现类对象进来参加游泳比赛// go 表示开始参加比赛public static void go(Swimming s) {System.out.println("开始----------");s.swim();}
}// 猫和狗都要参加有用比赛
interface Swimming{void swim();
}
匿名内部类有啥特点:
匿名内部类本质上就是一个子类,并会立即创建出一个子类对象。
匿名内部类有啥作用、应用场景?
可以更方便创建出一个子类对象。
匿名内部类通常作为一个参数传递给方法。
拓展:
package cn.ensource.d4_inner_class5;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class Test {public static void main(String[] args) {// 拓展:内部类在开发中的真实使用场景// GUI编程:// 1. 创建窗口JFrame win = new JFrame("登录");JPanel panel = new JPanel();win.add(panel);JButton btn = new JButton("登录");panel.add(btn);// 给按钮绑定单击事件监听器// 调别人的匿名内部类,需要用的时候才用// 真实应用场景btn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {JOptionPane.showMessageDialog(win, "登录一下");}});win.setSize(400, 400);win.setLocationRelativeTo(null);win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);win.setVisible(true);}
}
最终目的是为了简化代码。
箭头语法后面会讲得。
匿名内部类,我们需要的时候才会用。