【问题标题】:Getting the name of class in inherited static method in Java在Java中继承的静态方法中获取类的名称
【发布时间】:2018-09-21 11:32:18
【问题描述】:

假设我想用 Java 解决一堆 Project Euler 问题,而不是为每个问题类提供其自己的 main 方法的样板文件,而是继承它并拥有一个“解决”方法。

有没有办法让问题类的名称与解决方案一起打印出来?

我有什么:

abstract class Problem {

    private static String problemName = ???

    public static void main(String[] args) {
//  If I could summon an instance of the sub-class then it would be easy
//        Problem p = new ... what?
        System.out.println(problemName + ": " + solve());
    }

    abstract static long solve();
// oops, you can't do abstract static in Java :(
}

然后

public class Euler_001 extends Problem {
    static long solve() {...}
}

问题在于,获取 this answer 中给出的类名的各种 hack 返回“Problem”,而不是“Euler_001”。

我想我必须实例化问题类,但是我该怎么做呢?

【问题讨论】:

  • new Euler_001()?

标签: java inheritance java-8 static


【解决方案1】:

静态上下文无助于父需要调用子的继承。使用带有抽象的实例:

abstract class Problem {

    public static void main(String[] args) throws Exception {

        Problem problem;

        //Now, depending on where the exact problem is specified:

        //Class known at compile time
        problem = new Euler_001();

        //Class passed as parameter
        problem = (Problem) Class.forName(args[0]).getConstructor().newInstance();

        System.out.println(problem.getProblemName() + ": " + problem.solve());
    }

    abstract long solve();
    abstract String getProblemName();
}

并且子类将提供一个覆盖抽象方法的普通实现:

class Euler_001 extends Problem {
    @Override
    long solve() {
         return 0;
     }

    @Override
    String getProblemName() {
        return "????";
    }
}

根据您的配置方法,您可以在父类的 main 方法内基于类名创建具体类的实例。

这样,Problem 类可以被调用:

java com.mypackage.Problem "com.mypackage.Euler_001"

【讨论】:

  • 如果我理解正确,OP 要求提供标记为“作为参数传递的类”的构造函数。如果是这样,可以删除标记为“编译时已知的类”的行。
  • 真的我只是想右键单击并选择在 IntelliJ 中运行而不添加额外的样板,但如果我必须通过将问题名称放入运行配置来做到这一点,我想这并不太费力(如果这是一个具有潜在重构的更复杂的应用程序,虽然不是很好)。我更好奇它是否可以以某种干净和简单的方式“完成”。谢谢
  • @LuigiPlinge 如果您希望能够只运行一个特定的问题,那么更好的方法是反转链接:在Euler_001 或其他子类中拥有main。但这样一来,继承就变得无用了,因为没有任何东西可以从父级重用
【解决方案2】:

静态变量和方法不能被覆盖 - 它们会被替换。所以,根据我的理解,我们需要创建子类的实例。
我检查了 -
问题 p = new Euler_001();
System.out.println(p.getClass().getSimpleName()); //打印 Euler_001

【讨论】:

  • 不幸的是,这对Euler_002 或其他所有问题都没有好处!
  • 确实如此,但正如问题中所问的那样,您将如何在main 方法中创建子类的实例?
  • @LuigiPlinge - 使用反射我们可以创建类实例,然后使用 instanceof 条件检查它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-06
  • 1970-01-01
  • 2012-05-04
相关资源
最近更新 更多