为何要使用泛型?
首先我们以ArrayList为例,在使用ArrayList的时候常会遇到两个问题
1,当获取一个值的时候必须进行强制类型转换
2,当向其中放入值的时候没有约束只要是对象就行了
所以对数据操作失误便会引起程序报错,于是我们可以使用泛型提供的类型参数来解决这个问题
ArrayList<String> arr = new ArrayList<String>();
此时编译器在我们使用get()方法时自动知道返回的是String类型,不需要我们去进行类型转换,同样当我们去使用add()方法时编译器也会知道要添加的数据为String类型
一,泛型类
定义:具有一个或者多个的类型变量的类,称之为泛型类。
package test;
public class Person<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Person<Integer> integerP = new Person<Integer>();
Person<String> stringP = new Person<String>();
integerP.add(new Integer(6));
stringP.add(new String("复仇者联盟"));
System.out.println("组织成员有 :" + integerP.get() + "人");
System.out.println("这个组织是 :" + stringP.get());
}
}
二,泛型方法:所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前,每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。
package test;
public class MethodTest{
// 泛型方法 printArray
public static < E > E add( E[] numbers ){
// 输出数组元素
return numbers[0];
}
public static void main( String args[] ){
// 创建整型数组: Integer
Integer[] numbers = { 1, 2, 3, 4, 5 };
System.out.println( "整型数组元素为:" + add(numbers));
}
}
下面的例子演示了"extends"如何使用在一般意义上的意思"extends"(类)或者"implements"(接口)。该例子中的泛型方法返回三个可比较对象的最大值。
package test;
public class MaximumTest
{
// 比较三个值并返回最大值
public static <T extends Comparable<T>> T maximum(T x, T y, T z)
{
T max = x; // 假设x是初始最大值
if ( y.compareTo( max ) > 0 ){
max = y; //y 更大
}
if ( z.compareTo( max ) > 0 ){
max = z; // 现在 z 更大
}
return max; // 返回最大对象
}
public static void main( String args[] )
{
System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",
3, 4, 5, maximum( 3, 4, 5 ) );
System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",
6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear",
"apple", "orange", maximum( "pear", "apple", "orange" ) );
}
}
三,类型通配符:类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List<String>,List<Integer> 等所有List<具体类型实参>的父类。
package test;
import java.util.ArrayList;
import java.util.List;
public class GenericTest {
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
//getUperNumber(name);//1此处会报错,因为getUperNumber()方法中的参数已经限定了参数泛型上限为Number
getUperNumber(age);//2
getUperNumber(number);//3
}
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
public static void getUperNumber(List<? extends Number> data) {
System.out.println("data :" + data.get(0));
}
}
类型通配符下限通过形如 List<? super Number>来定义,表示类型只能接受Number及其三层父类类型,如 Object 类型的实例。
四,常见问题
1,不能使用基本数据类型实例化类型参数
2,运行时类型查询只适用于原始类型
3,泛型不能用在异常类实例
4,不能实例化类型变量
5,不能在静态内容中使用类型变量