如何在抽象基类的 main 方法中动态实例化并调用具体子类-java教程

本文介绍一种专业、可行的方式,让抽象基类 `calculation` 的 `main` 方法能自动发现并实例化所有继承它的具体子类(如 `mone`、`mtwo`),从而实现 `java mone 5` 等命令直接输出对应计算结果。核心在于运行时类路径扫描与反射实例化。

要实现在抽象基类 Calculation 的 main 方法中调用不同子类的 multiply() 方法,关键在于脱离“硬编码 new”,转而采用运行时动态发现 + 反射创建实例的策略。因为 main 方法位于抽象类中,它无法直接 new Calculation(),但可通过类路径扫描识别所有非抽象子类,并逐一实例化执行。

✅ 推荐方案:使用 ClassGraph 实现子类自动发现

ClassGraph 是一个高性能、轻量级的类路径扫描库,可安全、高效地枚举继承自指定基类的所有具体类(即非抽象、非接口的子类)。以下是完整可运行的改进版 Calculation 类:

import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;

import java.util.List;

public abstract class Calculation {
    public abstract int multiply(int x);

    public static void main(String[] args) {
        if (args.length == 0) {
            System.err.println("Usage: java  ");
            return;
        }

        try {
            // 解析输入参数(取第一个作为待计算数值)
            int input = Integer.parseInt(args[0]);

            // 扫描所有 Calculation 的具体子类
            List<Class> subclasses;
            try (ScanResult scanResult = new ClassGraph()
                    .enableClassInfo()
                    .acceptPackages("your.package.name") // ? 替换为你的实际包名,提升性能与安全性
                    .scan()) {

                subclasses = scanResult
                        .getSubclasses(Calculation.class.getName())
                        .filter(classInfo -> !classInfo.isAbstract()) // 排除抽象子类(如有)
                        .loadClasses();
            }

            // 对每个具体子类实例化并调用 multiply
            for (Class clazz : subclasses) {
                try {
                    Calculation instance = clazz.getDeclaredConstructor().newInstance();
                    int result = instance.multiply(input);
                    System.out.println(clazz.getSimpleName() + ": " + result);
                } catch (Exception e) {
                    System.err.println("Failed to instantiate or invoke " + clazz.getName() + ": " + e.getMessage());
                }
            }

        } catch (NumberFormatException e) {
            System.err.println("Invalid number argument: " + args[0]);
        }
    }
}

? 重要注意事项:✅ 子类(如 MOne)必须提供无参构造函数(默认即满足),否则 newInstance() 或 getDeclaredConstructor().newInstance() 会抛出异常;✅ 建议通过 .acceptPackages(…) 显式限定扫描范围,避免全类路径扫描带来的性能开销和潜在安全风险;✅ 若子类位于模块化环境(Java 9+),需确保 module-info.java 中 opens 相应包以支持反射访问;❌ 不推荐使用已弃用的 Class.newInstance()(Java 9+ 已标记为 deprecated),应统一使用 getDeclaredConstructor().newInstance()。

? 为什么不建议“在 main 中直接 new 子类”?

你可能会想到在 Calculation.main() 中写类似 new MOne().multiply(x) 的代码——但这违背了面向对象的开放封闭原则(OCP):每新增一个子类(如 MFour),就必须修改基类源码,丧失可扩展性。而上述 ClassGraph 方案实现了零侵入式扩展:只要新子类编译后在类路径中,且继承 Calculation,即可被自动识别并执行。

✅ 验证方式(终端命令)

确保所有类(Calculation, MOne, MTwo, MThree)已编译,并在类路径中:

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » 如何在抽象基类的 main 方法中动态实例化并调用具体子类-java教程
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1392+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4004944+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1392+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4004945+
  • 本周更新: 0+
  • 最后更新: 2026-03-16