关于javajava 泛型数组的小问题

没有更多推荐了,
不良信息举报
举报内容:
关于Java泛型的面试题
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!1、何为泛型
首先泛型的本质便是类型参数化,通俗的说就是用一个变量来表示类型,这个类型可以是String,Integer等等不确定,表明可接受的类型,原理类似如下代码
int //声明一个变量未赋值,pattern可以看作是泛型
pattern = 4;
pattern = 5;//4和5就可以看作是String和Integer
泛型的具体形式见泛型类、泛型方法
  *泛型类形式如下
class Test&T&
public void setT(T t)
  *泛型方法举例代码如下
public &T& void show()
operation about T...
泛型参数类型声明必须在返回类型之前
2、为何要引入泛型,即泛型与Object的优势
由于泛型可以接受多个参数,而Object经过强制类型转换可以转换为任何类型,既然二者都具有相同的作用,为何还要引进泛型呢?
解答:泛型可以把使用Object的错误提前到编译后,而不是运行后,提升安全性。以下用带泛型的ArrayList和不带泛型的Arraylist举例说明
ArrayList al = new ArrayList();
al.add("hello");
al.add(4);//自动装箱
String s1 = (String)al.get(0);
String s2 = (String)al.get(1);//在编译时没问题,但在运行时出现问题
首先声明无泛型的ArrayList时,其默认的原始类型是Object数组,既然为Object类型,就可以接受任意数据的赋值,因此编译时没有问题,但是在运行时,Integer强转成String,肯定会出现ClassCastException.因此泛型的引入增强了安全性,把类转换异常提前到了编译时期。
3、类型擦除和原始类型
  *类型擦除的由来
在JAVA的虚拟机中并不存在泛型,泛型只是为了完善java体系,增加程序员编程的便捷性以及安全性而创建的一种机制,在JAVA虚拟机中对应泛型的都是确定的类型,在编写泛型代码后,java虚拟中会把这些泛型参数类型都擦除,用相应的确定类型来代替,代替的这一动作叫做类型擦除,而用于替代的类型称为原始类型,在类型擦除过程中,一般使用第一个限定的类型来替换,若无限定则使用Object.
  *对泛型类的翻译
泛型类(不带泛型限定)代码:
class Test&T&
public void show(T t)
虚拟机进行翻译后的原始类型:
class Test
public void show(Object t)
泛型类(带泛型限定)代码: 
class Test&? extends Comparable&
public void show(T t)
虚拟机进行翻译后的原始类型:
class Test
public void show(Comparable t)
 *泛型方法的翻译
class Test&T&
public void show(T t)
class TestDemo extends Test&String&
public void show(String t)
由于TestDemo继承Test&String&,但是Test在类型擦除后还有一个public void Show(Object t),这和那个show(String t)出现重载,但是本意却是没有show(Object t)的,
因此在虚拟机翻译泛型方法中,引入了桥方法,及在类型擦除后的show(Object t)中调用另一个方法,代码如下:
public void show(Object t)
show((String) t);
4、泛型限定
  *泛型限定是通过?(通配符)来实现的,表示可以接受任意类型,那一定有人有疑问,那?和T(二者单独使用时)有啥区别了,其实区别也不是很大,仅仅在对参数类型的使用上。
public void print(ArrayList&?& al)
Iterator&?& it = al.iterator();
while(it.hasNext())
System.out.println(in.next());
}public &T& void print(ArrayList&T& al)
Iterator&T& it = al.iterator();
while(it.hasNext())
T t = it.next();
//区别就在此处,T可以作为类型来使用,而?仅能作为接收任意类型
System.out.println(t);
  *?&extends SomeClass &这种限定,说明的是只能接收SomeClass及其子类类型,所谓的&上限&
  *? super SomeClass 这种限定,说明只能接收SomeClass及其父类类型,所谓的&下限&
一下举例?&extends SomeClass说明一下这类限定的一种应用方式
由于泛型参数类型可以表示任意类型的类类型,若T要引用compareTo方法,如何保证在T类中定义了compareTo方法呢?利用如下代码:
public &T extends Comparable& shwo(T a, T b)
int num = a.compareTo(b);
此处用于限定T类型继承自Comparable,因为T类型可以调用compareTo方法。
  *可以有多个类型限定,例如:
