【Java基础】浅谈泛型
(1)基本介绍
(1)泛型的定义
在对象建立的时候不指定类中属性的具体类型,而由外部在声明和实例化对象的时候再指定具体的类型。
泛型可以解决数据类型的安全性问题,合理的使用泛型需要结合类集框架和反射机制。
例如:
//可以设置一个泛型T,也可以设置多个泛型T和V
class Point<T,V>{
//T是Type的简称,也可以是任意的字母
//表示具体类型在调用这个类的时候由外部决定
private T var;
//构造方法上应用泛型
public Point03(T var) {
super();
this.var = var;
}
public V getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
(2)定义泛型方法的规则
1-所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的 )。
2-每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
3-类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
4-泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像 int、double、char 等)。
(3)java 中泛型标记符
1-E - Element (在集合中使用,因为集合中存放的是元素)
2-T - Type(Java 类)
3-K - Key(键)
4-V - Value(值)
5-N - Number(数值类型)
6-? - 表示不确定的 java 类型
(4)如何使用泛型方法打印不同类型的数组元素
public class GenericMethodTest
{
// 泛型方法 printArray
public static < E > void printArray( E[] inputArray )
{
// 输出数组元素
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] )
{
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "整型数组元素为:" );
printArray( intArray ); // 传递一个整型数组
System.out.println( "\n双精度型数组元素为:" );
printArray( doubleArray ); // 传递一个双精度型数组
System.out.println( "\n字符型数组元素为:" );
printArray( charArray ); // 传递一个字符型数组
}
}
(2)泛型的通配符
(1)匹配任意类型用 ?号
通过通配符 ?接收任意指定泛型类型的对象,表示可以接收次类型的任意泛型对象
案例一
public class GenericsDemo05 {
public static void main(String[] args) {
Info<String> i=new Info<String>();
i.setVar("张三");
fun(i);
}
public static void fun(Info<?> temp) {
System.out.println("内容:"+temp);
}
}
案例二
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);
getData(name);
getData(age);
getData(number);
}
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
}
(2)给匹配类型加个范围
可能有时候,你会想限制那些被允许传递到一个类型参数的类型种类范围。例如,一个操作数字的方法可能只希望接受Number或者Number子类的实例。这就是有界类型参数的目的。
要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。
1-设置上限为Number类
// 只能接收泛型为Number或Number类型的子类
// 如果这时候传递一个字符型的数据,就会报错
public static void fun(Info<? extends Number> temp) {//在类定义的时候指定泛型的上限范围
System.out.println(temp+"、");
}
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(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));
}
}
data :18
data :314
解析: 在 //1 处会出现错误,因为 getUperNumber() 方法中的参数已经限定了参数泛型上限为 Number,所以泛型为 String 是不在这个范围之内,所以会报错。
3、类型通配符下限通过形如 List<? super Number> 来定义,表示类型只能接受 Number 及其上层父类类型,如 Object 类型的实例。
2-设置下限为String类
// 在定义的时候进行了下限的配置,只能接收泛型是String及Object类型的引用
public static void fun(Info03<? super String> temp) {
System.out.println("内容:"+temp);
}
3-案例
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" ) );
}
}
(4)泛型类
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。
和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("菜鸟教程"));
System.out.printf("整型值为 :%d\n\n", integerBox.get());
System.out.printf("字符串为 :%s\n", stringBox.get());
}
}