泛型
泛型概述
- 泛型:可以在类或者方法当中预支的使用未知的数据类型。
- 备注:一般在创建对象的时候,将未知的数据类型确定为具体的数据类型,当没有指定泛型时,默认类型为Object类型。
使用泛型的好处 - 1、避免了类型转换的麻烦,存储的是什么数据类型,取出的就是什么数据类型
- 2、把运行期异常(代码运行之后会抛出的异常)提升到编译器阶段(写代码的时候就会报错)
- 备注:泛型它其实也是数据类型的一部分,一般我们将类名和泛型合并一起看做数据类型
泛型的定义与应用
泛型,用来灵活的将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。因为我们的集合框架体系中,大量的使用了泛型
定义和使用含有泛型的类:
定义格式:
修饰符 class 类名<代表泛型的变量>{
}
例如:
public class ArrayList<E> {
public booelan add(E e){}
public E get(int index){}
//........
}
自定义一个带有泛型的类:
/**
* 定义一个含有泛型的类,模拟ArrayList集合
* 泛型是一个未知的数据类型,当我们不知道要什么样的数据类型,可以使用泛型
* 泛型可以接受任意的数据类型,可以使用Integer,String,People,Student,Object......
* 创建对象的时候,必须确定具体的数据类型
*/
public class GenericClass<E> {
private E unkonwn;
public E getName() {
return unkonwn;
}
public void setName(E unkonwn) {
this.unkonwn = unkonwn;
}
}
测试并确定自定义的类的泛型:
public static void main(String[] args) {
GenericClass genericClass = new GenericClass();
genericClass.setName("小孙");//只能写字符串
//我想往对象当中存储Integer类型的值
GenericClass<Integer> gc2 = new GenericClass<>();
gc2.setName(123);
int name = gc2.getName();//自动拆箱
System.out.println(name);
GenericClass<String> gc3 = new GenericClass<>();
gc3.setName("小赵");
String name1 = gc3.getName();
System.out.println(name1);
}
备注:定义的时候使用未知的泛型的变量,使用的时候(创建对象)确定的泛型的具体类型。
定义并使用含有泛型的方法
定义格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(泛型参数){}
例如:
/**
* 定义含有泛型的方法,泛型定义在方法的修饰符返回值之间
* 含有泛型的方法要确定泛型的数据类型
* 传递什么类型的实参,泛型就会被解析成什么样类型
*/
public class GenericMethod {
// 定义带有泛型的方法
public <VIP> void show (VIP vip) {
System.out.println(vip);
}
// 定义一个含有泛型的返回值
public <VIP> VIP show02(VIP vip) {
//.....
return vip;
}
}
// 定义测试类
public class TestGenericMethod {
public static void main(String[] args){
// 创建对象
GenericMethod gm = new GenericMethod();
// 调用带有泛型的方法
gm.show("abc");// VIP vip 参数 ---》形参 String str str="abc"
gm.show(123);// VIP--->Integer vip = 123
gm.show2(3.14);// VIP --->Double vip=3.14
}
}
定义并使用含有泛型的接口
定义格式:
修饰符 interface 接口名<代表泛型的变量> {}
例如:
public interface Collection<E> {
public void add(E e);
public Iterator<E> iterator();
}
//自定义一个泛型的接口
public interface MyGenericInterface<T>{
public abstract void add(E e);
public abstract E get();
//.......
}
使用格式:
1、定义实现类时可以确定泛型的类型
public class MyInterFaceImpl implements MyGenericInterFace<String>{
@Override
public void add(String e){
//......
}
@Override
public String get(){
//........
}
}
**备注:**此时泛型【T的值】就是String类型
2、始终不确定泛型的类型,直到创建对象的时候,确定泛型的类型
例如:
public class MyInterfaceImpl02<T> implements MyGenericInterface<T> {
@Override
public void add(T t) {
//....
}
@Override
public T get(){
//......
}
}
确定泛型
/*
使用泛型
*/
public class Demo04Generic {
public static void main(String[] args) {
MyInterface<String> my = new MyInterfaceImpl<String>();
my.add("abc");
}
}
这是演示创建对象的时候不使用泛型和使用泛型的区别:
public static void main(String[] args) {
show01();
show02();
}
/**
* 创建对象的时候,不使用泛型
* 好处:
* 可以存储任意数据类型的数据 默认的类型是Object
* 坏处:
* 不安全,伴随这引发异常。
*/
public static void show01(){
ArrayList list = new ArrayList();
list.add("abcefg");
list.add(123);
//使用迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Object obj = iterator.next();
String str = (String)obj;
System.out.println(obj);
}
}
/**
* 创建对象的时候,使用泛型
* 好处:
* 1、避免了类型转换的麻烦,存储的是什么数据类型,取出的就是什么数据类型
* 2、把运行期异常(代码运行之后会抛出的异常)提升到编译器阶段(写代码的时候就会报错)
* 坏处:
* 泛型是什么样的类型,只能存储什么样的类型的数据
*/
public static void show02(){
ArrayList<String> list = new ArrayList<>();
list.add("abc");
//使用迭代器遍历集合
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String str = iterator.next();
System.out.println(str);
}
}