Java内部类的应用分析

最近看了几篇博客,又温习了一次内部类相关的内容,感觉有必要在这方面写点博客记录一下,毕竟我个人接触的也不多,平时写代码也不常用,方便以后再次温习。

啥是内部类呢,简单来说就是写在类里面的类(Inner Class),也被叫做嵌套类(Nested Class)
 

class Outer {
    class Inner {
        // 定义了一个Inner Class
    }
}

具体的介绍可以看这里:内部类 - Java教程 - 廖雪峰的官方网站 (liaoxuefeng.com),我在这里就不多赘述了。

内部类是一个统称,具体的分类有哪些呢?

内部类的主要应用

  • 访问外部类的私有成员,类似于写一个getter/setter方法,提供了一个外部管理私有字段的方法。我们来举个例子:
    public class Outer {
        private String outerField = "Hello from Outer Class!";
    
        // 成员内部类
        class Inner {
            void displayOuterField() {
                // 内部类访问外部类的私有成员
                System.out.println(outerField);
            }
        }
    
        // 创建内部类的实例并调用其方法
        void createInner() {
            Inner inner = new Inner();
            inner.displayOuterField();
        }
    
        public static void main(String[] args) {
            Outer outer = new Outer();
            outer.createInner();  // 调用外部类的方法
        }
    }
    

  • 封装代码,从第一条就能看出来。
  • 简化代码结构,例如想要手动实现一个表,那么这个表的数据结构肯定会占很大篇幅,这时候不妨把代码放到内部类,和其他逻辑区分开。比如我们来写一个图的结构:
    import java.util.ArrayList;
    import java.util.List;
    
    public class Graph {
        // 内部类表示图的顶点
        class Vertex {
            String name;
            List<Vertex> adjacentVertices;
    
            // 构造函数
            Vertex(String name) {
                this.name = name;
                this.adjacentVertices = new ArrayList<>();
            }
    
            // 添加邻接顶点
            void addAdjacent(Vertex vertex) {
                adjacentVertices.add(vertex);
            }
    
            // 打印顶点及其邻接顶点
            void display() {
                System.out.print("Vertex: " + name + " is connected to: ");
                for (Vertex v : adjacentVertices) {
                    System.out.print(v.name + " ");
                }
                System.out.println();
            }
        }
    
        private List<Vertex> vertices;
    
        // 构造函数
        public Graph() {
            this.vertices = new ArrayList<>();
        }
    
        // 添加顶点
        public Vertex addVertex(String name) {
            Vertex vertex = new Vertex(name);
            vertices.add(vertex);
            return vertex;
        }
    
        // 打印所有顶点
        public void displayGraph() {
            for (Vertex vertex : vertices) {
                vertex.display();
            }
        }
    
        public static void main(String[] args) {
            Graph graph = new Graph();
            Graph.Vertex v1 = graph.addVertex("A");
            Graph.Vertex v2 = graph.addVertex("B");
            Graph.Vertex v3 = graph.addVertex("C");
    
            // 添加邻接关系
            v1.addAdjacent(v2);
            v1.addAdjacent(v3);
            v2.addAdjacent(v3);
    
            // 打印图的信息
            graph.displayGraph();
        }
    }
    

  • 处理监听事件,这个和c#的事件委托机制很像,例如有了内部类,可以把所有鼠标点击回调的逻辑放到一个内部类里,以后需要添加或修改鼠标点击的逻辑的时候,只需要修改这个内部类就可以了
    举个例子:
    import javax.swing.JButton;
    import javax.swing.JFrame;
    
    public class ButtonExample {
        private String buttonLabel = "Click me!";
    
        public ButtonExample() {
            JFrame frame = new JFrame();
            JButton button = new JButton(buttonLabel);
    
            // 成员内部类作为事件监听器
            button.addActionListener(new ButtonClickListener());
    
            frame.add(button);
            frame.setSize(200, 200);
            frame.setVisible(true);
        }
    
        // 内部类
        class ButtonClickListener implements java.awt.event.ActionListener {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                System.out.println("Button clicked! Label: " + buttonLabel);
            }
        }
    
        public static void main(String[] args) {
            new ButtonExample();
        }
    }
    

  • 实现接口,或者多重继承,我们不想让外部访问到我们的实现方式,只需要在私有的内部类里面写接口的实现即可。
    // 定义接口
    interface Animal {
        void makeSound();  // 声明一个抽象方法
    }
    
    // 外部类
    public class AnimalShelter {
        
        // 成员内部类 Dog
        private class Dog implements Animal {
            @Override
            public void makeSound() {
                System.out.println("Woof!");  // 实现狗叫声
            }
        }
    
        // 成员内部类 Cat
        private class Cat implements Animal {
            @Override
            public void makeSound() {
                System.out.println("Meow!");  // 实现猫叫声
            }
        }
    
        // 方法来创建并使用内部类
        public void adoptAnimals() {
            Animal dog = new Dog();  // 创建 Dog 对象
            Animal cat = new Cat();   // 创建 Cat 对象
    
            dog.makeSound();  // 调用 Dog 的方法
            cat.makeSound();  // 调用 Cat 的方法
        }
    
        public static void main(String[] args) {
            AnimalShelter shelter = new AnimalShelter(); // 创建 AnimalShelter 对象
            shelter.adoptAnimals(); // 调用 adoptAnimals 方法
        }
    }
    

    至于静态内部类,大多是在设计模式中应用,例如实现工厂模式中的工厂类:

    public class Outer {
        private static int count = 0;
    
        // 静态内部类
        static class Inner {
            private int id;
    
            Inner() {
                this.id = ++count;  // 为每个内部类实例分配一个唯一 ID
            }
    
            public int getId() {
                return id;
            }
        }
    
        public static void main(String[] args) {
            Inner inner1 = new Inner();
            Inner inner2 = new Inner();
    
            System.out.println("Inner 1 ID: " + inner1.getId());  // 输出:Inner 1 ID: 1
            System.out.println("Inner 2 ID: " + inner2.getId());  // 输出:Inner 2 ID: 2
        }
    }
    

    方法内部类我用的较少,但是还是举个例子,这是用局部内部类(方法内部类)进行临时算法的封装

    public class Calculator {
        
        public double calculate(int base, int exponent) {
            
            // 局部静态类用于计算幂
            class PowerCalculator {
                double calculatePower() {
                    return Math.pow(base, exponent);
                }
            }
            
            PowerCalculator powerCalculator = new PowerCalculator();
            return powerCalculator.calculatePower();  // 调用局部静态类的方法
        }
    
        public static void main(String[] args) {
            Calculator calculator = new Calculator();
            double result = calculator.calculate(2, 3);  // 2的3次方
            System.out.println("Result: " + result);  // 输出:Result: 8.0
        }
    }
    

