您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

Java 泛型与包装类示例分析

2024/3/3 16:09:26发布17次查看
1、什么是泛型泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。
先看以下的例子:
我们以前学过的数组,只能存放指定类型的元素。如:int[] array=new int[10];string[] array=new string[10];而object类是所有类的父类,那么我们是否可以创建obj数组呢?
class myarray{ public object[] array=new object[10]; public void setval(int pos,object val){ this.array[pos]=val; } public object getpos(int pos){ return this.array[pos]; }}public class testdemo{ public static void main(string[] args) { myarray myarray=new myarray(); myarray.setval(1,0); myarray.setval(2,"shduie");//字符串也可以存放 string ret=(string)myarray.getpos(2);//虽然我们知道它是字符串类型,但是还是要强制类型转换 system.out.println(ret); }}
以上代码实现后,我们发现:
任何类型的数据都能存放
2号下标本来就是字符串,但是必须进行强制类型转换
以此引出泛型,泛型的目的就是:指定当前的容器要持有什么类型的对象,让编译器自己去检查。
2、泛型的语法class 泛型类名称< 类型形参列表>{
//这里可以使用类型参数
}
泛型的使用:
泛型类<类型实参> 变量名=new 泛型类<类型实参>(构造方法实参)
myarray list=new myarray<>();
【注】
类型后的<>代表占位符,表示当前类是一个泛型类
在实例化泛型时,<>中不能是简单的类型,需要是包装类
<>不参与泛型的类型组成
不能new泛型类型的数组
使用泛型不需要进行强制类型转换
一个简单的泛型:
//此处t可以随便写为任意标识,常见的如t、e、k、v等形式的参数常用于表示泛型//在实例化泛型类时,必须指定t的具体类型public class test<t>{ //key这个成员变量的类型为t,t的类型由外部指定 private t key; public test(t key) { //泛型构造方法形参key的类型也为t,t的类型由外部指定 this.key = key; } public t getkey(){ //泛型方法getkey的返回值类型为t,t的类型由外部指定 return key; }}
擦除机制:编译时会将<>中的类型擦除掉,所以<>中的东西不参与类型的组成。会将t擦除为object。
为什么不能实例化泛型类型的数组?
数组和泛型之间的一个重要区别是它们如何强制执行类型检查。数组在运行时存储和检查类型信息,而泛型是在编译时检查类型错误。
返回的object数组里面,可能存放着任何类型的数据,如string,通过int类型的数组来接收,编译器认为是不安全的。
3、泛型的上界语法:
class 泛型类名称<t extends 类型边界>{
}
例:
public class myarray{} //e只能是number或number的子类
public class myarray<e extends comparable<e>>{}
//e一定实现了comparable接口的类
【注】没有指定边界的e,可以看作 e extends object
4、通配符? 用于在泛型的使用,即为通配符。通配符用来解决反泛型无法协变的问题。
如下两段代码:
代码一:public static<t> void printlist1(arraylist<t> list){ for(t x:list){ system.out.println(x); }} 代码二:public static<t> void printlist2(arraylist<?> list){ for(object x:list){ system.out.println(x); }}
代码2中使用了通配符,和代码1相比,此时传入代码1的具体是什么数据类型,我们是不清楚的。
(1)通配符的上界语法:
<? extends 上界>
<? extends number>//可以传入的实参类型为number或number的子类
例:对于以下关系,我们需要写一个方法来打印存储了animal或者animal子类的list。
animal
cat extends animal
dog extends animal
代码一:
public static <t extends animal> void print1(list<t> list>{ for(t animal:list){ system.out.println(animal);//调用了t的tostring }}
此时t类型是animal的子类或自己。
代码二:通过通配符实现
public static void print2(list<? extends animal> list){ for(animal animal:list){ syatem.out.println(animal);//调用了子类的tostring方法 }}
两种代码的区别:
对于泛型实现的方法来说,<t extends animal>对t进行了限制,只能是animal的子类。传入cat,就是cat。
对于通配符实现的方法来说,相当于对animal进行了规定,允许传入animal的子类。具体哪个子类,此时并不清楚。如:传入cat,实际上声明的类型是animal,使用多态才能调用cat的tostring方法
通配符上界&rarr;父子类关系:
//需要使用通配符来确定父子类型
myarraylist<? extends number>是myarraylist<integer>或者myarraylist<double>的父类
myarraylist<?>是myarraylist<? extends number>的父类
arraylist<integer> arraylist1 = new arraylist<>(); arraylist<double> arraylist2 = new arraylist<>(); list<? extends number> list = arraylist1; //list.add(1,1);//报错,此时list的引用的子类对象有很多,再添加的时候,任何子类型都可以,为了安全,java不让这样进行添加操作。 number a = list.get(0);//可以通过 integer i = list.get(0);//编译错误,只能确定是number子类
【注】
不能对其进行添加,list中存储的可能是number也可能是number的子类,无法确定类型。
通配符上界适合读取,不适合写入。
(2)通配符的下界语法:
<? super 下界>
<? super integer>//可以传入的参数类型是integer或者integer的父类
通配符下界的父子类关系:
myarraylist<? super integer>是myarraylist<intrger>的父类类型
myarraylist<?>是myarraylist<? super integer>的父类
通配符下界适合写入元素,不适合读取。
5、包装类在java中,由于基本类型不是继承自object,为了在泛型中可以支持基本类型,每个基本类型都对应了一个包装类。除了integer和character,其余基本类型的包装类都是首字母大写。
拆箱和装箱:
int i=10; //装箱操作,新建一个integer类型对象,将i的值放入对象的某个属性中integer ii=i; //自动装箱//integer ii=integer.valueof(i);integer ij= new integer(i);//显示装箱 //拆箱操作,将integer对象中的值取出,放到一个基本数据类型中int j=ii.intvalue();//显示的拆箱int jj=ii;//隐式的拆箱
以上就是java 泛型与包装类示例分析的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product