【问题标题】:Java - is mixed type container (non-generic class) possible without unchecked cast?Java - 没有未经检查的转换是否可以混合类型容器(非泛型类)?
【发布时间】:2026-01-25 04:45:01
【问题描述】:

我正在尝试制作一个简单的存储类,它将存储不同的类实例。我设法做到的唯一几乎正确的方法是使用未经检查的类型转换。

HashSet<T> result = (HashSet<T>) storage.get(s);

可以在不进行未经检查的强制转换和不使类通用 (class Storage&lt;T&gt; { }) 的情况下完成吗?

import java.util.*;
import org.junit.*;

class Tests {
    @Test
    public static void main (String[] args) {
        Storage storage = new Storage();

        HashSet<Child1> child1Set = storage.get("child1");
        HashSet<Child1> duplicateChild1Set = storage.get("child1");

        Assert.assertNotNull(child1Set);
        Assert.assertSame(child1Set, duplicateChild1Set);

        HashSet<Child2> child2Set = storage.get("child2");

        Assert.assertNotNull(child2Set);
        Assert.assertNotSame(child1Set, child2Set);
    }
}

class Storage {

    public Map<String, HashSet<? extends Parent>> storage = new HashMap<>();

    public <T extends Parent> HashSet<T> get(String s) {
        HashSet<T> result = (HashSet<T>) storage.get(s);
        if (result == null) {
            result = new HashSet<>();
            storage.put(s, result);
        }
        return result;
    }
}

class Parent { }

class Child1 extends Parent { }

class Child2 extends Parent { }

【问题讨论】:

  • 未经检查的类型转换是安全的,您不必担心。你甚至可以压制是-@SuppressWarnings("unchecked")。不幸的是,这就是您创建异构类型安全容器的方式。

标签: java generics types casting unchecked


【解决方案1】:

您可以使用Class 对象作为键,而不是Strings。这是一个简短的例子。为简单起见,我没有包含 extends Parent - 你可以把它们放回去。

public final class Storage {

    private final Map<Class<?>, Set<?>> storage = new HashMap<>();

    public <T> Set<T> get(Class<T> s) {
        Set<T> result = (Set<T>) storage.get(s); // Unchecked cast
        if (result == null) {
            result = new HashSet<>();
            storage.put(s, result);
        }
        return result;
    }
}

不可能像这样在混合类型的容器中消除未经检查的强制转换。无法指定如果键的类型为Class&lt;T&gt;,则值的类型为Set&lt;T&gt;。但是,只要 Storage 类的用户不忽略任何类型安全警告,这就是完全类型安全的。

例如,要使用该课程,您可以使用storage.get(Double.class).add(4.2);

【讨论】:

  • 您说“无法消除未经检查的演员表”,这是回答问题的错误论据
  • @HeyStackExchange 您错过了问题的全部要点。整个想法是Storage 是一个混合类型的容器。 OP 甚至明确表示 without making the class generic (class Storage&lt;T&gt;
  • 不能投票给你,伙计。 “您上次对此答案投票是在 13 分钟前。除非编辑此答案,否则您的投票现在已锁定”