美文网首页
提示三十三

提示三十三

作者: 飞絮搅青冥 | 来源:发表于2022-07-19 07:57 被阅读0次

    提示三十三:考虑类型安全的异构容器

    泛型常用于集合,被充当被参数化了的容器,这样就限制了每个容器都只能有固定个数的参数。将键参数化,而不是容器,可以突破这种限制。书中举例说明如果安全的操作:

    public class Favorites {
        private Map<Class<?>, Object> favorites = new HashMap<>();
        public <T> void putFavorite(Class<T> type, T instance) {
            favorites.put(Objects.requireNonNull(type), instance);
        } 
        public <T> T getFavorite(Class<T> type) {
            return type.cast(favorites.get(type));
        }
    }
    

    但是恶意使用原始形式的类对象,从而很容易破坏 类型安全性。为了确保类型安全,可以在插入数据时进行动态转换。

    public <T> void putFavorite(Class<T> type, T instance) { 
      favorites.put(type, type.cast(instance));
    }
    

    cast我也经常使用,在stream中用.stream().filter(T.class::isInstance).map(T.class::cast)可以方便的进行对象的转化。

    第二个限制是不能用于不可具体化的类型。比如:

    Favorites favorites = new Favorites();
    favorites.putFavorite(List.class, Arrays.asList("123"));
    favorites.putFavorite(List.class, Arrays.asList(12));
    System.out.println(favorites.getFavorite(List.class));
    

    List<Integer> 和List<String> 共用一个Class对象,可能会导致后续处理出现无法预计的结果。

    最后书中还提到可以利用 asSubclass方法把类Class<?>的对象强制转换成 Class<? extends Annotation>。这个在自定义注解的时候可能有用,正好注解这一块知识我也没有掌握的很好,有空可以好好研究研究。

    static Annotation getAnnotation(AnnotatedElement element, String annotationTypeName) {
        Class<?> annotationType = null; // Unbounded type token
        try {
            annotationType = Class.forName(annotationTypeName);
        } catch (Exception ex) {
            throw new IllegalArgumentException(ex);
        } 
        return element.getAnnotation(annotationType.asSubclass(Annotation.class));
    }
    

    相关文章

      网友评论

          本文标题:提示三十三

          本文链接:https://www.haomeiwen.com/subject/lmrjirtx.html