一. 成员内部类 [了解]
注意:JDK16之前,成员内部类中不能定义静态成员。
1. 如何创建一个成员内部类?
public class Outer {
//成员外部类
public class Inner {
//成员内部类
}
}
2. 如何创建成员内部类对象?
格式:
外部类名.内部类名 对象名 = new 外部类(...).new 内部类();
public class main {
public static void main(String[] args) {
Outer.Inner in = new Outer().new Inner();
}
}
3. 如何调用成员内部类中的方法?
public class Outer {
public class Inner {
public void test() {
//方法内容
}
}
}
public class main {
public static void main(String[] args) {
Outer.Inner in = new Outer.new Inner();
in.test();
}
}
4. 当成员外部类和成员内部类存在相同变量时该如何调用?
public class Outer {
private int age = 99;
public class Inner {
private int age = 88;
public void test() {
int age = 77;
System.out.println(age); //77
System.out.println(this.age); //88
System.out.println(Outer.this.age); //99
}
}
}
二. 静态内部类 [了解]
1. 如何创建一个静态内部类
参照成员内部类,只需要在定义成员内部类的时候在前面加上static关键词修饰
public class Outer {
///静态内部类
public static class Inner {
//类内容
}
}
2.如何创建静态内部类对象?
格式:
外部类.静态内部类 对象名 = new 外部类.静态内部类();
public class Main() {
public static void main(String[] args) {
Outer.Inner in = new Outer.Inner();
}
}
3. 静态内部类中访问外部类成员的特点
可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员。
三. 局部内部类 [了解]
局部内部类是定义在方法中,代码块中,构造器等执行体中的类。
黑马老师提醒:鸡肋语法,看看就好
public class Main {
public static void main(String[] args) {
}
public static void go() {
class A {
}
abstract class B {
}
interface C {
}
}
}
四. 匿名内部类 [重要]
定义:一种特殊的局部内部类,所谓匿名,指的是程序员不需要为这个类声明名字。
匿名类本质就是一个字类,而且会立即创建一个字类对象。
new 类或接口(参数值..) {
类体(一般是方法重写);
};
1. 了解匿名内部类
首先,我们通过一个例子来了解什么是匿名内部类呢?请看下面的代码:
public class Main {
public static void main(String[] args) {
Animal a = new Cat();
a.cry();
}
}
class Cat extends Animal {
@Override
public void cry {
System.out.println("喵喵叫~~~~");
}
}
abstract class Animal {
public abstract void cry();
}
在上面的实例中,我们定义了一个Animal类,并在其中添加了抽象方法cry,此时,如果我们想添加一个Cat类,让Cat继承Animal类,并在cry时发出”喵喵叫~“,就需要在Main类之外定义一个Cat类,再去这个里面写cry方法,然后去Main中创建对象并调用cry方法,这种实现过程比较复杂,所以我们引入”匿名内部类“,请看下文:
public class Main {
public static void main(String[] args) {
Animal a = new Animal() {
@Override
public void cry() {
System.out.println("小猫喵喵叫~~");
}
};
a.cry();
}
}
abstract class Animal {
public abstract void cry();
}
怎么样,代码是不是简化了很多?这里所用到的,就是匿名内部类!
2. 匿名内部类的常见使用场景
1. 通常作为一个参数传输给方法。
请看下面的代码:
public class Main {
public static void main(String[] args) {
Swimming s1 = new Swimming() {
@Override
public void swim() {
System.out.println("狗游得快");
}
};
go(s1);
}
//设计一个方法,可以接收swimming接口的一切实现类对象进来参加游泳比赛
public static void go(Swimming s) {
System.out.println("开始--------------------");
s.swim();
}
}
//猫和狗都要参加游泳比赛
interface Swimming {
void swim();
}
在上述情况中,我们创建一个s1对象,并在里面写上独有的“狗游泳”方法,再将s1传递给go方法。
而实际上我们可以直接将整个s1作为一个参数进行传输,如下:
public class Main {
public static void main(String[] args) {
go(new Swimming() {
@Override
public void swim() {
System.out.println("狗游得快");
}
});
}
//设计一个方法,可以接收swimming接口的一切实现类对象进来参加游泳比赛
public static void go(Swimming s) {
System.out.println("开始--------------------");
s.swim();
}
}
//猫和狗都要参加游泳比赛
interface Swimming {
void swim();
}
2. 实际运用
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test {
public static void main(String[] args) {
//扩展: 搞清楚匿名内部类在开发中的真实使用场景
//1. 创建窗口
JFrame win = new JFrame("登陆界面");
JPanel panel = new JPanel();
win.add(panel);
JButton btn = new JButton("登陆");
panel.add(btn);
//给按钮绑定单击事件监听器
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win,"登陆一下");
}
});
win.setSize(400,400);
win.setLocationRelativeTo(null); //居中
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
win.setVisible(true);
}
}
在后面的内容中,将会学到新的知识来简化这种语法:
import javax.swing.*;
public class Test {
public static void main(String[] args) {
//扩展: 搞清楚匿名内部类在开发中的真实使用场景
//1. 创建窗口
JFrame win = new JFrame("登陆界面");
JPanel panel = new JPanel();
win.add(panel);
JButton btn = new JButton("登陆");
panel.add(btn);
//给按钮绑定单击事件监听器
btn.addActionListener(e -> JOptionPane.showMessageDialog(win,"登陆一下"));
win.setSize(400,400);
win.setLocationRelativeTo(null); //居中
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
win.setVisible(true);
}
}