&T extends Comparable & Serializable&
这种书写方式为何把comparable写在前边?因为由于类型擦除的问题,原始类型是由Comparable替换的,因此写在前边的是类中存在此类型的泛型方法放在前边,避免调用方法时类型的强制转换,提高效率。
class Test&T extends Comparable & Serializable&
public Test(T first, T second) //此处是利用Comparable的方法,因此把Comparable写在前边,类型擦除后为Comparable,若为Serializable,还得用强制类型转换,否则不能使用compareTo方法。
int a = first.compareTo(second);
  *关于泛型类型限定的&继承&误区
总有些人误把类型的限定当作继承,比如:
//类型是这样的
&Student extends Person&
//然后出现此类错误
ArrayList&Person& al = new ArrayList&Student&();
此处的&Person&, &Student&作为泛型的意思是ArrayList容器的接收类型,用一个简单的例子来说明
ArrayList是一个大型养殖场,&Person&表明的是他能够接收动物,而上边的new语句生成的是一个只能够接收猪的养殖场(ArrayList&Student&),即把一个大型养殖场建造成了一个养猪场,若是继承的大型养殖场肯定是还能接受狗、羊....的,但是现在建造成了养猪场,那还能接受别的动物么?所以这肯定是错误的用法!简而言之,泛型new时两边的类型参数必须一致。
5、泛型的一些基本规则约束
  *泛型的类型参数必须为类的引用,不能用基本类型(int, short, long, byte, float, double, char, boolean)
  *泛型是类型的参数化,在使用时可以用作不同类型(此处在说泛型类时会详细说明)
  *泛型的类型参数可以有多个,代码举例如下:
public &T, E& void show()
coding operation.....
  *泛型可以使用extends, super, ?(通配符)来对类型参数进行限定
  *由于类型擦除,运行时类型查询只适用于原始类型,比如instanceof、getClass()、强制类型转换,a instanceof (Pair&Employe&),在类型擦除后便是 a instanceof Pair,因此以上运行的一些操作在虚拟机中操作都是对原始类型进行操作,无论写的多么虚幻,都逃不出类型擦除,因为在虚拟机种并不存在泛型。
  *不能创建参数化类型的数组
例如写如下代码:
Pair&String&[] table = new Pair&String&[10]; //ERROR
//让Object[] t指向table
Object[] t =
//向t中添加对象
t[0] = new Pair&Employe&();
//关键错误之处
String s = table[0];
由于Object可以接收任何类型,在里边存入 new Pari&Employe&时,没有任何问题,但是当取出的时候会出现ClassCastException,因此不能创建参数化类型数组。
  *不能实例化类型变量,及不能出现以下的类似代码
T t = new T();
因为在类型擦除后,便是Object t = new Object();与用意不符合,即本意肯定不是要调用Object.
  *不能再静态域或方法中出现参数类型
例如如下错误代码
class Test&T&
private static T
public static void showExample() //error
action about T...
public static T showExample() //error
action about T....
首先方法是一个返回类型为T的普通方法,而非泛型方法,这和在静态方法中使用非静态参数是一样的,静态方法是先于对象而存在内存中的,因此在编译的时候,T的类型无法确定,一定会出现&Cannot&make&a&static&reference&to&a&non_static&reference&这样类似的错误。
但是这样的代码就是正确的
class Test&T&
{public static &T& T show()
因为此处的静态方法是泛型方法,可以使用.
  *不能抛出或捕获泛型类的实例
    +不能抛出不能捕获泛型类对象
    +泛型类不能扩展Throwable,注意是类不能继承Throwable,类型参数的限定还是可以的。
    +catch子句不能使用类型变量,如下代码
catch(T e) //error
  *类型擦除后的冲突注意
class Pair&T&
public boolean equals(T value) //error
此处的错误的原因不能存在同一个方法,在类型擦除后,Pair的方法为,public boolean equals(Object value),这与从Object.class中继承下来的equals(Object obj)冲突。
  *一个类不能成为两个接口类型的子类,而这两个接口是同一接口的不同参数化。
class Calendar implements coparable&Calendar&{}
class GregorianCalendar extends Calendar implements Comparable&GregorianCalendar&{} //error
当类型擦除后,Calendar实现的是Comparable,而GregorianCalendar继承了Calendar,又去实现Comparable,必然出错!
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&先总结到此处。
阅读(...) 评论()
友情链接:没有更多推荐了,
不良信息举报
举报内容:
遇到个小问题,Java泛型真的是鸡肋吗?
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!Java泛型编程最全总结
我的图书馆
Java泛型编程最全总结
1介绍Java泛型编程是JDK1.5版本后引入的。泛型让编程人员能够使用类型抽象,通常用于集合里面。下面是一个不用泛型例子:&Java代码&&List&myIntList=new&LinkedList();&&&myIntList.add(newInteger(0));&&&Integer&x=(Integer)myIntList.iterator().next();&&&&注意第3行代码,但这是让人很不爽的一点,因为程序员肯定知道自己存储在List里面的对象类型是Integer,但是在返回列表中元素时,还是必须强制转换类型,这是为什么呢?原因在于,编译器只能保证迭代器的next()方法返回的是Object类型的对象,为保证Integer变量的类型安全,所以必须强制转换。这种转换不仅显得混乱,更可能导致类型转换异常ClassCastException,运行时异常往往让人难以检测到。保证列表中的元素为一个特定的数据类型,这样就可以取消类型转换,减少发生错误的机会,&这也是泛型设计的初衷。下面是一个使用了泛型的例子:&Java代码&&List&Integer&&myIntList=newLinkedList&Integer&();&&&myIntList.add(newInteger(0));&&&Integerx=myIntList.iterator().next();&&&&&&&&&&&在第1行代码中指定List中存储的对象类型为Integer,这样在获取列表中的对象时,不必强制转换类型了。&2定义简单的泛型下面是一个引用自java.util包中的接口List和Iterator的定义,其中用到了泛型技术。&Java代码&&public&interface&List&E&&{&&&span&style="white-space:&"&&&&&&/span&void&add(E&x);&&&span&style="white-space:&"&&&&&&/span&Iterator&E&&iterator();&&}&&public&interface&Iterator&E&&{&&&span&style="white-space:&"&&&&&&/span&E&next();&&&span&style="white-space:&"&&&&&&/span&boolean&hasNext();&&}&&&&&&&&&&这跟原生类型没有什么区别,只是在接口后面加入了一个尖括号,尖括号里面是一个类型参数(定义时就是一个格式化的类型参数,在调用时会使用一个具体的类型来替换该类型)。&&&&&&&也许可以这样认为,List&Integer&表示List中的类型参数E会被替换成Integer。&Java代码&&public&interface&IntegerList&{&&&span&style="white-space:&"&&&&&&/span&void&add(Integer&x)&&&span&style="white-space:&"&&&&&&/span&Iterator&Integer&&iterator();&&}&&&&&&&&&&类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上,因此泛型类型中的静态变量是所有实例共享的。此外,需要注意的是,一个static方法,无法访问泛型类的类型参数,因为类还没有实例化,所以,若static方法需要使用泛型能力,必须使其成为泛型方法。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法。在使用泛型时,任何具体的类型都被擦除,唯一知道的是你在使用一个对象。比如:List&String&和List&Integer&在运行事实上是相同的类型。他们都被擦除成他们的原生类型,即List。因为编译的时候会有类型擦除,所以不能通过同一个泛型类的实例来区分方法,如下面的例子编译时会出错,因为类型擦除后,两个方法都是List类型的参数,因此并不能根据泛型类的类型来区分方法。&Java代码&&&&&&public&class&Erasure{&&&&&&&&&&&&&&public&void&test(List&String&&ls){&&&&&&&&&&&&&&&&&&System.out.println("Sting");&&&&&&&&&&&&&&}&&&&&&&&&&&&&&public&void&test(List&Integer&&li){&&&&&&&&&&&&&&&&&&System.out.println("Integer");&&&&&&&&&&&&&&}&&&&}&&&&&&&&&&那么这就有个问题了,既然在编译的时候会在方法和类中擦除实际类型的信息,那么在返回对象时又是如何知道其具体类型的呢?如List&String&编译后会擦除掉String信息,那么在运行时通过迭代器返回List中的对象时,又是如何知道List中存储的是String类型对象呢?&&&&&&&擦除在方法体中移除了类型信息,所以在运行时的问题就是边界:即对象进入和离开方法的地点,这正是编译器在编译期执行类型检查并插入转型代码的地点。泛型中的所有动作都发生在边界处:对传递进来的值进行额外的编译期检查,并插入对传递出去的值的转型。&3.泛型和子类型为了彻底理解泛型,这里看个例子:(Apple为Fruit的子类)&Java代码&&List&Apple&&apples&=&new&ArrayList&Apple&();&&&List&Fruit&&fruits&=&&&&&第1行代码显然是对的,但是第2行是否对呢?我们知道Fruit fruit = new Apple(),这样肯定是对的,即苹果肯定是水果,但是第2行在编译的时候会出错。这会让人比较纳闷的是一个苹果是水果,为什么一箱苹果就不是一箱水果了呢?可以这样考虑,我们假定第2行代码没有问题,那么我们可以使用语句fruits.add(new Strawberry())(Strawberry为Fruit的子类)在fruits中加入草莓了,但是这样的话,一个List中装入了各种不同类型的子类水果,这显然是不可以的,因为我们在取出List中的水果对象时,就分不清楚到底该转型为苹果还是草莓了。通常来说,如果Foo是Bar的子类型,G是一种带泛型的类型,则G&Foo&不是G&Bar&的子类型。这也许是泛型学习里面最让人容易混淆的一点。&4.通配符4.1通配符?先看一个打印集合中所有元素的代码。&Java代码&&&&void&printCollection(Collection&c)&{&&&&&&&&&&&&&&&&&&&span&style="white-space:&"&&&&&&/span&Iterator&i=c.iterator();&&&span&style="white-space:&"&&&&&&/span&for&(k=0;k&&&c.size();k++)&{&&&span&style="white-space:&"&&&&&&&&&&/span&System.out.println(i.next());&&&span&style="white-space:&"&&&&&&/span&}&&}&&&&Java代码&&&&void&printCollection(Collection&Object&&c)&{&&for&(Object&e:c)&{&&System.out.println(e);&&}&&}&&&&&&&&很容易发现,使用泛型的版本只能接受元素类型为Object类型的集合如ArrayList&Object&();如果是ArrayList&String&,则会编译时出错。因为我们前面说过,Collection&Object&并不是所有集合的超类。而老版本可以打印任何类型的集合,那么如何改造新版本以便它能接受所有类型的集合呢?这个问题可以通过使用通配符来解决。修改后的代码如下所示:&Java代码&&&&void&printCollection(Collection&?&&c)&{&&&span&style="white-space:&"&&&&&&/span&for&(Object&e:c)&{&&&span&style="white-space:&"&&&&&&&&&&/span&System.out.println(e);&&&span&style="white-space:&"&&&&&&/span&}&&}&&&这里使用了通配符?指定可以使用任何类型的集合作为参数。读取的元素使用了Object类型来表示,这是安全的,因为所有的类都是Object的子类。这里就又出现了另外一个问题,如下代码所示,如果试图往使用通配符?的集合中加入对象,就会在编译时出现错误。需要注意的是,这里不管加入什么类型的对象都会出错。这是因为通配符?表示该集合存储的元素类型未知,可以是任何类型。往集合中加入元素需要是一个未知元素类型的子类型,正因为该集合存储的元素类型未知,所以我们没法向该集合中添加任何元素。唯一的例外是null,因为null是所有类型的子类型,所以尽管元素类型不知道,但是null一定是它的子类型。&Java代码&&Collection&?&&c=new&ArrayList&String&();&&c.add(newObject());&&&c.add(null);&&&&另一方面,我们可以从List&?& lists中获取对象,虽然不知道List中存储的是什么类型,但是可以肯定的是存储的类型一定是Object的子类型,所以可以用Object类型来获取值。如for(Object obj: lists),这是合法的。4.2边界通配符&& 1)?extends通配符假定有一个画图的应用,可以画各种形状的图形,如矩形和圆形等。为了在程序里面表示,定义如下的类层次:&Java代码&&public&abstract&class&Shape&{&&&span&style="white-space:&"&&&&&&/span&public&abstract&void&draw(Canvas&c);&&}&&&&public&class&Circle&extends&Shape&{&&&span&style="white-space:&"&&&&&&/span&private&int&x,y,&&&span&style="white-space:&"&&&&&&/span&public&void&draw(Canvas&c)&{&...&}&&}&&&&public&class&Rectangle&extends&Shape&&&span&style="white-space:&"&&&&&&/span&private&int&x,y,width,&&&span&style="white-space:&"&&&&&&/span&public&void&draw(Canvasc)&{&...&}&&}&&&为了画出集合中所有的形状,我们可以定义一个函数,该函数接受带有泛型的集合类对象作为参数。但是不幸的是,我们只能接收元素类型为Shape的List对象,而不能接收类型为List&Cycle&的对象,这在前面已经说过。为了解决这个问题,所以有了边界通配符的概念。这里可以采用public void drawAll(List&? extends Shape&shapes)来满足条件,这样就可以接收元素类型为Shape子类型的列表作为参数了。&Java代码&&&&public&void&drawAll(List&Shape&&shapes)&{&&&span&style="white-space:&"&&&&&&/span&for&(Shapes:shapes)&{&&&span&style="white-space:&"&&&&&&&&&&/span&s.draw(this);&&&span&style="white-space:&"&&&&&&/span&}&&}&&&&Java代码&&&&public&void&drawAll(List&?exends&Shape&&shapes)&{&&&span&style="white-space:&"&&&&&&/span&for&(Shapes:shapes)&{&&&span&style="white-space:&"&&&&&&&&&&/span&s.draw(this);&&&span&style="white-space:&"&&&&&&/span&}&&}&&&这里就又有个问题要注意了,如果我们希望在List&?exends Shape& shapes中加入一个矩形对象,如下所示:shapes.add(0, new Rectangle()); //compile-time error那么这时会出现一个编译时错误,原因在于:我们只知道shapes中的元素时Shape类型的子类型,具体是什么子类型我们并不清楚,所以我们不能往shapes中加入任何类型的对象。不过我们在取出其中对象时,可以使用Shape类型来取值,因为虽然我们不知道列表中的元素类型具体是什么类型,但是我们肯定的是它一定是Shape类的子类型。&2)?super通配符&&&&&&&这里还有一种边界通配符为?super。比如下面的代码:&Java代码&&List&Shape&&shapes&=&new&ArrayList&Shape&();&&List&?&super&Cicle&&cicleSupers&=&&&cicleSupers.add(new&Cicle());&&&cicleSupers.add(new&Shape());&&&&&&&&&&&这表示cicleSupers列表存储的元素为Cicle的超类,因此我们可以往其中加入Cicle对象或者Cicle的子类对象,但是不能加入Shape对象。这里的原因在于列表cicleSupers存储的元素类型为Cicle的超类,但是具体是Cicle的什么超类并不清楚。但是我们可以确定的是只要是Cicle或者Circle的子类,则一定是与该元素类别兼容。&3)边界通配符总结&!--[if !supportLists]--&l&!--[endif]--&如果你想从一个数据类型里获取数据,使用&? extends&通配符&!--[if !supportLists]--&l&!--[endif]--&如果你想把对象写入一个数据结构里,使用&? super&通配符&!--[if !supportLists]--&l&!--[endif]--&如果你既想存,又想取,那就别用通配符。&5.泛型方法考虑实现一个方法,该方法拷贝一个数组中的所有对象到集合中。下面是初始的版本:&Java代码&&static&void&fromArrayToCollection(Object[]a,&Collection&?&&c)&{&&&span&style="white-space:&"&&&&&&/span&for&(Object&o:a)&{&&&span&style="white-space:&"&&&&&&&&&&/span&c.add(o);&&&&span&style="white-space:&"&&&&&&/span&}&&}&&&可以看到显然会出现编译错误,原因在之前有讲过,因为集合c中的类型未知,所以不能往其中加入任何的对象(当然,null除外)。解决该问题的一种比较好的办法是使用泛型方法,如下所示:&Java代码&&static&&T&&void&fromArrayToCollection(T[]&a,&Collection&T&c){&&&span&style="white-space:&"&&&&&&/span&for(T&o&:&a)&{&&&span&style="white-space:&"&&&&&&&&&&/span&c.add(o);&&&span&style="white-space:&"&&&&&&/span&}&&}&&&注意泛型方法的格式,类型参数&T&需要放在函数返回值之前。然后在参数和返回值中就可以使用泛型参数了。具体一些调用方法的实例如下:&Java代码&&Object[]&oa&=&new&Object[100];&&Collection&Object&co&=&new&ArrayList&Object&();&&fromArrayToCollection(oa,&co);&&String[]&sa&=&new&String[100];&&Collection&String&cs&=&new&ArrayList&String&();&&fromArrayToCollection(sa,&cs);&&fromArrayToCollection(sa,&co);&&Integer[]&ia&=&new&Integer[100];&&Float[]&fa&=&new&Float[100];&&Number[]&na&=&new&Number[100];&&Collection&Number&cn&=&new&ArrayList&Number&();&&fromArrayToCollection(ia,&cn);&&fromArrayToCollection(fa,&cn);&&fromArrayToCollection(na,&cn);&&fromArrayToCollection(na,&co);&&fromArrayToCollection(na,&cs);&&&注意到我们调用方法时并不需要传递类型参数,系统会自动判断类型参数并调用合适的方法。当然在某些情况下需要指定传递类型参数,比如当存在与泛型方法相同的方法的时候(方法参数类型不一致),如下面的一个例子:&Java代码&&public&&&T&&void&go(T&t)&{&&&&&&System.out.println("generic&function");&&}&&public&void&go(String&str)&{&&&&&&System.out.println("normal&function");&&}&&public&static&void&main(String[]&args)&{&&&&&&&&&&FuncGenric&fg&=&new&FuncGenric();&&&&&&&&&&fg.go("haha");&&&&&&&&&&fg.&String&go("haha");&&&&&&&&&&fg.go(new&Object());&&&&&&&&&&fg.&Object&go(new&Object());&&}&&&如例子中所示,当不指定类型参数时,调用的是普通的方法,如果指定了类型参数,则调用泛型方法。可以这样理解,因为泛型方法编译后类型擦除,如果不指定类型参数,则泛型方法此时相当于是public void go(Object t)。而普通的方法接收参数为String类型,因此以String类型的实参调用函数,肯定会调用形参为String的普通方法了。如果是以Object类型的实参调用函数,则会调用泛型方法。6.其他需要注意的小点1)方法重载在JAVA里面方法重载是不能通过返回值类型来区分的,比如代码一中一个类中定义两个如下的方法是不容许的。但是当参数为泛型类型时,却是可以的。如下面代码二中所示,虽然形参经过类型擦除后都为List类型,但是返回类型不同,这是可以的。&Java代码&&&&&public&class&Erasure{&&&&&&&&&&&&&&public&void&test(int&i){&&&&&&&&&&&&&&&&&&System.out.println("Sting");&&&&&&&&&&&&&&}&&&&&&&&&&&&&&public&int&test(int&i){&&&&&&&&&&&&&&&&&&System.out.println("Integer");&&&&&&&&&&&&&&}&&&&}&&&&Java代码&&&&&public&class&Erasure{&&&&&&&&&&&&&&public&void&test(List&String&&ls){&&&&&&&&&&&&&&&&&&System.out.println("Sting");&&&&&&&&&&&&&&}&&&&&&&&&&&&&&public&int&test(List&Integer&&li){&&&&&&&&&&&&&&&&&&System.out.println("Integer");&&&&&&&&&&&&&&}&&&&}&&&&2)泛型类型是被所有调用共享的&&&&&&&所有泛型类的实例都共享同一个运行时类,类型参数信息会在编译时被擦除。因此考虑如下代码,虽然ArrayList&String&和ArrayList&Integer&类型参数不同,但是他们都共享ArrayList类,所以结果会是true。&&&&&&&Java代码&&List&String&l1&=&new&ArrayList&String&();&&List&Integer&l2&=&new&ArrayList&Integer&();&&System.out.println(l1.getClass()&==&l2.getClass());&&&&&3)instanceof不能对确切的泛型类型使用instanceOf操作。如下面的操作是非法的,编译时会出错。&Java代码&&Collection&cs&=&new&ArrayList&String&();&&if&(cs&instanceof&Collection&String&){…}&&&&4)泛型数组问题不能创建一个确切泛型类型的数组。如下面代码会出错。List&String&[] lsa = new ArrayList&String&[10];&//compile error.&&&&&&&因为如果可以这样,那么考虑如下代码,会导致运行时错误。&Java代码&&List&String&[]&lsa&=&new&ArrayList&String&[10];&&&Object&o&=&&&Object[]&oa&=&(Object[])&o;&&List&Integer&li&=&new&ArrayList&Integer&();&&li.add(new&Integer(3));&&oa[1]&=&&&String&s&=&lsa[1].get(0);&&&&&&&&&&&因此只能创建带通配符的泛型数组,如下面例子所示,这回可以通过编译,但是在倒数第二行代码中必须显式的转型才行,即便如此,最后还是会抛出类型转换异常,因为存储在lsa中的是List&Integer&类型的对象,而不是List&String&类型。最后一行代码是正确的,类型匹配,不会抛出异常。Java代码&&List&?&[]&lsa&=&new&List&?&[10];&&&Object&o&=&&&Object[]&oa&=&(Object[])&o;&&List&Integer&li&=&new&ArrayList&Integer&();&&li.add(new&Integer(3));&&oa[1]&=&&&&String&s&=&(String)&lsa[1].get(0);&&Integer&it&=&(Integer)lsa[1].get(0);&&&
TA的最新馆藏[转]&[转]&[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢}

我要回帖

更多关于 java 泛型方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信