因此,假设我有一个名为Users的类,该类具有一个名为name的私有变量和一个只返回name变量的公共getter方法,那么我该如何做,以便该getter为所有的实例返回name +“ test”而不是访问用户类?
答案 0 :(得分:4)
在Java中有几种方法可以做到这一点……
首先,您可以扩展Users类并重写getter方法,如下所示:
public class TestUser extends User {
@Override
public String getName() { return super.getName() + "test"; }
}
然后,您可以通过User类引用TestUser实例,并调用getName方法以使用新行为:
User tu = new TestUser("username");
tu.getName(); // should return "usernametest"
现在...如果由于某种原因无法扩展您的班级并且无法接触现有的User类,那么另一种方法是使用proxy via reflection:
例如,如果您的User类实现了一个称为IUser(或其他任何东西)的接口,该接口声明了String getName()
方法>
public interface IUser {
String getName();
}
然后使用动态代理可以创建一个实现InvocationHandler的IUser代理,该代理将拦截getName方法并更改其返回值。
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DebugProxy(obj));
}
private DebugProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result;
try {
result = m.invoke(obj, args);
if ("getName".equals(m.getName())) {
return result + "test";
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
然后您可以申请:
public class MainApp {
public static void main(String[] args) {
IUser userProxy = (IUser) DebugProxy.newInstance(new User("foo"));
System.out.println(userProxy.getName());
}
}
System.out.println将打印“最底”
这是一个丑陋的解决方案,仅在您的User类实现公开getName方法的接口时才有效。唯一的好处是您不需要继承也不需要更改User类代码:
我会说继承是必经之路。
希望这会有所帮助,并欢迎堆栈溢出!