2

我很好奇原始Class类型和通用类型的使用之间有什么真正的区别Class<?>吗?我积极使用 Java SE 6 和 SE 7。至少 Oracle 泛型教程没有回答这个问题,我最初尝试谷歌搜索并没有带来任何合适的结果。

先感谢您。

4

2 回答 2

6

类实际上不是原始类型,它被称为unknown typeunbounded wildcard

来自 Java 文档:

无界通配符

The unbounded wildcard type is specified using the wildcard character (?), for example, List<?>. This is called a list of unknown type. There are two scenarios where an unbounded wildcard is a useful approach:

If you are writing a method that can be implemented using functionality provided in the Object class. When the code is using methods in the generic class that don't depend on the type parameter. For example, List.size or List.clear. In fact, Class<?> is so often used because most of the methods in Class<T> do not depend on T.

于 2013-10-13T10:11:11.100 回答
1

无界通配符 <?> 似乎意味着“任何东西”,因此使用无界通配符似乎等同于使用原始类型。事实上,编译器起初似乎同意这个评估:

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

public class UnboundedWildcards1 {
    static List list1;
    static List<?> list2;
    static List<? extends Object> list3;

    static void assign1(List list) {
        list1 = list;
        list2 = list;
        // list3 = list; // Warning: unchecked conversion
        // Found: List, Required: List<? extends Object>
    }

    static void assign2(List<?> list) {
        list1 = list;
        list2 = list;
        list3 = list;
    }

    static void assign3(List<? extends Object> list) {
        list1 = list;
        list2 = list;
        list3 = list;
    }

    public static void main(String[] args) {
        assign1(new ArrayList());
        assign2(new ArrayList());
        // assign3(new ArrayList()); // Warning:
        // Unchecked conversion. Found: ArrayList
        // Required: List<? extends Object>
        assign1(new ArrayList<String>());
        assign2(new ArrayList<String>());
        assign3(new ArrayList<String>());
        // Both forms are acceptable as List<?>:
        List<?> wildList = new ArrayList();
        wildList = new ArrayList<String>();
        assign1(wildList);
        assign2(wildList);
        assign3(wildList);
    }
}

在很多情况下,就像您在此处看到的那样,无论您使用原始类型还是 <?>,编译器都不太在意。在这些情况下,<?> 可以被认为是一种装饰。但它很有价值,因为实际上它说:“我在编写这段代码时考虑到了 Java 泛型,我在这里并不是说我使用的是原始类型,但在这种情况下泛型参数可以容纳随便哪种。”

第二个示例显示了未绑定通配符的重要用途。当您处理多个泛型参数时,有时重要的是允许一个参数为任何类型,同时为另一个参数建立特定类型:

import java.util.HashMap;
import java.util.Map;

public class UnboundedWildcards2 {
    static Map map1;
    static Map<?, ?> map2;
    static Map<String, ?> map3;

    static void assign1(Map map) {
        map1 = map;
    }

    static void assign2(Map<?, ?> map) {
        map2 = map;
    }

    static void assign3(Map<String, ?> map) {
        map3 = map;
    }

    public static void main(String[] args) {
        assign1(new HashMap());
        assign2(new HashMap());
        // assign3(new HashMap()); // Warning:
        // Unchecked conversion. Found: HashMap
        // Required: Map<String,?>
        assign1(new HashMap<String, Integer>());
        assign2(new HashMap<String, Integer>());
        assign3(new HashMap<String, Integer>());
    }
}

但是同样,当您拥有所有无界通配符时,如Map<?,?>所示,编译器似乎无法将其与原始Map区分开来。另外,第一个例子表明编译器处理List<?>List<? 以不同的方式扩展 Object>

如需更多信息,欢迎阅读 Bruce Eckel 的书:Thinking in Java

于 2013-10-13T10:42:59.010 回答