泛型
当集合中存储的对象类型不同时,那么会导致程序在运行的时候的转型异常
package cn.chen.demo;
import java.util.ArrayList;
import java.util.Iterator;
public class Demo {
public static void main(String[] args) {
ArrayList arr = new ArrayList();
arr.add( new Tiger("华南虎 "));
arr.add( new Tiger("东北虎 "));
arr.add( new Sheep("喜羊羊 "));
System. out .println(arr);
Iterator it = arr.iterator();
while (it.hasNext()) {
Object next = it.next();
Tiger t = (Tiger) next;
t.eat();
}
}
}
class Tiger {
String name;
public Tiger() {
}
public Tiger(String name) {
this .name = name;
}
@Override
public String toString() {
return "Tiger@name:" + this. name ;
}
public void eat() {
System. out .println( this. name + "吃羊 " );
}
}
class Sheep {
String name;
public Sheep() {
}
public Sheep(String name) {
this .name = name;
}
@Override
public String toString() {
return "Sheep@name:" + this. name ;
}
public void eat() {
System. out .println( this. name + "吃青草 " );
}
}
运行结果:
[Tiger@name:华南虎 , Tiger@name:东北虎 , Sheep@name:喜羊羊 ]
Exception in thread "main" 华南虎 吃羊
东北虎 吃羊
java.lang.ClassCastException: cn.chen.demo.Sheep cannot be cast to cn.chen.demo.Tiger
at cn.chen.demo.Demo.main(Demo.java:16)
原因 :虽然集合可以存储任意对象,但是如果需要使用对象的特有方法,那么就需要类型转换,如果集合中存入的对象不同,可能引发类型转换异常.
出现问题:
- 存入的是特定的对象,取出的时候是Object对象,需要强制类型转换,可能诱发类型转换异常.
- 无法控制存入的是什么类型的对象,取出对象的时候进行强转时可能诱发异常.而且在编译时期无法发现问题.
- 虽然可以再类型转换的时候通过if语句进行类型检查(instanceof),但是效率较低.(例如吃饭的时候,还需要判断米饭里有没有沙子,吃饭效率低).可以通过给容器加限定的形式规定容器只能存储一种类型的对象.
- 就像给容器贴标签说明该容器中只能存储什么样类型的对象。
- 在jdk5.0后出现了泛型
格式:集合类<类类型> 变量名 = new 集合类<类类型>();
- 细节
- 声明好泛型类型之后,集合中只能存放特定类型元素
- 泛型类型必须是引用类型
- 使用泛型后取出元素不需要类型转换.
泛型方法
1. 函数上的泛型定义
当函数中使用了一个不明确的数据类型,那么在函数上就可以进行泛型的定义。
public <泛型的声明> 返回值类型 函数名(泛型 变量名){
}
使用泛型方法前需要进行泛型声明,使用一对尖括号 <泛型>,声明的位置在static后返回值类型前。
当一个类中有多个函数声明了泛型,那么该泛型的声明可以声明在类上。
2.类上的泛型声明
修饰符 class 类名 <泛型>{
}
3.在泛型类中定义一个静态方法
注意:静态方法不可以使用类中定义的泛型
因为类中的泛型需要在对象初始化时指定具体的类型,而静态优先于对象存在。那么类中的静态方法就需要单独进行泛型声明,声明泛型一定要写在static后,返回值类型之前
4.泛型类细节
- 创建对象的时候要指定泛型的具体类型
- 创建对象时可以不指定泛型的具体类型 ( 和创建集合对象一眼 )。默认是 Object ,例如我们使用集合存储元素的时候没有使用泛型就是那么参数的类型就是 Object
- 类上面声明的泛型只能应用于非静态成员函数,如果静态函数需要使用泛型,那么
需要在函数上独立声明。 - 如果建立对象后指定了泛型的具体类型,那么该对象操作方法时,这些方法只能操作一种数据类型。
- 所以既可以在类上的泛型声明,也可以在同时在该类的方法中声明泛型。
泛型接口
//泛型接口
interface Inter<T> {
void print(T t);
}
//1.实现不知为何类型时可以这样定义
class MyInter<T> implements Inter<T> {
public void print(T t) {
System. out .println("不知道类型:" + t);
}
}
//2.使用接口时明确具体类型。
class MyInter2 implements Inter<String> {
@Override
public void print(String t) {
System. out .println("String类型:" + t);
}
}