我需要用Java覆盖最终类的构造函数。我知道这不是理想的,但不幸的是,这是必要的。是否有任何聪明的解决方法能够实现这一目标?具体来说,有一个方法是从最终类中的构造函数内部调用的,我需要使用不同的参数调用(现在使用最终类的包中定义的常量调用它)。
答案 0 :(得分:4)
它不是理想的,它是不可能的,因为它是最终的。您最好的选择是创建一个包装类:
class WrapperClass {
private FinalClass finalClass;
public WrapperClass() {
finalClass = new FinalClass();
}
public void doStuff() {
finalClass.doStuff(); // <- this would be the final method you want to override
// Do your own stuff
}
}
答案 1 :(得分:1)
规避最终方法没有好办法,但there is a good trick against (static or not) final fields 。如果改变你所谈论的那个常数是一个选项,那么你可以通过使用反射来做到这一点:
private static void setDefault(String newDefault) throws Exception {
Field staticField = SomeFinalClass.class.getDeclaredField("CONSTANT");
setValue(null, staticField, newDefault);
}
protected static void setValue(Object owner, Field field, Object value) throws Exception {
makeModifiable(field);
field.set(owner, value);
}
/**
* Force the field to be modifiable and accessible.
*/
protected static void makeModifiable(Field nameField) throws Exception {
nameField.setAccessible(true);
int modifiers = nameField.getModifiers();
Field modifierField = nameField.getClass().getDeclaredField("modifiers");
modifiers = modifiers & ~Modifier.FINAL;
modifierField.setAccessible(true);
modifierField.setInt(nameField, modifiers);
}
}
注意:显然,如果有可用的常规设计模式,应谨慎处理并避免这种技巧。
答案 2 :(得分:0)
如果要修改的类具有界面,则可以使用java.lang.reflect.Proxy
:
public class ProxyTest {
@Test
public void proxy() throws Throwable {
InvocationHandler handler = new MyInvocationHandler(new MyClass());
MyInterface f = (MyInterface) Proxy.newProxyInstance(MyClass.class.getClassLoader(),
new Class[] { MyInterface.class },
handler);
int result = f.test();
assertThat(result).isEqualTo(20);
}
}
class MyInvocationHandler implements InvocationHandler {
private MyInterface wrappedInstance;
public MyInvocationHandler(MyInterface object) {
this.wrappedInstance = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("test")){
return 20;
} else {
return method.invoke(this.wrappedInstance, args);
}
}
}