Class和Class <! - ? - >之间有什么真正的区别(如果有的话)?

时间:2013-10-13 10:06:07

标签: java generics

我很好奇原始Class类型和通用Class<?>类型的使用之间是否有任何真正的区别?我主动使用Java SE 6和SE 7。 至少Oracle泛型教程没有回答这个问题,我最初试图谷歌周围没有带来任何合适的结果。

提前谢谢。

2 个答案:

答案 0 :(得分:6)

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

来自Java doc:

无界通配符

  

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.

答案 1 :(得分:1)

无界通配符&lt;?&gt;似乎意味着“任何东西”,因此使用无界通配符似乎等同于使用原始类型。实际上,编译器似乎首先同意这一评估:

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);
    }
}

在很多情况下,例如您在此处看到的情况,编译器可能会关注您是使用原始类型还是&lt;?&gt;。在那些情况下,&lt;?&gt;可以被认为是一种装饰;然而它有价值,因为它实际上说,“我在编写这个代码时考虑到了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&lt;?,?&gt; 中所示,编译器似乎无法将其与原始地图。此外,第一个示例显示编译器处理 List&lt;?&gt; List&lt;?以不同方式扩展Object&gt;

欲了解更多信息,欢迎阅读Bruce Eckel的书:Thinking in Java