Java 如何在使用时避免泛型警告;“原始类型”;是否为静态字段/返回类型?

Java 如何在使用时避免泛型警告;“原始类型”;是否为静态字段/返回类型?,java,generics,unchecked,raw-types,Java,Generics,Unchecked,Raw Types,这基本上是从昨天开始的后续行动。我试图实现“最通用的方式”(我能想到的),以构建“真正的”不可修改的集合。下面的代码工作正常;但它需要抑制警告(“rawtypes”和“unchecked”) 我尝试了各种方法来避免这些警告;但根本找不到替代方案。所以,我的问题是:有没有一种干净的方法来避免我压制的警告 (我看到了另一个;但我不能100%确定它是否真的适用于我的代码;因为我不确定我是否可以在不使用原始类型的情况下写下“Generator”接口) 专用接口生成器{ T生成性(); } @抑制警告(“

这基本上是从昨天开始的后续行动。我试图实现“最通用的方式”(我能想到的),以构建“真正的”不可修改的集合。下面的代码工作正常;但它需要抑制警告(“rawtypes”和“unchecked”)

我尝试了各种方法来避免这些警告;但根本找不到替代方案。所以,我的问题是:有没有一种干净的方法来避免我压制的警告

(我看到了另一个;但我不能100%确定它是否真的适用于我的代码;因为我不确定我是否可以在不使用原始类型的情况下写下“Generator”接口)

专用接口生成器{
T生成性();
}
@抑制警告(“原始类型”)
专用最终静态生成器ListGenerator=新生成器(){
@凌驾
公共列表generateNewInstance(){
返回新的ArrayList();
}
};
公共静态列表不可修改ListBasedOnCloneof(列表元素){
@抑制警告(“未选中”)
List newInstance=makeNewInstanceOf(elements.getClass(),ListGenerator);
newInstance.addAll(元素);
返回集合。不可修改列表(newInstance);
}
私有静态T makeNewInstanceOf(类incomingClass、生成器fallbackGenerator){
试一试{
返回(T)incomingClass.newInstance();
}catch(IllegalAccessException |实例化exception e){
返回fallbackGenerator.generateNewInstance();
}
}

不可能总是避免@SuppressWarnings注释。我试图将其范围限制为局部变量

我想到了这个:

private interface Generator<T> {

    T generateNewInstance();
}

private static class ListGenerator<T> implements Generator<List<T>> {
    @Override
    public List<T> generateNewInstance() {
        return new ArrayList<>();
    }
};

public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
    @SuppressWarnings("unchecked")
    Class<List<T>> clazz = (Class<List<T>>)elements.getClass();
    List<T> newInstance = makeNewInstanceOf(clazz , new ListGenerator<T>());
    newInstance.addAll(elements);
    return Collections.unmodifiableList(newInstance);
}

private static <T> T makeNewInstanceOf(Class<T> incomingClass, Generator<T> fallbackGenerator) {
    try {
        return (T) incomingClass.newInstance();
    } catch (IllegalAccessException | InstantiationException e) {
        return fallbackGenerator.generateNewInstance();
    }
}
专用接口生成器{
T生成性();
}
私有静态类ListGenerator实现了{
@凌驾
公共列表generateNewInstance(){
返回新的ArrayList();
}
};
公共静态列表不可修改ListBasedOnCloneof(列表元素){
@抑制警告(“未选中”)
Class clazz=(Class)elements.getClass();
List newInstance=makeNewInstanceOf(clazz,newlistgenerator());
newInstance.addAll(元素);
返回集合。不可修改列表(newInstance);
}
私有静态T makeNewInstanceOf(类incomingClass、生成器fallbackGenerator){
试一试{
返回(T)incomingClass.newInstance();
}catch(IllegalAccessException |实例化exception e){
返回fallbackGenerator.generateNewInstance();
}
}

不可能总是避免@SuppressWarnings注释。我试图将其范围限制为局部变量

我想到了这个:

private interface Generator<T> {

    T generateNewInstance();
}

private static class ListGenerator<T> implements Generator<List<T>> {
    @Override
    public List<T> generateNewInstance() {
        return new ArrayList<>();
    }
};

public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
    @SuppressWarnings("unchecked")
    Class<List<T>> clazz = (Class<List<T>>)elements.getClass();
    List<T> newInstance = makeNewInstanceOf(clazz , new ListGenerator<T>());
    newInstance.addAll(elements);
    return Collections.unmodifiableList(newInstance);
}

