深入理解java泛型详解,java泛型的用法
目录
1.什么是泛型2。派生泛型3。泛型类的语法4。裸体类型5。如何编译泛型5.1擦除机制5.2?为什么泛型数组不能实例化6。泛型的上界7。通配符7.1。7.2可以用什么通配符?通配符上限(读取数据)7.3。通配符的下限(写入数据)。
1.什么是泛型
泛型是JDK1.5中引入的新语法,一般来说,泛型适用于很多很多类型。从代码的角度来看,类型是参数化的。
有些兄弟看到这句红色的话可能会很困惑。我们过去传递参数,但它是一个整形数据和一个引用。我从来没有通过类型测试。类型还能作为参数传递吗?马鞭马鞭是的,没错。接下来,让我们看看类型作为参数传递的实现。
2.引出泛型
我们以前研究过遗传和多态性。我们知道所有类的父类默认都是Object class。我们现在的目标是:任何类型的数据都可以存储在数组中。这时,我们可以创建一个对象类型的数组,
class MyArray { public Object[]array=new Object[10];public Object get pos(int pos){ return array[pos];} public void setPos(int pos,Object value){ array[pos]=value;} } public class test demo { public static void main(String[]args){ MyArray MyArray=new MyArray();myArray.setPos(0,1);myArray.setPos(1, hello );}}当我们写这样的代码时,发现数组中的所有元素都可以放,比如整形数据,字符串,小数。可以放进去的东西太多了。你能知道带下标的元素是什么样的吗?马鞭当我们取元素的时候,会发现你的代码无法编译,
为什么会这样?相信大部分兄弟都知道我们观察到getPos的返回值是Object,也就是说我们取出来的可能是任意元素,但是编译器知道吗?马鞭马鞭它只知道它返回一个对象:这是显而易见的。父类给子类。这不是纯粹的向下转型吗?向下转换必须强制类型,否则您的代码不会通过。
那么问题又来了。我这里只是放了两个元素,肉眼还是能看出来的,但是里面的类型一直在变。即使知道类型,也需要每次都强转吗?我是动态的,我的代码写死了,所以这个地方如果用Object来做,会特别麻烦,局限性非常大。
我们现在面临两个困境:
1.什么类型都可以玩,而且不好控制,
2.每当你获取一个元素,你必须转换类型,
这个时候,我们不得不搞希望工程。我们的希望是:
1.我们可以自己指定类型吗?
2.能不能停止类型转换,省略这一步,兄弟!
为了解决这个问题,我们java引入了这个东西——泛型。
那么如何指定类型呢?让我们看看代码:
class MyArray T {//public Object[]array=new Object[10];public T[]array=(T[])new Object[10];//这样写也不好。为什么以后会说?马鞭public T get pos(int pos){ return array[pos];} public void setPos(int pos,T value){ array[pos]=value;}} public class测试演示{ public static void main(string[]args){//我指定放shape myarray integer myarray=new myarray();//后面尖括号中的类型可以省略,实例化对象时可以根据前面进行判断。//myarrayInteger myarray=newmyarrayInteger();myArray.setPos(0,1);myArray.setPos(1,2);integer ret=myarray . get pos(1);system . out . println(ret);//我指定字符串类型MyArrayStrin。
g> myArray2 = new MyArray<>(); myArray2.setPos(0,"abc"); myArray2.setPos(1,"bit"); String ret2 = myArray2.getPos(0); System.out.println(ret2); }}这个代码有几个注意事项:
1.尖括号<>里面只能放引用类型;
2.<T>是一个占位符,代表当前类是一个泛型类;
3.MyArray<Integer> array = new MyArray<>();后面的尖括号可以省略Integer不写,实例化对象的 时候编译器根据前面能做出判断。
看完上面的代码,我相信兄弟们已经明白是怎么一回事了吧
我们刚刚的希望工程也已经实现了
1.<Integer>,指定当前类中,使用的类型是Integer类型
2.泛型帮我在编译期间做了2件事情(目前为止的优点):
存放元素的时候,进行类型的检查取元素的时候,帮我进行类型的转换
3.泛型类的语法
有了刚刚知识的铺垫,这一块咱就形式化一下啦,,当然,语法还是很重要滴!!
语法:
泛型类<类型实参> 变量名; // 定义一个泛型类引用new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
栗子:
MyArray<Integer> list = new MyArray<Integer>();
4.裸类型
说明:
兄弟们,咱学了新东西,这旧东西,咱也得了解一下是不咯,,万一以后跟别人聊到了,自己好像从来没听过就尴尬了,,
裸类型是一个泛型类但没有带着类型实参,例如 MyArrayList 就是一个裸类型
MyArray list = new MyArray();
注意: 我们不要自己去使用裸类型,裸类型是为了兼容老版本的 API 保留的机制
5.泛型如何编译的
5.1 擦除机制
我用的是Powershell窗口查看的字节码文件,当然用idea的兄弟们也可以去下载一个展示字节码的插件,,接下来我们看看泛型到底是怎么编译的,,javap -c查看字节码
我们发现在编译期间,所有的T都被擦除为了Object,那既然所有的T都变成了Object,那我们为什要指定类型呢?注意这里不是编译的时候替换,指定类型只是为了在编译的时候帮我们进行类型的检查和转换,并不是替换!!!最终字节码编译完成的时候,所有的T变成了Object,而这就是我们Java当中泛型所谓的擦除机制!!!
提问:那既然T在编译的时候被擦除为了Object,那为啥 T[] array = new T[] 会报错呢?
5.2会给你答案
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。