匿名内部类比较特殊,不需要变量名,创建时自带一个生命周期,在生命周期内自动被调用,也就是说,匿名内部类一般和其他的类或者方法是绑定在一起的,由其他的类或方法来控制其行为。它的应用大概有这些:

  • 事件处理,这里先给出一个例子
    import javax.swing.JButton;
    import javax.swing.JFrame;
    
    public class ButtonExample {
        public static void main(String[] args) {
            JFrame frame = new JFrame("Button Example");
            JButton button = new JButton("Click me!");
    
            // 使用匿名内部类实现 ActionListener
            button.addActionListener(new java.awt.event.ActionListener() {
                @Override
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    System.out.println("Button clicked!");
                }
            });
    
            frame.add(button);
            frame.setSize(200, 200);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    }
    

    这里和C#的事件委托机制是一样的,只是java有些区别罢了,创建的事件类并没有一个确切的名字,它单纯是和我们的buttonclick绑定在了一起,每次这个按钮被点击,就会激活这个事件,但是具体这个事件较什么名字我们并不清楚,只知道要让这个事件去做一些事,调一些函数。

  • 代码简化
    public class AnimalExample {
        public static void main(String[] args) {
            // 使用匿名内部类实现接口
            Animal dog = new Animal() {
                @Override
                public void makeSound() {
                    System.out.println("Woof!");
                }
            };
    
            dog.makeSound();  // 输出:Woof!
        }
    }
    
  • 实现比较器,集合排序的时候是需要一个比较器的,也就是我们排序需要一个规则,这和数据库的理论很像,这个时候我们可以用匿名内部类来实现Comparator接口:
    import java.util.Arrays;
    import java.util.Comparator;
    
    public class SortExample {
        public static void main(String[] args) {
            String[] names = {"Alice", "Bob", "Charlie"};
    
            // 使用匿名内部类实现Comparator
            Arrays.sort(names, new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return s1.length() - s2.length();  // 按字符串长度排序
                }
            });
    
            System.out.println(Arrays.toString(names));  // 输出:[Bob, Alice, Charlie]
        }
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FurryMonster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值