java - 从课堂外替换吸气剂
问题描述
所以,假设我有一个名为 Users 的类,它有一个名为 name 的私有变量和一个只返回 name 变量的公共 getter 方法,我怎样才能让 getter 为类的所有实例返回 name +“test”而不是可以访问用户类?
解决方案
好吧,在 Java 中有几种方法可以做到这一点……</p>
子类
首先,您可以扩展您的 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 类,那么另一种方法是通过反射使用代理:
例如,如果您的 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 将打印“footest”
这是一个丑陋的解决方案,仅当您的 User 类实现了一个公开 getName 方法的接口时才有效。唯一的好处是您不需要继承也不需要更改 User 类代码:
我会说继承是要走的路。
希望这有助于并欢迎堆栈溢出!
推荐阅读
- sql - 外推数据
- mysql - 在 MySQL 中,我的日期格式为 (mm-dd-yyyy),因此无法检索 2020 年的总销售额
- r - 使用 fviz_dend 和 1000 的大型数据集在 zero_range() 中出错
- branch - Branch.io - 自定义 Deepview 中的 iFrame 不起作用
- angular - 通过 Nginx 提供预压缩的 Angular dist 文件
- sql - SQL 查询以获取每年表现最佳的统计数据(例如 3 个指针)
- r - R group_by 和汇总功能不再起作用
- azure - 使用 Azure AD 对 VM 进行身份验证 - 适用于一个用户,而不适用于另一个用户
- algorithm - 在二分图的集合 U 中选择最小数量的顶点以覆盖集合 V 中的至少一定数量的顶点
- go - 切换多种类型的案例,如何设置案例以捕获来自某个导入的所有错误