private static <T> T makeNewInstanceOf(Class<T> incomingClass, Generator<T> fallbackGenerator) {
    try {
        return (T) incomingClass.newInstance();
    } catch (IllegalAccessException | InstantiationException e) {
        return fallbackGenerator.generateNewInstance();
    }
}
专用接口生成器{
T生成性();
}
私有静态类ListGenerator实现了{
@凌驾
公共列表generateNewInstance(){
返回新的ArrayList();
}
};
公共静态列表不可修改ListBasedOnCloneof(列表元素){
@抑制警告(“未选中”)
Class clazz=(Class)elements.getClass();
List newInstance=makeNewInstanceOf(clazz,newlistgenerator());
newInstance.addAll(元素);
返回集合。不可修改列表(newInstance);
}
私有静态T makeNewInstanceOf(类incomingClass、生成器fallbackGenerator){
试一试{
返回(T)incomingClass.newInstance();
}catch(IllegalAccessException |实例化exception e){
返回fallbackGenerator.generateNewInstance();
}
}

如果将
列表
复制到一个新的
数组列表
,并将该引用内联传递到
集合。不可修改列表
,则除了不可修改的装饰器之外,没有其他任何东西可以访问该副本来修改它:

    List<String> original = new ArrayList<>(Arrays.asList("Hello", "World"));

    // This simply decorates original, so updates to original are
    // reflected in this list.
    List<String> unmodifiableDecorator = Collections.unmodifiableList(original);

    // The reference to the new ArrayList is scoped to the call to
    // Collections.unmodifiableList, so nothing else can have a
    // reference to it.
    List<String> unmodifiableCopy =
        Collections.unmodifiableList(new ArrayList<>(original));

    System.out.println("Before clear:");
    System.out.println(original);
    System.out.println(unmodifiableDecorator);
    System.out.println(unmodifiableCopy);

    original.clear();

    System.out.println("After clear:");
    System.out.println(original);
    System.out.println(unmodifiableDecorator);
    System.out.println(unmodifiableCopy);
因此,
unmodifiableCopy
不会被修改,也不能被修改,除非您能够以某种方式说服
unmodifiableList
将代理引用提供给您

由于无法修改它,因此不需要将副本设置为与输入列表相同的具体列表类型。只需将其设置为
ArrayList
,因为它具有几乎可以通过
列表实现的最佳读取性能

因此,在没有警告或额外类的情况下,您的方法可以是:

public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
  return Collections.unmodifiableList(new ArrayList<>(elements));
}
公共静态列表不可修改ListBasedOnCloneof(列表元素){
返回集合。不可修改列表(新的ArrayList(元素));
}

如果将
列表
复制到一个新的
数组列表
,并将该引用内联传递到
集合。不可修改列表
,则除了不可修改的装饰器之外,没有其他任何东西可以访问该副本来修改它:

    List<String> original = new ArrayList<>(Arrays.asList("Hello", "World"));

    // This simply decorates original, so updates to original are
    // reflected in this list.
    List<String> unmodifiableDecorator = Collections.unmodifiableList(original);

    // The reference to the new ArrayList is scoped to the call to
    // Collections.unmodifiableList, so nothing else can have a
    // reference to it.
    List<String> unmodifiableCopy =
        Collections.unmodifiableList(new ArrayList<>(original));

    System.out.println("Before clear:");
    System.out.println(original);
    System.out.println(unmodifiableDecorator);
    System.out.println(unmodifiableCopy);

    original.clear();

    System.out.println("After clear:");
    System.out.println(original);
    System.out.println(unmodifiableDecorator);
    System.out.println(unmodifiableCopy);
因此,
unmodifiableCopy
不会被修改,也不能被修改,除非您能够以某种方式说服
unmodifiableList
将代理引用提供给您

由于无法修改它,因此不需要将副本设置为与输入列表相同的具体列表类型。只需将其设置为
ArrayList
,因为它具有几乎可以通过
列表实现的最佳读取性能

因此,在没有警告或额外类的情况下,您的方法可以是:

public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
  return Collections.unmodifiableList(new ArrayList<>(elements));
}
公共静态列表不可修改ListBasedOnCloneof(列表元素){
返回集合。不可修改列表(新的ArrayList(元素));
}

我明白了。保存其中一个警告;以单个“new”语句的微妙代价(这可能是过早的优化;但我特意提出了一个解决方案,试图在没有引发异常的“良好”情况下最小化发生的“活动”。
incomingClass.newInstance()
可以绕过编译器对已检查异常的支持。如果调用
incomingClass.getConstructor().newInstance()
它将迫使您捕获
InvocationTargetException
,它将包装构造函数中抛出的异常,允许您处理它们或使用您认为合适的
fallbackGenerator
。我明白了。保存其中一个警告;以罪恶的微妙代价