java基础_泛型
对于java基础小白来说,遇到泛型的时候开始可能会一脸懵逼…什么玩意这是…
但是了解了它之后,发现还是非常有用的
泛型有什么用?
假设有一个手机修理厂家,可以修各类手机,我们可以用一个类来描述,正常来说,我们可以定义一些修手机的重载方法,让它修苹果手机,然后返回修好的苹果手机,修小米手机,返回修好的小米手机等等…
class RepairFactory {
public Apple repair(Apple iphone) {
//修理
return iphone;//返回修理好的苹果手机
}
public XiaoMi repair(XiaoMi xiaomi) {
//修理
return xiaomi;//返回修理好的小米手机
}
public Sanxing repare(Sanxing sanxing) {
//修理
return sanxing //返回修理好的三星
}
//...
}
是不是发现特别麻烦,那有的同学可能会说,可以用Object呀,像下面这样:
class RepairFactory {
public Object repair(Object obj) {
//修理
return obj;//返回修理好的手机?东西?
}
}
这样做也行,但是如果是Object的话,会不会有一些不放心呢,比如你让商家给你修个苹果手机,结果给你返回一个小米手机,或者是其他手机,也有可能是砖头…这样你是不是会不放心.如果有一种方法或者机制,保证你给商家什么手机,商家就给你返回什么手机,这样你会不会放心一些.那么这时候就可以用到泛型了.可以像下面这样设置.
class RepairFactory{
public <T> T repair(T phone) {
//修理
return phone;//返回修里好的的手机
}
}
repair方法中的T就代表着泛型.这个方法就可以规定你传进去什么手机就返回什么手机.
到这里可能对泛型有了初步的认识了,但是泛型在java中是怎么实现的呢?
这里我将上面的例子在java中做了一下简单的实现:
编译之前:
public class RepairFactory {
public static <T> T repair(T phone) {
//修理过程省略
return phone;
}
public static void main(String[] args) {
IPhone badIPhone = new IPhone();
IPhone repairedIPhone = repair(badIPhone);
}
}
class IPhone {
}
class XiaoMi {
}
下面是java对上面的java文件编译过后的class文件,发现亮点没有?泛型的T全部转化成Object,但是在使用返回的类型的时候,会自动强制转换成传进去的类型,是不是很神奇^_^
public class RepairFactory
{
public RepairFactory()
{
}
public static Object repair(Object phone)//T全部转换成Object
{
return phone;
}
public static void main(String args[])
{
IPhone badIPhone = new IPhone();
IPhone repairedIPhone = (IPhone)repair(badIPhone);//自动强制转换成Ihone类型
}
}
所以泛型在运行的时候会被全部抹去,替换成为Object,但是在使用泛型返回值的地方,会自动强转为指定的类型.
看到这里相信大家对泛型已经有了初步认识,也感受到的好处.对,泛型的作用就是规定类型.
当然上面的例子比较简单,可能不能充分体会到泛型的好处.
但是如果应用到java中常用到的集合ArrayList中,泛型就非常有用了.
泛型出现之前ArrayList添加的元素的时候是可以添加任何类型的,但是我们往往希望在一个集合中存入同一种类型的数据.通过Object添加也可以实现,但是有可能一不小心添加到其他类型的数据
ArrayList list = new ArrayList();
list.add(1);
list.add(2);
list.add("hello");//因为没有指定泛型,所以不会报错,但是我们并不想存入字符串类型
ArrayList<Integer> newList = new ArrayList<>();
newList.add(1);
newList.add("helloworld");//因为指定泛型Integer,所以会报错
虽然运行时,泛型会被默契,但是通过泛型的指定,可以有效避免存入不同类型的数据.这是好处之一,然后指定泛型之后,可以用响应的类型直接引用取出来的值,无需类型转换
ArrayList<Integer> newList = new ArrayList<>();
newList.add(1);
Integer i = newList.get(0);//可以直接用Integer接收
泛型的缺点?
正如泛型的名字一样,泛化的类型,意味着你不知道它的具体类型是什么,不知道它具体的类型是什么就不能直接调用你想赋予类型的方法.
//比如这个手机修理的例子,有一部手机屏幕换了,你就想让他换一下屏幕
class RepairFactory{
public <T> T repair(T phone) {
//修理
phone.changeScreen();//这样是不行的,因为T会替换成Object类型,Object并没有changeScreen()方法,所以编译会报错.
return phone;//返回修里好的的手机
}
}
//但是非泛型传参的时候就可以非常简单调用该类型的方法
public Apple repair(Apple iphone) {
//修理
iphone.changeScreen();//直接换上苹果手机屏幕(假设有这么一个方法)
return iphone;//返回修理好的苹果手机
}
泛型的使用方法:
- 1.定义在类上: 类名<泛型参数>
//比如ArrayList的定义 (源码很多,作为例子截取跟泛型相关的api作为例子)
public class ArrayList<E>{
boolean add(E e)
E set(int index, E element)
}
//定义在类上的泛型,方法中也可以使用
- 2.定义在方法上:方法的返回类型前面加<泛型参数>
比如上面举的修手机方法
java
class RepairFactory{
public <T> T repair(T phone) {
//修理
return phone;//返回修里好的的手机
}
public <T> void repair(T phone) {}//没有返回值也可以添加
}
总结
本文简答的说明了一下泛型的基本用处与用法,总的来说泛型的用处就是指定类型.
当然泛型还有更多更复杂的用法,本人也在学习中,也就不深入讨论了.