从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()我想打印类的名称(例如 do System.out.println(ParentClass.class))。当然后扩展ParentClass(例如像 in ChildClass)和调用ChildClass.printClass()时,我希望它打印扩展类的名称(像 do System.out.println(ChildClass.class))。这有可能吗?

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

rzwitserloot

最好将静态方法视为完全存在于类本身之外。它们出现在类中的原因是因为 java(语言)本身的设计:类型不仅仅是具有层次结构的类型,它们也是 java 命名空间系统的主要载体。

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

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

ChildClass.lookupClass()

编译器只是弄清楚:对,好吧,您显然指的是lookupClass()方法,ParentClass所以就是我要编译的。您可以通过运行亲自看到这一点javap -c -p MyExample同样的原则也适用于非静态方法。

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

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

并且您可以使用它javap来验证这将最终写入调用方法 AbstractList::sort 的类文件中。但是,在运行时,JVM 将始终检查list实际指向的内容——它是 ArrayList 的一个实例,而不是 AbstractList(这很明显:AbstractList 是抽象的;任何对象都不能直接实例化为`new AbstractList)。如果 ArrayList 对 sort 方法有自己的看法,那么它将被调用。

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

那么该怎么办?

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

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

这就是工厂类的用武之地

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

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

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

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!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章