本文讲解如何在抽象基类的静态main方法中,根据运行时调用的子类名(如java mone 5)自动识别并实例化对应的具体子类,从而调用其multiply()方法完成计算,避免硬编码、实现灵活可扩展的命令行工具模式。
在Java中,抽象基类无法直接实例化,但其main方法作为程序入口点仍可被继承类间接调用——关键在于:main方法属于类,而非对象;它不依赖于当前类是否被实例化,而取决于JVM启动时指定的主类。因此,当执行 java MOne 5 时,JVM实际加载并运行的是 MOne 类的 main 方法(若未重写,则继承自 Calculation),此时 this 的运行时类型就是 MOne。
但原问题中 Calculation.main() 是 static 且 final 的,无法被重写,且希望所有子类共用同一份逻辑(解析参数、调用 multiply),同时又能“知道自己是谁”。最简洁、健壮且符合JVM机制的解法是:利用反射获取当前正在执行 main 方法的类(即启动类),然后实例化它——无需扫描整个类路径,也无需第三方库。
以下是推荐实现(零依赖、高效、安全):
public abstract class Calculation {
public abstract int multiply(int x);
public static void main(String[] args) {
// 1. 获取当前正在执行 main 的具体类(如 MOne、MTwo)
Class callerClass = null;
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
if ("main".equals(e.getMethodName()) && e.getClassName() != Calculation.class.getName()) {
try {
callerClass = Class.forName(e.getClassName());
break;
} catch (ClassNotFoundException ignored) {}
}
}
if (callerClass == null || !Calculation.class.isAssignableFrom(callerClass)) {
System.err.println("Error: No valid Calculation subclass found in call stack.");
return;
}
// 2. 实例化该子类(要求有无参构造器)
Calculation instance;
try {
instance = (Calculation) callerClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
System.err.println("Failed to instantiate " + callerClass.getSimpleName() + ": " + e.getMessage());
return;
}
// 3. 解析参数并调用 multiply
if (args.length == 0) {
System.out.println("Usage: java ");
return;
}
try {
int x = Integer.parseInt(args[0]);
System.out.println(instance.multiply(x));
} catch (NumberFormatException e) {
System.err.println("Invalid number argument: " + args[0]);
}
}
}
配套子类保持原样(确保有默认构造器):
立即学习“Java免费学习笔记(深入)”;