【问题标题】:Java why method overload from generic type cannot be determined at compile timeJava为什么无法在编译时确定泛型类型的方法重载
【发布时间】:2013-04-18 12:31:13
【问题描述】:

我想知道为什么下面的代码不能使用编译时泛型类型信息来正确查找最具体的方法重载,而是始终使用适用于所有潜在泛型参数的方法。有没有办法在编译时切换泛型参数类型以避免在运行时出现讨厌的反射?

import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

public class Temp {
    class A<T> {
        T x;
        A(T x) {
            this.x = x;
        }
        String bar = foo(x);

        private String foo(Integer i) {
            return "Int";
        }
        private String foo(String i) {
            return "String";
        }
        private <T> String foo(List<T> l) {
            return "List";
        }
        private <T> String foo(T v) {
            return "Value";
        }
    }

    @Test
    public void IntTest() {
        Assert.assertEquals(new A<Integer>(1).bar, "Int");
    }
    @Test
    public void StringTest() {
        Assert.assertEquals(new A<String>("A").bar, "String");
    }
    @Test
    public void ListTest() {
        Assert.assertEquals(new A<List<String>>(new ArrayList<String>()).bar, "List");
    }
    @Test
    public void LongTest() {
        Assert.assertEquals(new A<Long>(1L).bar, "Value");
    }
}

【问题讨论】:

标签: java generics overloading


【解决方案1】:

这是因为编译器必须为用于T 的每种类型生成不同的类A(因为A.bar 的初始化程序需要调用不同的方法)。决定只生成一个类。这与例如不同。 C++,其中编译器为所有使用的类型参数生成一个新类型。

换句话说,A&lt;String&gt; 类型的编译代码与A&lt;Integer&gt; 类型不同,但编译后只有A 类型。

【讨论】:

    【解决方案2】:

    这是因为泛型在编译时被删除。 有擦除的概念,它在编译时删除所有泛型代码,用类型转换替换它。所以java在运行时不会知道泛型方法。

    编辑:

    也请查看此链接:http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotOverload

    【讨论】:

    • 问题是为什么不能在编译时完成,所以同时删除的信息作为解释没有意义。这是因为 Java 泛型不是模板机制。在示例代码中只有一次对foo 的调用。未根据运行时类型选择覆盖已预先擦除。
    • 所以澄清一下,这是因为在选择方法重载决议之前,泛型在编译时被删除了?
    • @Woodz question I marked as a duplicate 的公认答案非常清楚地解释了这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多