gpt4 book ai didi

java - 代理困惑的优雅解决方案

转载 作者:行者123 更新时间:2023-11-29 04:50:22 25 4
gpt4 key购买 nike

在 Java 8 中,我想编写一个类,在给定一个或多个监听器的情况下,该类将返回一个代理列表(通过传入其类使用我选择的列表的实现),每当添加或删除某些内容时触发监听器.代码(请耐心等待)如下:

public final class EventedList {
private EventedList() {
}

protected static class ListInvocationHandler<T> implements InvocationHandler {
private List<T> theList;
private ListChangeHandler<T>[] listeners;

public ListInvocationHandler(Class<? extends List<T>> listClass, ListChangeHandler<T>[] listeners) throws InstantiationException, IllegalAccessException {
this.listeners = listeners;
theList = listClass.newInstance();
}

public Object invoke(Object self, Method method, Object[] args)
throws Throwable {
Object ret = method.invoke(theList, args);
switch(method.getName()) {
case "add":
trigger((T)args[0], true);
break;
case "remove":
if(args[0] instanceof Integer) {
trigger((T)ret, false);
} else {
trigger((T)args[0], false);
}
break;
}
return ret;
}

public void trigger(T obj, boolean added) {
Arrays.stream(listeners).forEachOrdered(l -> l.onChange(obj, added));
}
}

public static <T, U extends List<T>> List<T> newList(Class<U> listClass, ListChangeHandler<T> ... listeners) throws IllegalArgumentException, InstantiationException, IllegalAccessException {
@SuppressWarnings("unchecked")
List<T> obj = (List<T>)Proxy.newProxyInstance(listClass.getClassLoader(), new Class<?>[]{List.class}, new ListInvocationHandler<T>(listClass, listeners));
return obj;
}

public static <T, U extends List<T>> List<T> newListSafe(Class<U> listClass, ListChangeHandler<T> ... listeners) {
List<T> obj = null;
try {
obj = newList(listClass, listeners);
} catch (IllegalArgumentException | InstantiationException
| IllegalAccessException e) {
}
return obj;
}
}

它有效,但肯定不是没有问题。

  1. 我最初只有一种类型 T,但我在使用 Class<? extends List<T>> 时遇到错误所以我用U来代表? extends List<T>反而。
  2. ListInvocationHandler 的调用方法中,我不得不强行投 ObjectT .我认为这是不可避免的,但我欢迎任何替代方案。
  3. newProxyInstance正在返回 Object我必须转换为 List .此外,我认为这是不可避免的,但我欢迎任何替代方案。
  4. 我收到关于监听器参数的“潜在堆污染通过可变参数监听器”的警告,大概是因为它们是可变参数参数,但是我没有看到这样做的明显风险。

我使用的主要是以下内容:

public static void main(String[] args) {
List<String> list = EventedList.newListSafe(ArrayList.class, new ListChangeHandler<String>() {

@Override
public void onChange(String value, boolean added) {
System.out.println(value + ", " + (added ? "added" : "removed"));
}

});

list.add("Badger"); // Badger, added
list.add("Badger"); // Badger, added
list.add("Badger"); // Badger, added
list.add("Badger"); // Badger, added
list.remove("Badger"); // Badger, removed
list.add("Mushroom"); // Mushroom, added
list.remove("Mushroom"); // Mushroom, removed

// [Badger, Badger, Badger]
System.out.println(Arrays.toString(list.toArray()));
}
  1. 调用该方法的 main 本身有一个很好的类型安全警告,即使参数应该是隐式的。
  2. 如果可能的话,我希望能够按如下方式调用它(尽管我收到了这样的错误):

    List<String> list = EventedList.newListSafe(ArrayList.class, (value, added) -> {
    System.out.println(value + ", " + (added ? "added" : "removed"));
    });

我为文字墙道歉。我感谢任何意见。

最佳答案

您可以改用装饰器并可能摆脱(几乎)所有这些警告:

class EventedList<E> implements List<E> {
private List<E> delegate;
private List<ListChangeHandler<E>> listeners;

//using varargs here would still cause the heap pollution warning
public EventedList( List<E> d, ListChangeHandler<E>... l ) {
//set and initialize
}

public boolean add(E e) {
delegate.add(e);
trigger(e);
}

... //other methods

private void trigger(E e) {
//trigger listeners
}

那么就这样调用吧

List<String> list = new EventedList<String>(new ArrayList<String>(), 
new ListChangeHandler<String>() { ... } );

...或创建一个工厂方法。

关于java - 代理困惑的优雅解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35655582/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com