15Java基础之内部类

内部类

  • 内部类是类中五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。
  • 场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
    image

内部类有四种形式

  1. 成员内部类
  • 就是类中的一个普通成员,类似我们学过的普通的成员变量、成员方法。
    image

注意:JDK16之前,成员内部类中不能定义静态成员,JDK16开始才可以定义静态成员了。

创建内部成员对象的格式:
外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
Outer.Inner in = new Outer().new Inner();

成员内部类的特点

  • 无static修饰,属于外部类的对象持有的
  • 必须存在外部类对象,才会有这个内部类
  • 拓展:成员内部类访问外部类的成员特点
    • 成员内部类的实例方法中,是可以直接访问外部类的实例成员、静态成员的。
    • 成员内部类的实例方法中,拿到当前外部类对象,格式是:外部类名.this。
      案例:
// 外部类
public class Outer {
    public static String schoolName = "霍格沃兹";
    public static void inAdder(){
        System.out.println("我是外部类的静态方法");
    }
    private String hobby;
    private double height;
    public void run(){
        System.out.println("run");
    }

    // 成员内部类
    // 特点:无static修饰,属于外部类的对象持有的
    // 必须存在外部类对象,才会有这个内部类
    public class Inner{
        private String name;
        private int age;

        public Inner() {
        }

        public Inner(String name, int age) {
            this.name = name;
            this.age = age;
        }

        //拓展:成员内部类访问外部类的成员特点
        public void show(){
            System.out.println("我是成员内部类的方法");
            // 成员内部类中,是可以直接访问外部类的静态成员的
            System.out.println(schoolName);
            inAdder();

            // 成员内部类中,可以直接访问外部类的实例对象。
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }
    }
}

测试:
// 目标:掌握成员内部类,搞清楚语法即可。
public class Test {
    public static void main(String[] args) {
        //创建外部类对象
        Outer out = new Outer();
        //创建内部类对象
        //格式:外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
        Outer.Inner in = new Outer().new Inner();
        in.show();
    }
}

  1. 静态内部类
  • 有static修饰的内部类,属于外部类自己持有。
    image

创建对象的格式

  • 外部类.内部类 对象名 = new 外部类名.静态内部类名();
    Outer.Inner in = new Outer.Inner();

静态内部类中的访问外部类成员的特点

  • 可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员。

案例:

//外部类
public class Outer {
    public static String schoolName = "霍格沃兹";
    public static void inAdder(){
        System.out.println("我是外部类的静态方法");
    }

    private String hobby;
    private double height;
    public void run(){
        System.out.println("run");
    }

    //静态内部类:static修饰,属于外部类本身
    public static class Inner{
        // 类有的成员它都有
        private String name;
        private int age;

        public Inner() {
        }

        public Inner(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public void show(){
            System.out.println("我是成员静态内部类的方法");
            // 1. 静态内部类中,是可以直接访问外部类的静态成员。
            System.out.println(schoolName);
            inAdder();
            // 2. 静态内部类中,是不可以直接访问外部类的实例成员
            //System.out.println(hobby); // 报错
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }
    }
}
测试:
// 目标:认识静态内部类,搞清楚其特点
public class Test {
    public static void main(String[] args) {
        // 静态内部类的定义
        // 外部类.内部类 对象名 = new 外部类名.new 静态内部类名();
        Outer.Inner in = new Outer.Inner();
        in.show();
    }
}

  1. 局部内部类
  • 局部内部类是定义在方法中、代码块中、构造器等执行体中。
    案例:
//目标:了解局部内部类,定义在方法里,构造器里,代码块里等局部范围里的类。
public class Test {
    public static void main(String[] args) {

        // 局部内部类(鸡肋语法)
        class A{
            public void show(){
                System.out.println("我是局部内部类的方法");
            }
        }

        A a = new A();
        a.show();

    }
}

  1. 匿名内部类(重点)
  • 就是一种特殊的局部内部类。所谓的匿名:指的是程序员不需要为这个类声明名字。
    image
  • 特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
  • 作用:用于更方便的创建一个子类对象。

案例

// 目标:认识匿名内部类
public class Test {
    public static void main(String[] args) {
        // 匿名内部类本质是一个子类,同时会立即创建一个子类对象
        Animal a = new Animal(){
            @Override
            public void cry() {
                System.out.println("狗是汪汪的叫~");
            }
        };
        a.cry();
    }
}

/*
class Dog extends Animal{

    @Override
    public void cry() {
        System.out.println("狗是汪汪的叫~");
    }
}
*/

abstract class Animal{
    public abstract void cry();
}

匿名内部类的常见使用场景

  • 通常作为一个参数传输给方法。

案例:

需求:学生和老师一起参加游泳比赛

//目标:匿名内部类的使用场景,通常作为一个对象参数传递给方法使用
public class Test {
    public static void main(String[] args) {
        // 创建匿名内部类
        Swimming s = new Swimming() {
            @Override
            public void swim() {
                System.out.println("学生游泳贼快!");
            }
        };
        goSwimming(s);
        goSwimming(new Swimming() {

            @Override
            public void swim() {
                System.out.println("老师游的贼慢~");
            }
        });

    }

    public static void goSwimming(Swimming s){
        System.out.println("开始。。。");
        s.swim();
        System.out.println("结束了。。。");
    }
}

//需求:学生和老师一起参加游泳比赛
interface Swimming{
    void swim();
}

匿名类的拓展

案例:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

// 拓展:掌握匿名内部类的真实场景。
public class Test2 {
    public static void main(String[] args) {
        //GUI SWING编程:桌面编程
        //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) {
                System.out.println("点击我,我要登录!");
                JOptionPane.showMessageDialog(win, "没事别点我!");
            }
        });

        //2. 设计大小,居中显示
        win.setSize(400, 300);
        win.setLocationRelativeTo(null);
        win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        win.setVisible(true);
    }
}
posted @ 2025-07-27 20:23  狂风将军  阅读(18)  评论(0)    收藏  举报