繁体   English   中英

从 static 获取子 class 父 class 在 Java 中的方法

[英]getting child class from static method of parent class in Java

假设我有这些课程:

public class ChildClass extends ParentClass
{
    // some class definition here
}


public abstract class ParentClass
{
    public static void printClass()
    {
        // get the class that extends this one (and for example, print it)
    }

    // some class definition here
}

假设在调用ParentClass.printClass()时我想打印 class 的名称(就像做System.out.println(ParentClass.class) )。 然后扩展ParentClass (例如在ChildClass )并调用ChildClass.printClass()时,我希望它打印扩展的名称 class (就像做System.out.println(ChildClass.class) )。 这有可能吗?

我找到了一种通过使用MethodHandles.lookup().lookupClass()从 static 方法内部获取 class 的方法,但是当在ParentClass.printClass内部使用它并扩展 ParentClass,然后在扩展 Class 上调用printClass时,我总是得到 class 的ParentClass

引用@RealSkeptic

Static 方法不被继承。 您可以调用 ChildClass.printClass() 的事实只是语法糖。 它实际上总是调用 ParentClass.printClass()。 所以你不能用 static 方法做类似的事情,只能用一个可继承的非静态方法。

static 方法最好被认为完全存在于 class 本身之外。 它们确实出现在类中的原因是 java(语言)本身的设计:类型不仅仅是具有层次结构的类型,它们还充当 java 命名空间系统的主要载体。

类型存在于包中,包是类型的顶级命名空间概念。 那么如何引用方法呢? 只有一种方法:通过类型系统。 因此,static 方法必须放在一个类型中。 但这就是它结束的地方。

他们根本不继承。 当你写:

ChildClass.lookupClass()

编译器只是弄明白了: 好吧,你显然指的是ParentClass中的lookupClass()方法,所以就是我要编译的内容。 您可以通过运行javap -c -p MyExample亲眼看到这一点。 同样的原则甚至适用于非静态方法。

对于实例方法,运行时取消了这个操作:每当你在任何 object 上调用方法时,运行时系统将始终执行动态调度; 你不能选择退出。 你可以写:

AbstractList<String> list = new ArrayList<String>();
list.sort(someComparator);

并且您可以使用javap来验证这将最终写入调用方法 AbstractList::sort 的 class 文件。 但是,在运行时,JVM 将始终检查实际指向的list - 它是 ArrayList 的实例,而不是 AbstractList(很明显:AbstractList 是抽象的;object 不能直接实例化为“new AbstractList”)。 如果 ArrayList 有自己的排序方法,那么将调用它。

所有这一切的关键是:Static 方法不继承,因此,这个动态调度系统对它们不可用,因此,你想要的东西不能以那种方式完成。

那么该怎么办?

感觉就像您正在做的是尝试将层次结构与适用于 class 本身的属性相关联。 换句话说,您希望“ParentClass 的lookupClass方法和 ChildClass 的lookupClass方法的概念之间存在层次关系 - lookupClass 不是你问 ChildClass 或 ParentClass 的实例的东西 - 你在这些类型的概念中问它他们自己。

如果你想一想,构造函数也是一样的。 您不会向 ArrayList 的实例“询问”新的 arraylist。您询问 ArrayList,这个概念。 两者都'不真正做' inheritance 并且不能抽象为类型层次结构。

这就是工厂类的用武之地

工厂类作为一个概念只是“分层”静态,通过从中删除static :为您的 class 层次结构创建兄弟类型(例如ParentClassFactory ):

abstract class ParentClassFactory {
  abstract ParentClass create();
  abstract void printClass();
}

然后,在编写ChildClass的同时,您还编写了ChildClassFactory 通常工厂只有一个实例——您可能希望为此使用 singleton 模式。 现在你可以做得很好了:

class ChildClassFactory extends ParentClassFactory {
  private static final ChildClassFactory INSTANCE = new ChildClassFactory();
  public static ChildClassFactory instance() { return INSTANCE; }
  public ParentClass create() { return new ChildClass(); }
  public void printClass() { System.out.println(ChildClass.class); }
}

// elsewhere:

// actually gets the ChildClassFactory singleton:
ParentClassFactory factory = ....;
factory.printClass(); // will print ChildClass!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM