3 回答

TA貢獻1871條經驗 獲得超8個贊
如果使用的是JDK7,則可以使用MethodHandle來實現:
public class Test extends Base {
public static void main(String[] args) throws Throwable {
MethodHandle h1 = MethodHandles.lookup().findSpecial(Base.class, "toString",
MethodType.methodType(String.class),
Test.class);
MethodHandle h2 = MethodHandles.lookup().findSpecial(Object.class, "toString",
MethodType.methodType(String.class),
Test.class);
System.out.println(h1.invoke(new Test())); // outputs Base
System.out.println(h2.invoke(new Test())); // outputs Base
}
@Override
public String toString() {
return "Test";
}
}
class Base {
@Override
public String toString() {
return "Base";
}
}

TA貢獻1963條經驗 獲得超6個贊
這是不可能的。即使使用反射,Java中的方法分派始終考慮對象的運行時類型。請參見javadoc中的Method.invoke ; 特別是本節:
如果基礎方法是實例方法,則使用《 Java語言規范》第二版15.12.4.4節中所述的動態方法查找來調用該方法。特別是,將發生基于目標對象的運行時類型的覆蓋。

TA貢獻1842條經驗 獲得超13個贊
在@ java4script的答案的基礎上,我注意到,IllegalAccessException如果您嘗試從子類外部(即通常從那里super.toString()開始調用)執行此技巧,則會得到一個提示。該in方法僅在某些情況下(例如,當您從Base和一起從同一包中調用時)才繞過此方法Sub。對于一般情況,我發現的唯一解決方法是極端的(顯然是不可移植的)hack:
package p;
public class Base {
@Override public String toString() {
return "Base";
}
}
package p;
public class Sub extends Base {
@Override public String toString() {
return "Sub";
}
}
import p.Base;
import p.Sub;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
public class Demo {
public static void main(String[] args) throws Throwable {
System.out.println(new Sub());
Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
IMPL_LOOKUP.setAccessible(true);
MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null);
MethodHandle h1 = lkp.findSpecial(Base.class, "toString", MethodType.methodType(String.class), Sub.class);
System.out.println(h1.invoke(new Sub()));
}
}
印刷
Sub
Base
添加回答
舉報