引用:
B站韩顺平 零基础30天学会java
菜鸟教程-Java泛型
泛型介绍
?
??Java泛型(genetics)是JDK 5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是所操作的数据类型被指定为一个参数。
??Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException 异常(也就是类型安全检测机制),同时,代码更加简洁、健壮。
下面用一个实例详细分析: ??编写程序,在ArrayList中,添加3个Dog对象。Dog对象中有name属性,并输出name(要求使用getName())
- 这里的ArrayList没有
<> ,其中存储的类型是Object
import java.util.ArrayList;
public class Demo01 {
@SuppressWarnings({"all"})
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("来福"));
arrayList.add(new Dog("旺财"));
arrayList.add(new Dog("狗蛋"));
arrayList.add(new Cat("小花"));
for(Object o : arrayList){
Dog dog = (Dog) o;
System.out.println("这里有狗!叫"+dog.getName());
}
}
}
class Dog{
private String name;
public Dog(String name){
this.name = name;
}
public String getName(){
return name;
}
}
class Cat{
private String name;
public Cat(String name){
this.name = name;
}
public String getName(){
return name;
}
}
当使用泛型之后
- 编译器发现了ArrayList添加到类型不满足要求,会报错(没使用泛型是发现不了的),这样在编译时就提高了安全性
- 遍历时,可以直接取出Dog类型,不用类型转换,节省效率!
那么,泛型到底是什么?简单来说,泛型就是——一个表示数据类型的数据类型!
泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值类型,或者是参数类型。
class Person<E>{
E s;
public Person(E s) {
this.s = s;
}
public E f(){
return s;
}
}
假定有这样一个需求:写一个排序方法,能够对整形数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?
答案是使用Java泛型
使用Java泛型的概念,可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整数型数组、浮点数数组、字符串数组等进行排序。
泛型方法
定义泛型方法的规则
-
所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数部分在方法返回类型前 -
每一个类型参数声明部分包括一个或多个类型参数,参数键用逗号隔开。一个泛型参数,也被称为一个类型变量,适用于指定一个泛型类型名称的标识符 -
类型参数能被用来声明返回值类型,并且作为泛型方法得到的实际参数类型的占位符 -
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用类型,不能是原始类型(像int、double、char等)
java中的泛型标记符
实例
下面的列子演示如何使用泛型方法打印不同类型的元素
public class Demo02 {
public static <E> void printArray(E[] inputArray){
for(E element : inputArray){
System.out.print(element+" ");
}
}
public static void main( String args[] ) {
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 );
}
}
运行结果为:
有界的参数类型
??指限制被允许传递到一个类型参数的类型范围。例如,一个操作数字的方法可能只接受Number或者Number子类的实例。这就是有界类型参数参数的目的。要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,然后跟紧他的上界。
public class Demo03 {
public static <T extends Comparable<T>> 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.println( "3,4,5 中最大的数为"+ maximum( 3, 4, 5 ) );
System.out.println( "6.6, 8.8, 7.7 中最大的数为" + maximum( 6.6, 8.8, 7.7 ));
System.out.println( "pear,apple,orange中最大的数为" + maximum( "pear", "apple", "orange" ));
}
}
泛型类
??泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。
??和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
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> box1 = new Box<>();
Box<String> box2 = new Box<>();
box1.add(13);
box2.add("mikasa");
System.out.println("整数型值为:" + box1.get());
System.out.println("字符串型值为:" + box2.get());
}
}
? 运行结果:
类型通配符
??类型通配符一般是使用?代替具体的类型参数。例如List<?> 在逻辑上是List<String> ,List<Integer> 等所有List<具体类型实参> 的父类
??类型通配符的上限通过形如List<? extends Number> 来定义,如此定义就是通配符泛型值接受Number及其下子层类类型。
import java.util.ArrayList;
import java.util.List;
public class Demo04 {
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("mikasa");
age.add(13);
number.add(624);
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){
System.out.println("data:" +data.get(0));
}
}
??类型通配符下限通过形如List<? super Number>来定义,表示类型只接受Number及其上层父类类型,如Object类型的实例
|