从 Java 中父 class 的静态方法获取子 class
getting child class from static method of parent class in Java
假设我有这些 classes:
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()
从静态方法内部获取 class 的方法,但是当在 ParentClass.printClass
内部使用它并扩展 ParentClass,然后在扩展 Class 上调用 printClass
,我总是得到 ParentClass
的 class。
引用 :
Static methods are not inherited. The fact that you can call ChildClass.printClass() is just syntactic sugar. It actually always calls ParentClass.printClass(). So you can't do something like that with a static method, only an inheritable non-static one.
静态方法最好被认为完全存在于 class 本身之外。它们确实出现在 classes 中的原因是 java(语言)本身的设计:类型不仅仅是具有层次结构的类型,它们还充当 java的命名空间系统。
类型存在于包中,包是类型的顶级命名空间概念。那么如何引用方法呢?只有一种方法:通过类型系统。因此,静态方法必须放在类型中。但这就是它结束的地方。
他们根本不继承。当你写:
ChildClass.lookupClass()
编译器刚刚弄明白: 对,好吧,你显然指的是 ParentClass
中的 lookupClass()
方法,所以 那 就是我要编译的.您可以通过 运行 javap -c -p MyExample
亲眼看到这一点。同样的原则也适用于non-static方法,甚至.
对于 instance 方法,runtime 取消了这个操作:每当你在任何对象上调用方法时,运行时系统将始终执行动态调度;你不能选择退出。你可以写:
AbstractList<String> list = new ArrayList<String>();
list.sort(someComparator);
并且您可以使用 javap
来验证这将最终写入调用方法 AbstractList::sort 的 class 文件。但是,在运行时,JVM 将始终检查 list
实际指向的是什么——它是 ArrayList 的一个实例,而不是 AbstractList(很明显:AbstractList 是抽象的;没有对象可以直接实例化为 `new AbstractList)。如果 ArrayList 有自己的排序方法,那么 that 将被调用。
所有这些的关键要点是:静态方法不继承,因此,这个动态调度系统对它们不可用,因此,你想要的东西不能以那种方式完成。
那怎么办?
感觉就像您正在尝试将层次结构与适用于 class 本身的属性相关联。换句话说,您希望“ParentClass 的 lookupClass
方法和 ChildClass 的 lookupClass
方法的概念之间存在层次关系 - lookupClass 不是你问 ChildClass 或 ParentClass 的实例的东西 - 你问它基于这些类型本身的概念。
如果你仔细想想,构造函数也是一样的。您没有 'ask' 新数组列表的 ArrayList 实例。你问ArrayList,这个概念。既'do not really do'继承又不能抽象成类型层次
这就是工厂 classes 进来的地方。
工厂 classes 作为一个概念只是 'hierarchicalizing' 静态,通过从中删除 static
:为您的 class 层次结构创建兄弟类型(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!
假设我有这些 classes:
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()
从静态方法内部获取 class 的方法,但是当在 ParentClass.printClass
内部使用它并扩展 ParentClass,然后在扩展 Class 上调用 printClass
,我总是得到 ParentClass
的 class。
引用
Static methods are not inherited. The fact that you can call ChildClass.printClass() is just syntactic sugar. It actually always calls ParentClass.printClass(). So you can't do something like that with a static method, only an inheritable non-static one.
静态方法最好被认为完全存在于 class 本身之外。它们确实出现在 classes 中的原因是 java(语言)本身的设计:类型不仅仅是具有层次结构的类型,它们还充当 java的命名空间系统。
类型存在于包中,包是类型的顶级命名空间概念。那么如何引用方法呢?只有一种方法:通过类型系统。因此,静态方法必须放在类型中。但这就是它结束的地方。
他们根本不继承。当你写:
ChildClass.lookupClass()
编译器刚刚弄明白: 对,好吧,你显然指的是 ParentClass
中的 lookupClass()
方法,所以 那 就是我要编译的.您可以通过 运行 javap -c -p MyExample
亲眼看到这一点。同样的原则也适用于non-static方法,甚至.
对于 instance 方法,runtime 取消了这个操作:每当你在任何对象上调用方法时,运行时系统将始终执行动态调度;你不能选择退出。你可以写:
AbstractList<String> list = new ArrayList<String>();
list.sort(someComparator);
并且您可以使用 javap
来验证这将最终写入调用方法 AbstractList::sort 的 class 文件。但是,在运行时,JVM 将始终检查 list
实际指向的是什么——它是 ArrayList 的一个实例,而不是 AbstractList(很明显:AbstractList 是抽象的;没有对象可以直接实例化为 `new AbstractList)。如果 ArrayList 有自己的排序方法,那么 that 将被调用。
所有这些的关键要点是:静态方法不继承,因此,这个动态调度系统对它们不可用,因此,你想要的东西不能以那种方式完成。
那怎么办?
感觉就像您正在尝试将层次结构与适用于 class 本身的属性相关联。换句话说,您希望“ParentClass 的 lookupClass
方法和 ChildClass 的 lookupClass
方法的概念之间存在层次关系 - lookupClass 不是你问 ChildClass 或 ParentClass 的实例的东西 - 你问它基于这些类型本身的概念。
如果你仔细想想,构造函数也是一样的。您没有 'ask' 新数组列表的 ArrayList 实例。你问ArrayList,这个概念。既'do not really do'继承又不能抽象成类型层次
这就是工厂 classes 进来的地方。
工厂 classes 作为一个概念只是 'hierarchicalizing' 静态,通过从中删除 static
:为您的 class 层次结构创建兄弟类型(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!