泛型介绍引用:
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){ //向下转型 Object ==> Dog 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中,代码显示时是没有异常的!这样是存在隐患的,同时编译器是发现不了。在运行之后,会发生报错,类型转换异常!
-
使用这种传统的方法不能对加入到集合ArrayList中的数据类型进行约束(不安全)。同时在遍历时,需要进行类型转换,如果集合中的数据量较大,对效率会存在影响
当使用泛型之后
- 编译器发现了ArrayList添加到类型不满足要求,会报错(没使用泛型是发现不了的),这样在编译时就提高了安全性
- 遍历时,可以直接取出Dog类型,不用类型转换,节省效率!
那么,泛型到底是什么?简单来说,泛型就是——一个表示数据类型的数据类型!
泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值类型,或者是参数类型。
class Person{ E s;// E表示 s 的数据类型,该数据类型在定义Person对象时指定,即在编译期间,就确定E是什么类型 public Person(E s) {//E也可以是参数类型 this.s = s; } public E f(){//也可以是返回类型 return s; } }
假定有这样一个需求:写一个排序方法,能够对整形数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?
答案是使用Java泛型
使用Java泛型的概念,可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整数型数组、浮点数数组、字符串数组等进行排序。
泛型方法定义泛型方法的规则
-
所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数部分在方法返回类型前
-
每一个类型参数声明部分包括一个或多个类型参数,参数键用逗号隔开。一个泛型参数,也被称为一个类型变量,适用于指定一个泛型类型名称的标识符
-
类型参数能被用来声明返回值类型,并且作为泛型方法得到的实际参数类型的占位符
-
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用类型,不能是原始类型(像int、double、char等)
java中的泛型标记符
-
E Element(在集合中使用,因为集合中存在放的是元素
-
T Type(java类)
-
K key(键)
-
V Value(值)
-
N Number(数值类型)
-
? 表示不确定的java类型
实例
下面的列子演示如何使用泛型方法打印不同类型的元素
public class Demo02 { //泛型方法 public staticvoid printArray(E[] inputArray){ //输出元素数组 for(E element : inputArray){ System.out.print(element+" "); } } 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 ); // 传递一个字符型数组 } }
运行结果为:
有界的参数类型
指限制被允许传递到一个类型参数的类型范围。例如,一个 *** 作数字的方法可能只接受Number或者Number子类的实例。这就是有界类型参数参数的目的。要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,然后跟紧他的上界。
public class Demo03 { // 比较三个值并返回最大值 public static泛型类> 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.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{ private T t; public void add(T t){ this.t = t; } public T get(){ return t; } public static void main(String[] args) { Box box1 = new Box<>(); Box box2 = new Box<>(); box1.add(13); box2.add("mikasa"); System.out.println("整数型值为:" + box1.get()); System.out.println("字符串型值为:" + box2.get()); } }
运行结果:
类型通配符 类型通配符一般是使用?代替具体的类型参数。例如List>在逻辑上是List
类型通配符的上限通过形如List extends Number>来定义,如此定义就是通配符泛型值接受Number及其下子层类类型。
import java.util.ArrayList; import java.util.List; public class Demo04 { public static void main(String[] args) { Listname = new ArrayList (); List age = new ArrayList (); List number = new ArrayList (); name.add("mikasa"); age.add(13); number.add(624); // 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){ System.out.println("data:" +data.get(0)); } } //输出结果 //data:18 //data: 314 //getUperNumber(name); 会出现错误,因为 getUperNumber() 方法中的参数已经限定了参数泛型上限为 Number,所以泛型为 String 是不在这个范围之内,所以会报错。
类型通配符下限通过形如List super Number>来定义,表示类型只接受Number及其上层父类类型,如Object类型的实例
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)