我为什么要关心Java没有经过修饰的泛型呢?

2022-08-31 10:03:18

这是我最近在一次面试中提出的一个问题,作为候选人希望看到添加到Java语言中的东西。Java没有经过修饰的泛型,这通常被认为是一种痛苦,但是当被推动时,候选人实际上无法告诉我,如果他们在那里,他可以实现什么样的目标。

显然,由于原始类型在Java中是允许的(并且不安全的检查),因此可能会破坏泛型并最终得到(例如)实际包含s的泛型。如果类型信息得到重新定义,这显然是不可能的;但一定不止这些List<Integer>String

人们是否可以发布他们真正想做的事情的例子,是否有可用的重新定义的泛型?我的意思是,显然你可以在运行时获得a的类型 - 但是你会用它做什么呢?List

public <T> void foo(List<T> l) {
   if (l.getGenericType() == Integer.class) {
       //yeah baby! err, what now?

编辑:对此进行快速更新,因为答案似乎主要关注是否需要将a作为参数传递(例如)。我正在寻找更多的东西,就像这是不可能的。例如:ClassEnumSet.noneOf(TimeUnit.class)

List<?> l1 = api.gimmeAList();
List<?> l2 = api.gimmeAnotherList();

if (l1.getGenericType().isAssignableFrom(l2.getGenericType())) {
    l1.addAll(l2); //why on earth would I be doing this anyway?

答案 1

最常咬我的是无法利用跨多个泛型类型的多个调度。以下是不可能的,在许多情况下,这将是最佳解决方案:

public void my_method(List<String> input) { ... }
public void my_method(List<Integer> input) { ... }

答案 2

从我遇到这种“需求”的几次,它最终归结为这个结构:

public class Foo<T> {

    private T t;

    public Foo() {
        this.t = new T(); // Help?
    }

}

这在 C# 中确实有效,假设它具有默认构造函数。您甚至可以按 typeof(T) 获取运行时类型,并通过 Type.GetConstructor() 获取构造函数。T

常见的 Java 解决方案是传递 as 参数。Class<T>

public class Foo<T> {

    private T t;

    public Foo(Class<T> cls) throws Exception {
        this.t = cls.newInstance();
    }

}

(它不一定需要作为构造函数参数传递,因为方法参数也很好,上面只是一个例子,为了简洁起见,也省略了 try-catch

对于所有其他泛型类型构造,可以通过一点反射帮助轻松解析实际类型。下面的问答说明了用例和可能性:


推荐