java - 泛型友好的类型处理程序映射

标签 java java-8 generics

我正在尝试创建返回特定类型的处理程序的“注册表”

public class HandlerRegistry {
   Map<Class<?>, Handler<?>> handlers;

   <T> void setHandler(Class<T> type, Handler<? extends T> handler) {
      handlers.put(type, handler);
   }

   <T> T handle(Class<T> type, HandlerArgument arg) {
      Handler<? extends T> handler = getHandler(type);

      return handler.handle(arg);
   } 

   <T> Handler<? extends T> getHandler(Class<T> type) {
      // warning produced here "uses unchecked or unsafe operations."
      return (Handler<? extends T>)handlers.get(type);
   }
}

我知道这个特定的强制转换在运行时永远不会失败,但是除了使用 @SuppressWarnings("unchecked") 之外,有没有办法告诉编译器这确实是安全的?

我专门使用 Java 8,如果有更优雅的方式来做我想在 8 中做的事情的话。

最佳答案

通常,在这种情况下,未经检查的操作是不可避免的。您可以做的最好的事情是隔离未经检查的操作并通过安全测试来保护它。一个经过验证的解决方案是将实例包装在一个 holder 实例中,该实例封装了未经检查的操作并强制执行预检查:

class HandlerRegistry {
    private static class Holder<T> {
        private final Class<T>   type;
        private final Handler<? extends T> handler;
        Holder(Class<T> c, Handler<? extends T> h) {
            type=Objects.requireNonNull(c);
            handler=h;
        }
        <U> Holder<U> as(Class<U> expected) {
            if(type!=expected)
                throw new ClassCastException();
            @SuppressWarnings("unchecked") Holder<U> h=(Holder)this;
            return h;
        }
        public Handler<? extends T> getHandler() {
            return handler;
        }
    }
    Map<Class<?>, Holder<?>> handlers;

    <T> void setHandler(Class<T> type, Handler<? extends T> handler) {
        handlers.put(type, new Holder<>(type, handler));
    }
    <T> T handle(Class<T> type, HandlerArgument arg) {
        return getHandler(type).handle(arg);
    }
    <T> Handler<? extends T> getHandler(Class<T> type) {
        return handlers.get(type).as(type).getHandler();
    }
}

关于java - 泛型友好的类型处理程序映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29837124/

相关文章:

java - 将多个 onClickListener 和 OnClick 放在同一个 Activity 中

java - 如何使用 java Streams API 转换 for 循环迭代 n 次以实现具有多个动态变化的计数的列表

java - IntStream.empty() 方法的目的是什么?

c# - 无法将运算符 '<' 应用于类型 T 和 T 的操作数

java - 接口(interface)中方法级通用返回类型

c# - 将多态列表合并为一个列表并获取派生类型

java - 正则表达式、地理坐标系值(秒)问题、Java

java - Spring 请求范围的 bean - 所有字段为空/空

java - 如何用新加密的数据更新部分加密的数据?

jakarta-ee - 如何为 Java EE 容器中的并行流设置 SonarQube 警告?