美文网首页
Java 泛型使用限制

Java 泛型使用限制

作者: xiaofudeng | 来源:发表于2017-11-07 18:40 被阅读0次

参考

The Java™ Tutorials

限制

  • 无法和原始类型使用, 即类型参数不能是<int>这些.
  • 不能生成类型参数的实例, 即不能new T(), 因为编译之后参数T已经没有了.
public static <E> void append(List<E> list) {
    E elem = new E();  // compile-time error
    list.add(elem);
}

正确做法, 使用反射

public static <E> void append(List<E> list, Class<E> cls) throws Exception {
    E elem = cls.newInstance();   // OK
    list.add(elem);
}
  • 无法用类型参数T声明类的静态变量
public class MobileDevice<T> {
    private static T os;

    // ...
}

原因:

If static fields of type parameters were allowed, then the following code would be confused:

  • MobileDevice<Smartphone> phone = new MobileDevice<>();
  • MobileDevice<Pager> pager = new MobileDevice<>();
  • MobileDevice<TabletPC> pc = new MobileDevice<>();

Because the static field os is shared by phone, pager, and pc, what is the actual type of os? It cannot be Smartphone, Pager, and TabletPC at the same time. You cannot, therefore, create static fields of type parameters.

如果可以用T声明静态, 变量, 那么在上述情况中, 这个静态变量的类型到底是什么呢? 因为静态变量属于类, 所以静态变量不可能同时是上述的三个类型, 所以无法实现这点.

  • 无法instanceof 带类型参数的泛型类
    比如说不能 boolean b = list instanceof ArrayList<String>, 因为编译之后ArrayList<String>实际变成了ArrayList, 根本没有新的类产生. 同理也没有ArrayList<String>.class.
    但是可以这样list instanceof ArrayList<?>, 等同于list instanceof ArrayList
  • 类型转换的问题
    首先List<Number>List<Integer>不是协变的, 所以后者无法转变为前者, 编译器不会允许这个操作.
    但是这种操作确实允许的, 不过会给出警告:
List<String> stringList = new LinkedList<>();  // 这里只是用错误类型举个例子
ArrayList<String> stringArrayList = (ArrayList<String>) stringList;
  • 无法生成泛型数组
List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error

原因:

The following code illustrates what happens when different types are inserted into an array:
Object[] strings = new String[2];
strings[0] = "hi"; // OK
strings[1] = 100; // An ArrayStoreException is thrown.

上面代码展示了, 当数组中插入不同类型元素时候发生的事情. 运行到strings[1]=100的时候, 会有异常.
假设可以创建泛型数组, 那么会发生以下情况:

If you try the same thing with a generic list, there would be a problem:

Object[] stringLists = new List<String>[];  // compiler error, but pretend it's allowed
stringLists[0] = new ArrayList<String>();   // OK
stringLists[1] = new ArrayList<Integer>();  // An ArrayStoreException should be thrown,
                                            // but the runtime can't detect it.

If arrays of parameterized lists were allowed, the previous code would fail to throw the desired ArrayStoreException.

runtime不能detect这个应该是和泛型类型擦除有关.

  • 无法生成, 捕获, 或者抛出泛型类型的对象

A generic class cannot extend the Throwable class directly or indirectly. For example, the following classes will not compile:

// Extends Throwable indirectly
class MathException<T> extends Exception { /* ... */ }    // compile-time error

// Extends Throwable directly
class QueueFullException<T> extends Throwable { /* ... */ // compile-time error

A method cannot catch an instance of a type parameter:

public static <T extends Exception, J> void execute(List<J> jobs) {
    try {
        for (J job : jobs)
            // ...
    } catch (T e) {   // compile-time error
        // ...
    }
}

不过, 可以在throws语句中使用泛型类型参数

class Parser<T extends Exception> {
    public void parse(File file) throws T {     // OK
        // ...
    }
}
  • Cannot Overload a Method Where the Formal Parameter Types of Each Overload Erase to the Same Raw Type

A class cannot have two overloaded methods that will have the same signature after type erasure.

public class Example {
    public void print(Set<String> strSet) { }
    public void print(Set<Integer> intSet) { }
}

因为Set<String>和Set<Integer>在编译后, 都变成了Set, 所以不满足重载条件.

一些习题

https://docs.oracle.com/javase/tutorial/java/generics/QandE/generics-answers.html

相关文章

  • Java 泛型

    一、泛型使用 1、泛型类 2、泛型函数 二、泛型限定符 1、泛型上限 泛型上限使用 extends 限制 多个限制...

  • java 中的泛型

    为什么要使用泛型 类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制...

  • Java 泛型使用限制

    参考 The Java™ Tutorials 限制 无法和原始类型使用, 即类型参数不能是 这些. 不能生成类型参...

  • java泛型及泛型擦除

    泛型的好处: 类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编...

  • java泛型及泛型擦除

    泛型的好处: 类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编...

  • Objective-C 泛型 协变 逆变

    为什么要使用泛型 如何使用泛型 限制泛型 协变 逆变 为什么要使用泛型 在使用NSArray, NSSet, NS...

  • JAVA泛型•约束和局限性

    为了更好地阅读体验,欢迎访问博客原文 泛型参数的限制 在Java中,实例化泛型类时泛型参数不能使用基本类型,如Li...

  • 泛型高级进阶

    一、 限制泛型可用类型 1、自定义泛型类时,默认可以使用任何类型来实例化泛型变量。但是如果想要限制使用的泛型类别,...

  • Java编程思想---泛型(3)

    Java编程思想---泛型(3) 泛型带来的各类问题 任何基本类型都不能作为类型参数 Java泛型的限制之一是不能...

  • Android 开发也要掌握的Java知识 - Java泛型

    如果需要看泛型擦除Java泛型擦除 1.Java泛型有什么用?为啥要使用泛型? Java中数组的类型是定义的时候就...

网友评论

      本文标题:Java 泛型使用限制

      本文链接:https://www.haomeiwen.com/subject/oeijmxtx.html