1.啥是泛型?
Java SE 5.0引入了“泛型”的概念,泛型实现了参数化类型,使代码可以应用于多种类型,让类或方法具备了更广泛的表达能力。
2.为嘛要引入泛型?
先来看一段代码:
class Print {
int i;
Print(int i) {
this.i = i;
}
void print() {
System.out.println(i);
}
}
class Print2 {
char i;
Print2(char i) {
this.i = i;
}
void print() {
System.out.println(i);
}
}
class Print3 {
String i;
Print3(String i) {
this.i = i;
}
void print() {
System.out.println(i);
}
}
public class Test {
public static void main(String[] args) {
Print p1 = new Print(5);
p1.print();
Print2 p2 = new Print2('a');
p2.print();
Print3 p3 = new Print3("Hello World");
p3.print();
}
}
类似的类结构,但因为属性的类型不同,就要写这么多类,既然属性值可以用属性名来代替,那么属性类型就不能也引入一个类似“属性名”的来代替?这就可以使用泛型了。
看一下使用泛型之后的代码
class Print<T> {
T i;
Print(T i) {
this.i = i;
}
void print() {
System.out.println(i);
}
}
public class Test {
public static void main(String[] args) {
Print<Integer> p1 = new Print<Integer>(5);
p1.print();
Print<Character> p2 = new Print<Character>('a');
p2.print();
Print<String> p3 = new Print<String>("Hello World");
p3.print();
}
}
使用泛型之后,类只要写一个,用泛型的T来代替属性类型
3.泛型对象的使用?
可以看一下上面使用泛型的例子,T是类型参数,所以在创建Print实例时就要指名T所要持有类型,否则就会默认为Object类型。
Java 7 开始引用“菱形”语法,允许构造器后不需要带完整的泛型信息,只要给出一对尖括号(<>)就可以,所以以上的代码就可以简写为
Print<Integer> p1 = new Print<>(5);
Print<Character> p2 = new Print<>('a');
Print<String> p3 = new Print<>("Hello World");
Java 能够推断出尖括号里应该是什么泛型信息,改写后的程序运行结果一样。
泛型对象还可以带两个甚至更多的泛型参数
看下面的例子:
class Print<T,V> {
T i;
V v;
Print(T i,V v) {
this.i = i;
this.v=v;
}
void print() {
System.out.println(i+"--"+v);
}
}
public class Test {
public static void main(String[] args) {
Print<Integer,String> p1 = new Print<>(5,"heihei");
p1.print();
}
}
一个泛型类就是具有一个或多个类型变量的类,即泛型类可以带有两个及以上类型参数,参数之间用逗号分隔。
4.泛型方法?
那么既然有泛型类,那么有没有泛型方法?
有,只需要将泛型参数列表置于方法返回值之前即可。
看例子:
class Print {
<T, V> void print(T i, V v) {
System.out.println(i + "--" + v);
}
}
public class Test {
public static void main(String[] args) {
Print p1 = new Print();
p1.<Integer, String>print(55, "heihei");
}
}
这个泛型方法是在普通类(而不是泛型类)中定义的,其类型变量放在修饰符的后面,返回值类型的前面。
那么什么时候使用泛型方法,而不是泛型类呢?
(1)添加类型约束至作用于一个方法的多个参数之间,而不涉及到类中的其他方法时。
(2)施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型参数。
5.受限泛型?
在定义泛型类型时,若没有指定其参数类型继承的类(接口),就默认继承自Object,所以任何类型都可作为参数传入来实例化该泛型。但如果想要限制使用此泛型的类别,可以在定义参数类型时使用extends 关键字指定这个类型的父类(或实现的接口),以确保没有用不适当的类型来实例化类型参数。
看例子:
class Print<T, V extends String> {
T i;
V v;
Print(T i, V v) {
this.i = i;
this.v = v;
}
void print() {
System.out.println(i + "--" + v);
}
}
public class Test {
public static void main(String[] args) {
Print<Integer, String> p1 = new Print<>(5, "heihei");
p1.print();
}
}
上面的泛型中V被限制为只能使用String及其子类的对象,其他的对象放进去就会编译错误