<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test(); // Outputs "B"
?>
我希望在Java中得到一个等价物......所以像
class A {
public static void who(){
System.out.println("A");
};
public static void test(){
who(); //<<< How to implement a static:: thing here???
}
}
class B extends A {
public static void who(){
System.out.println("B");
};
public static void main(String[] args){
B.test(); // Outputs "A" but I want "B"
}
}
我希望who()
内的A::test
调用通过调用B::who
来解析,就像在PHP 5.3中一样。
这不适用于任何实际设计。我只是好奇。
答案 0 :(得分:2)
Java中不可能。 (至少不是没有丑陋的反思黑客。)
我鼓励您重新考虑您的设计并依赖适当的物品。
相关问题:
编辑: B.test()
将(或至少可以根据规范)编译成对A.test()
的调用,因此无法发现如何在A.test()
内进行通话。换句话说,没有办法让A.test
的行为取决于它是通过A.test()
还是B.test()
调用的。
既然你好奇了,这里是AFAIK最接近的“解决方案”。
test
重载test(Class<?> c)
,该参数将定义预期who
方法的类作为参数。test()
中B
。A.test
的实施。在代码中:
class A {
public static void who() {
System.out.println("A");
}
public static void test() {
test(A.class);
}
public static void test(Class<?> c) {
//who(); //<<< How to implement a static:: thing here???
try {
c.getMethod("who").invoke(null); // Call static who on given class.
} catch (Exception e) {
}
}
}
public class B extends A {
public static void who(){
System.out.println("B");
}
public static void test() {
test(B.class);
}
public static void main(String[] args){
A.test(); // Outputs "A"
B.test(); // Outputs "B"
}
}
答案 1 :(得分:2)
似乎编译器在字节码中生成对B.test
的调用,即使B
未声明名为test
的方法。
Bytecode of main method:
invokestatic #5 = Method B.test(()V)
return
给定类和方法("B"
和"who"
)的名称,您可以轻松地使用反射来调用方法。所以问题就变成了
您可以通过在
B
内组合调用堆栈和字节码来提取A.test
吗?
您需要使用存储在堆栈中的返回地址来定位字节码中对B.test
的调用并提取声明的调用。有很多字节码操作库,但我不知道它们中是否有任何一个允许你将它绑定到JVM中的执行堆栈。
答案 2 :(得分:1)
您不能在java中覆盖静态方法。
http://geekexplains.blogspot.co.uk/2008/06/can-you-override-static-methods-in-java.html
答案 3 :(得分:1)
这是Java的一个例子。它使用Java 8默认方法和getClass()
。我打赌它也适用于课程:
interface A {
default String name() {
return getClass().getName();
}
}
class B implements A {}
public class LateBinding {
public static void main(String[] args) {
// Create an anonymous class in `LateBinding` (called `$1`)
System.out.println(new A(){}.name());
// Instantiate a new `B`
B b = new B();
System.out.println(b.name());
}
}
结果:
$ javac LateBinding.java && java LateBinding
LateBinding$1
B
正如您所看到的,该方法在两种情况下都知道它在哪里运行,尽管它在A
中已定义。这个例子并不是静态的,因为你不能静态调用getClass()
,但PHP中的LSB并不仅限于静态上下文。
答案 4 :(得分:0)
使用静态方法声明没有优雅的方法(只有Delphi从我所知道的支持覆盖静态方法)。但是,如果你不需要静态,你可以这样写:
class A {
public void who(){
System.out.println("A");
};
public void test(){
who(); //<<< How to implement a static:: thing here???
}
}
class B extends A {
@Override
public void who(){
System.out.println("B");
};
public void main(String[] args){
A instance = new A();
instance.test(); // prints 'A'
instance = new B();
instance.test(); // prints 'B'
}
}
澄清后编辑: 非常hacky这样做的方式:Thread.currentThread().getStackTrace()然后从最顶层的记录获取此方法所属的方法和类。有了C类 - 你可以写c.getMethod(“who”)。invoke(null);调用对应的who()方法。