在 Java 泛型使用过程中,开发者常犯或容易误解的错误主要集中在类型擦除、边界使用、数组与泛型、通配符、类型推断等方面。下面按“常见错误 + 原因 + 正确做法”的方式说明。
public <T> void test() {
if (T instanceof String) { } // 编译错误
}
List<String> list = new ArrayList<>();
if (list instanceof List<String>) { } // 编译错误
Java 泛型是编译期特性,运行时会进行类型擦除,泛型信息不存在于 JVM 中。
Class<T> 参数public <T> void test(Class<T> clazz) {
if (clazz == String.class) { }
}
List<String>[] lists = new List<String>[10]; // 编译错误
数组在运行期需要具体类型,而泛型在运行期被擦除。
List<String>[] lists = (List<String>[]) new List[10]; // 不推荐但可行
或更好:
List<List<String>> lists = new ArrayList<>();
List<int> list = new ArrayList<>(); // 编译错误
泛型只接受引用类型。
List<Integer> list = new ArrayList<>();
class Box<T> {
static T value; // 编译错误
}
静态成员属于类,不属于某个泛型实例。
class Box<T> {
static Object value;
}
List<? extends Number> list = new ArrayList<>();
list.add(1); // 编译错误
? extends Number 表示“某种未知子类”,不能安全写入。
List<? super Integer> list = new ArrayList<>();
list.add(1); // OK
List list = new ArrayList();
list.add("abc");
List<Integer> ints = list; // 警告但能编译
运行时 ClassCastException
始终声明泛型类型:
List<Integer> ints = new ArrayList<>();
public <T> T get() { return null; }
String s = get(); // 可能推断失败
String s = this.<String>get();
try {
} catch (T e) { } // 编译错误
异常类型必须在编译期确定。
class Utils {
<T> T convert(T t) { return t; }
}
调用时误以为和类泛型有关。
class Box<T><T> T method()List<? extends ? super Number>
只在 API 边界(参数/返回值)使用通配符,内部实现用具体泛型。
| 错误类型 | 关键点 |
|---|---|
| 泛型不是运行时类型 | 类型擦除 |
| 不能用基本类型 | 用包装类 |
| 不能 new 泛型数组 | 用 List |
| 静态不能用泛型 | 属于类 |
| 通配符写不进 | PECS |
| 忽略警告 | 隐藏 bug |
如果你愿意,我也可以:
你想看哪一个?
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。