java - 在Java中,为什么我只能使用泛型来限制集合参数?

标签 java generics methods

下面我有两个通用方法。两者都有两个参数化类型 T 和 V 扩展 T。第一个方法 foo 接受类型 T 和 V 的参数。奇怪的是,我可以调用 foo("hello", new Integer(10)) 并且它会编译并运行,即使 Integer显然不扩展 String.第二种方法 bar 采用 List< T > 和 List< V > 类型的参数。在这里,我无法调用 bar,向其传递字符串列表和整数列表。为什么后者限制类型,而前者不限制。

public class GenMeth {

    public static void main(String[] args) {

        List<String> s_list = new ArrayList<>();
        s_list.add("hello");

        List<Integer> i_list = new ArrayList<>();
        i_list.add(10);

        foo("hello", new Integer(10));  // will compile - why?

        bar(s_list, i_list);  // won't compile - understandable

    }

    public static <T,V extends T> void foo(T obj1, V obj2) {
            // do something
    }

    public static <T,V extends T> void bar(List<T> list1, List<V> list2) {
            // do something
    }
}

最佳答案

foo总是能够接受任何引用类型的两个参数,因为 TV可以选择为Object ,任何引用类型都是 Object 的子类型。所以foo不妨声明为 public static void foo(Object obj1, Object obj2) ;这没什么区别。从它的声明方式来看,没有什么 foo可以用它的任何一个参数来做,除了 Object 可以做的事情,由于类型变量没有界限,因此除了它们都是 Object 之外没有任何限制.

bar不同是因为类型变量位于类型参数中。泛型是不变的 -- List<String>不是 List<Object> 的子类型(反之亦然)即使 StringObject 的子类型。因此,第一个参数的类型为 List<T> ,它迫使T与传递的参数的类型参数完全匹配;即通过传递 List<String>作为第一个参数,它强制 T成为String ;不可能Object或者其他什么——它不会兼容。并且由于第二个参数的类型是 List<V>V延伸T ,这意味着第二个参数的类型参数必须是 StringString 的子类型。 (p.s. bar 也可以简单一点地声明为 public static <T> void bar(List<T> list1, List<? extends T> list2) )

关于java - 在Java中,为什么我只能使用泛型来限制集合参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47087814/

相关文章:

java - 为什么Java的类型推断这么弱?

java - 无法使用 oauth2 添加 spring security 的自定义配置

java - Android 在运行时无法从 JAR 中找到方法

c# - EF Core中抽象通用DbContext类的设计

c++ - 使用循环创建类对象

c# - 是否可以忽略 'out' 参数?

java - 异常: Requires 'start' < 'end'

c# - 为什么我不能将此接口(interface)转换为具体类?

android - 我用于 Retrofit 接口(interface)创建的通用函数出现编译器错误 : inferred type is Class<T>?,但需要 Class<T!>

php - codeigniter 检查每个 Controller 中的用户 session