一、java泛型基本理解
java 泛型其实你可以将它理解为一种强大的工具,比如你要写一个排序方法,要求该方法能够同时对整型数组、字符型数组甚至别的任何类型进行排序,一个方法就要实现这样的不同类型的排序;按常理来说这个要求需要写多个方法,分别来对他们排序,但是不用,java泛型可以用一个方法就实现这些要求。
字面理解就是:用户可以给出任意的参数类型,我都能有这个方法处理你的参数。
二、java泛型之泛型方法
1、普遍的泛型方法
泛型方法可以接收用户提供的不同类型的参数,下面是定义泛型方法的规则:
a、所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(如下面会有例子)。
b、每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
c、类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
d、泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等),所以才有了你之前看不懂的E,T之类的类型。
实例
下面的例子演示了如何用泛型方法打印不同字符串的元素:
public class GenericMethodTest
{
// 泛型方法 printElement
public static < E > void printElement( E[] YourArray )
{//这里的表示你可以输入任何类型的数组
// 输出数组元素
for ( E element : YourArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] )
{
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 3,6,9,2,4,8 };
Double[] doubleArray = { 3.3,6.6,9.9,2.2,4.4,8.8};
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
//正常调用泛型方法
System.out.println( "整型数组元素为:" );
printElement( intArray ); // 传递一个整型数组
System.out.println( "\n双精度型数组元素为:" );
printElement( doubleArray ); // 传递一个双精度型数组
System.out.println( "\n字符型数组元素为:" );
printElement( charArray ); // 传递一个字符型数组
}
}
2、深入了解java泛型的泛型方法
java泛型的泛型方法不仅是可以接收任何类型的参数,他还可以将泛型方法定义为只接收部分类型的参数。这就是有界类型参数。
要声明一个有界的类型参数,首先列出类型参数的名称(如T),然后名称后面跟extends关键字,最后紧跟这个参数的上界;如:
下面用实例详细说明,下面的例子中的泛型方法返回三个可比较对象的最大值。
public class MaximumTest
{
// 比较三个值并返回最大值
public static > T maximum(T x, T y, T z)
{ //它的意思是只接收那种可以用来比较大小的类型参数。
//算法就是普通算法
T max = x;
if ( y.compareTo( max ) > 0 ){
max = y;
}
if ( z.compareTo( max ) > 0 ){
max = z;
}
return max;
}
public static void main( String args[] )
{
System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",
3, 6, 9, maximum( 3, 6, 9 ) );
System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",
3.3, 6.8, 9.7, maximum( 3.3, 6.8, 9.7 ) );
System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear",
"apple", "orange", maximum( "pear", "apple", "orange" ) );
}
}
三、java泛型之泛型类
1、基本的泛型类
泛型类和非泛型类生命差不多,泛型类在非泛型类的声明基础之上添加了类型参数的声明。此类型参数的声明和泛型方法的参数声明方式一样。
下面是泛型类的定义实例:
public class GenericClass{
private T t;
public void setValue(T t){
this.t = t;
}
public T getValue(T t){
return t;
}
public static void main(String[] args){
GenericClass intValue = new GenericClass();
GenericClass strValue = new GenericClass();
intValue.add(new Integer(3));
strValue.add(new String("yisun03's blog"));
System.out.printf("整数类型实例化:%d\n",intValue.get());
System.out.printf("字符串类型实例化:%s\n",strValue.get());
}
}
2.深入了解泛型类之类型通配符
用问号"?"代替具体的类型参数,如List>。
下面用实例展示类型通配符的用法:
import java.util.*;
public class GenericTest {
public static void main(String[] args) {
/*
用同一个方法实例化了三种不同类型的对象。
因为getData()方法的参数是List类型,而name,age,number
都是List的一种,所以name,age,number都可以作为这个
方法的实参,这就是类型通配符的好处。
*/
List name = new ArrayList();
List age = new ArrayList();
List number = new ArrayList();
name.add("icon");
age.add(18);
number.add(314);
getData(name);
getData(age);
getData(number);
}
public static void getData(List> data) {//类型通配符的用法。
System.out.println("data :" + data.get(0));
}
}
3.类型通配符的上下限
和泛型方法的有界类型参数类似。
类型通配符的上限用extends关键字,如List extends Number>,它的意思是通配符泛型值接收Number及其下层的子类类型(接收是有上线的,不接收Number的父类);
类型通配符的下限用super关键字来定义,如List super Number>,表示通配符泛型值只接收Number及其三层父类类型,如Object类型的实例。
下面用一个实例来说明:
实例中被注释掉的那行代码处会出现错误的,因为getUperNumber()方法中的参数限定了参数泛型的上线为Number,而String不是Number或Number的子类,即不在范围之类,所以报错。
实例
import java.util.*;
public class GenericTest {
public static void main(String[] args) {
List name = new ArrayList();
List age = new ArrayList();
List number = new ArrayList();
name.add("icon");
age.add(18);
number.add(314);
//getUperNumber(name);//该行代码是不正确的。
getUperNumber(age);
getUperNumber(number);
}
public static void getData(List> data) {
System.out.println("data :" + data.get(0));
}
public static void getUperNumber(List extends Number> data) {
//List extends Number>定义上限为Number类型
System.out.println("data :" + data.get(0));
}
}