发布于2026-07-19 阅读(0)
扫一扫,手机访问
泛型是 Ja va 语言中一个非常实用的特性,它允许你写代码的时候先不把类型定死,等到真正用的时候再指定。打个比方,就像设计一个“盒子”,你只告诉别人“这个盒子能装东西”,但具体装什么——是苹果还是书本——由使用者决定。这类设计在集合框架里用得最多,因为集合在声明阶段根本不知道你会往里塞什么类型的对象。
用专业点的话说,泛型就是在定义类、接口或方法时,用一个标识符(比如 T、E)来表示某个属性的类型,或者方法的返回值类型、参数类型。这个类型参数会在你实际使用的时候确定下来——比如继承、实现接口、声明变量、创建对象时传入具体的类型实参。
Ja va 集合框架在 JDK 1.5 之前,容器里能装什么类型是不确定的,所以设计者把元素类型统一设成了 Object。这样一来,你从集合里取出来的东西都得强转,而且直到运行时才能发现类型不对。JDK 1.5 引入泛型之后,情况就完全不同了——除了元素的类型不确定,其他部分(比如元素怎么存、怎么管理)都是确定的,所以干脆把元素类型设计成一个参数,也就是泛型。像 Collection、List、ArrayList 里的 E,就是那个类型参数。
先看一段没有泛型时的代码:
import ja va.util.ArrayList;
import ja va.util.List;
public class test {
public static void main(String[] args) {
List list = new ArrayList();
list.add("string");
list.add(100);
for (int i = 0; i < list.size(); i++) {
String name = (String) list.get(i); // 1
System.out.println("name:" + name);
}
}
}
运行这段代码会抛出 ClassCastException,因为 ArrayList 里同时塞了 String 和 Integer,而循环里却把它们都当成 String 强转,自然就出错了。
引入泛型之后,问题迎刃而解:
import ja va.util.ArrayList;
import ja va.util.List;
public class test {
public static void main(String[] args) {
List list = new ArrayList();
list.add("string");
// list.add(100); // 编译错误
for (int i = 0; i < list.size(); i++) {
String name = list.get(i); // 2
System.out.println("name:" + name);
}
}
}
如果你试着加一个 100,编译器会直接报错:add(int) 找不到合适的方法 —— 参数不匹配,int 无法转换为 String。这就是泛型带来的编译期类型检查,把运行时错误提前挡在了门外。
泛型的好处总结一下:
add(E e) 变成 add(Integer e)。Integer 代替 int。Object。一个泛型类就是拥有一个或多个类型变量的类。看个简单的例子:
public class test {
public static class Point {
private T var;
public void setVar(T x) {
this.var = x;
}
public T getVar() {
return this.var;
}
}
public static void main(String[] args){
Point p = new Point();
p.setVar(new Float(100.12f));
System.out.println(p.getVar());
}
}
尖括号里的 T 是形式类型参数,你可以随便起名字(比如 E、K、V)。当类被使用的时候,就会传入实际类型参数,比如这里的 Float。需要说明的是,泛型类只能用在成员变量上,而且只能使用引用类型。
泛型方法有自己的规则:类型参数声明部分(用尖括号括起来)必须放在方法返回类型之前。可以声明一个或多个类型参数,用逗号隔开。类型参数可以用来声明返回值类型,也可以作为方法参数类型的占位符。方法体和其他方法一样,但注意类型参数只能代表引用类型,不能是原始类型(int、double、char 等)。
public class MethodTest {
int var = 100;
String varStr = "Hello Datawhale";
public T Method(T a) {
return a;
}
public static void main(String[] args) {
MethodTest t = new MethodTest();
System.out.println(t.Method(t.var));
System.out.println(t.Method(t.varStr));
}
}
实现泛型接口时,可以在子类中指定具体的类型参数。比如下面这个例子:
class InfoImpl implements Info{ // 定义泛型接口的子类
private String var ; // 定义属性
public InfoImpl(String var){ // 通过构造方法设置属性内容
this.setVar(var) ;
}
@Override
public void setVar(String var){
this.var = var ;
}
@Override
public String getVar(){
return this.var ;
}
}
public class GenericsDemo24{
public void main(String arsg[]){
InfoImpl i = new InfoImpl("harvic");
System.out.println(i.getVar()) ;
}
};
当你不确定具体类型参数时,可以用 ? 代替,它表示未知类型。类型通配符只能用在声明类型、方法参数上,不能用在定义泛型类上。看个例子:
public class match {
public static void test(List> list) {
List> list2;
list2 = new ArrayList();
list2 = new ArrayList();
list2 = new ArrayList
这段代码里,List> 可以接受任何类型的 ArrayList,但你不能往里面写数据(除了 null),因为类型不确定,编译器不让你做任何可能破坏类型安全的操作。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8