深入学习Java泛型.pptx
《深入学习Java泛型.pptx》由会员分享,可在线阅读,更多相关《深入学习Java泛型.pptx(67页珍藏版)》请在咨信网上搜索。
泛型泛型泛型入门深入泛型类型通配符泛型方法擦除与转换泛型与数组本章小结本章要点:本章要点:本章的知识是Java集合的补充阅读,因为JDK1.5增加泛型支持在很大程度上都是为了让集合能记住其元素的数据类型。在没有泛型之前,一旦把一个对象“丢进”Java集合中,集合就会忘记对象的类型,把所有的对象当做Object类型处理。当程序从集合中取走对象后,就需要进行强制类型转换,这种强制类型转换不仅是代码臃肿,而且容易引起ClassCastException一场。增加泛型支持后的集合,完全可以记住集合中的元素的类型,并可以在编译时检查集合中元素的类型,如果试图向集合中添加不满足类型要求的对象,编译器就会提示错误。增加泛型后的集合,可以让代码更加简洁,程序更加健壮(Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常)。Java集合有一个缺点-把一个对象“丢进”集合里之后,集合就会忘记这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型。(其运行时类型没变)。Java集合之所以被设计成这样,是因为集合的设计者不知道我们会用集合来保存什么类型的对象,所以他们把集合设计成能保存任何类型的对象,只要求具有很好的通用性。但这样做带来如下两个问题:集合对元素类型没有任何限制,这样可以引发一些问题。由于把对象“丢进”集合时,集合丢失了对象的状态信息,集合只知道它盛装的是Object,因此取出集合元素后通常还需要进行强制类型转换。这种强制类型转换即增加了编程的复杂度,也可能引发ClassCastException异常。第一节第一节 泛型入门泛型入门第一节第一节 泛型入门泛型入门第一节第一节 泛型入门泛型入门第一节第一节 泛型入门泛型入门 没有泛型的时候我们需要一个箱子,可以放入一个对象,也可以取出对象。public class Box private Object object;public Object getObject()return object;public void setObject(Object object)this.object=object;在使用中,每次取出的东西都必须强制类型转换,不但麻烦,而且容易出现类型转换异常。Box box1=new Box();box1.setObject(hello);String s=(String)box1.getObject();Box box2=new Box();box2.setObject(Integer.valueOf(123);/中间经过一些处理中间经过一些处理/取出时必须强制类型转换取出时必须强制类型转换Integer itg=(Integer)box2.getObject();/编译器无法判断这是个错误的类型转换编译器无法判断这是个错误的类型转换String errorStr=(String)box2.getObject();Exception in thread main java.lang.ClassCastException:java.lang.Integer cannot be cast to java.lang.Stringat Box.main(Box.java:22)Java5.0中引入了泛型,在实例化箱子的时候可以“贴上标签”,规定箱子必须放入对象的类型、取出的对象类型,这样就无需强制类型转换了。Box box1=new Box();box1.setObject(hello);Box box2=new Box();box2.setObject(Integer.valueOf(123);/中间经过一些处理中间经过一些处理/取出时必须强制类型转换取出时必须强制类型转换Integer itg=(Integer)box2.getObject();/编译器无法判断这是个错误的类型转换编译器无法判断这是个错误的类型转换String errorStr=(String)box2.getObject();public class Boxprivate T t;public T getObject()return t;public void setObject(T t)this.t=t;1.1.编译时不检查类型的异常编译时不检查类型的异常在输出在输出5的长度时,程序试图将的长度时,程序试图将Integer对象转换为对象转换为String类类型引发型引发ClassCastException异常。异常。从Java5之后,Java引入了“参数化类型”的概念,允许程序在创建集合时指定集合元素的类型。Java的参数化类型被称为泛型(Generic)。2.2.使用泛型使用泛型上面程序成功创建了一个特殊的List集合:strList,这个List集合只能保存字符串对象,不能保存其他类型的对象。创建这种特殊集合的方法是:在集合接口、类后增加尖括号,尖括号里放一个数据类型,即表明这个集合接口、集合类只能保存特定类型的对象。注意List后面的类型声明,它指定strList不是一个任意的List,而是一个String类型的list,写作:List。可以称List是带一个类型参数的泛型接口,在本例中,类型参数是String。在创建这个ArrayList对象时也指定了一个类型参数。程序在取出集合元素时不需要进行强制类型转换,因为该对象已经记住了它是什么类型的集合。在Java 7 以前,如果使用带泛型的接口、类定义变量,那么调用构造器创建对象时构造器的后面也必须带泛型,这显得有些多余了。例如:上面两条语句中后面尖括号的类型声明完全多余,在Java7之前是必须的,不能省略。从Java7开始,Java允许在构造器后不要带完整的泛型信息,只要给出一对尖括号即可,Java可以推断尖括号里应该是什么泛型信息。即上面可以改写为:3.Java 7 3.Java 7 泛型的泛型的“菱形菱形”语法语法实例实例使用菱形语法,对泛型并不会改变,只是更好的使用菱形语法,对泛型并不会改变,只是更好的简化了泛型编程。简化了泛型编程。所谓泛型,就是允许在定义类、接口、方法时使用类型形参,这个类型形参将在声明变量、创建对象、调用方法时动态地指定(即传入实际的类型参数,也可称为类型实参)。Java 5 改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持,从而可以在声明集合变量、创建集合对象时传入类型实参,这就是在前面程序中看到的List和ArrayList两种类型。第二第二节节 深入泛型深入泛型泛型的实质:允许在定义接口、类时声明类型形参,类型形参在整个接口、类体内可当成类型使用,几乎所有可使用普通类型的地方都可以使用这种类型形参。虽然程序只定义了一个List接口,但实际上使用时可以产生无数多个List接口,只要为E传入不同的类型实参,系统就会多出一个新的List子接口。必须指出:LIst绝对不会被替换成ListString,系统没有尽心源代码赋值,二进制代码中没有,磁盘中没有,内存中也没有。包含泛型声明的类型可以在定义变量、创建对象时传入一个类型实参,从而可以动态地生成无数多个逻辑上的子类,但这种子类在物理上并不存在。1.1.定义泛型接口、类定义泛型接口、类可以为任何类、接口增加泛型声明(并不是只有集合类才可以使用泛型声明,虽然集合类是泛型的重要使用场所)。下面自定义一个类,此类包含泛型声明。实例实例上面程序定义了一个带泛型声明的Apple类(不要理会这个类型形参是否有实际意义),使用Apple类时就可以为T类型形参传入实际类型,这样就可以生成如Apple、Apple.形式的多个逻辑子类(物理上并不存在)。这就是第一节中List、ArrayList等类型的原因-JDK在定义List、ArrayList等接口、类时使用了类型形参,所以在使用这些类时为之传入了实际的类型参数。注意:当创建带泛型声明的自定义类,为该类定义构造器时,构造器名还是原来的类名,不要增加泛型声明。例如,为Apple类定义构造器,其构造器名依然是Apple,而不是Apple!调用该构造器时却可以使用Apple的形式,当然应该为T形参传入实际的类型参数。Java7提供了菱形语法,允许省略中的类型实参。当创建了带泛型声明的接口、父类之后,可以为该接口创建实现类,或者从该父类派生子类,需要指出的是,当使用这些接口、父类时不能再包含类型形参。例如,下面代码是错误的。方法中的形参代表变量、常量、表达式等数据,本书把它们直接成为形参,或者称为数据形参。定义方法时可以声明数据形参,调用方法(使用方法)时必须为这些数据形参传入实际的数据;如果想从Apple类派生一个子类,则可以改为如下代码:2.2.从泛型类派生子类从泛型类派生子类调用方法时必须为所有的数据形参传入参数值,与调用方法不同的是,使用类、接口时也可以不为类型形参参入实际的类型参数。如果从Apple类派生子类,则在Apple类中所有使用T类型形参的地方都将被替换成String类型,即它的子类将会继承到String getInfo()和void setInfo(String info)两个方法,如果子类需要重写父类的方法,就必须注意这一点。实例实例如果使用了Apple类是没有传入实际的类型参数,Java编译器可能发出警告:使用了未经检查或不安全的操作-这就是泛型检查的警告。如果希望看到该警告的更详细信息,则可以通过为Javac命令增加-Xlink:unchecked选项类实现。此时,系统会把Apple类里的T形参当成Object类型处理。上面程序都是从带泛型声明的父类来派生子类,创建带泛型声明的接口的实现类与此几乎完全一样,此处不要赘述。前面提到可以把ArrayList类当成ArrayList的子类,事实上,ArrayList类也确实像一种特殊的ArrayList类:该ArrayList对象只能添加String对象作为集合元素。旦实际上,系统并没有为ArrayList生成新的Class文件,而且也不会把ArrayList当成新类来处理。3.3.并不存在泛型类并不存在泛型类看下面代码打印结果:因为不管泛型的实际参数是什么,它们在运行时总有同样的类(class)。不管为泛型的类型形参传入哪一种类型实参,对于Java来说,它们依然被当成同一个类处理,在内存中也只占同一块内存空间,因此在静态方法、静态初始化或者静态变量的声明和初始化中不允许使用类型形参。实例实例由于系统中并不会真正生成泛型类,所以instanceof运算符后不能使用泛型类。例如,下面的代码是错误的。正如前面所讲的,当使用一个泛型类时(包括声明变量和创建对象两种情况),都应该为这个泛型类传入一个类型实参。如果没有传入类型实际参数,编译器就会提出泛型警告。假设现在需要定义一个方法,该方法里有一个集合形参,集合形参的元素类型是不确定的,那应该怎样定义呢?考虑以下代码:上面程序当然没有问题:这是一段最普通的遍历List集合的代码。问题是上面程序中List是一个有泛型声明的接口,此处使用List接口时没有传入实际类型参数,这强引起泛型警告。第三节第三节 类型通配符类型通配符为此,考虑为List接口传入实际的类型参数-因为List集合里的元素类型是不确定的,将上面方法改为如下形式:表面上看来,上面方法声明没有问题,这个方法声明确实没有任何问题。问题是调用该方法传入的实际参数值是可能不是我们所期望的,当试图调用该方法是,可能会出现编译错误。如果Foo是Bar的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G并不是G的子类型!这一点非常值得注意,因为它与大部分人的习惯认为是不同的。注意注意与数组进行比较,先看一下数组是如何工作的。在数组中,程序可以直接把一个Integer数组赋给一个Number变量。如果试图把一个Double对象保存到Number数组中,编译可以通过,但在运行时抛出ArrayStoreException异常。这是一种潜在的风险。一门设计优秀的语言,不仅需要提供强大的功能,而且能够提供强大的“错误提示”和“错误警告”,这样才能尽量避免开发者犯错。而Java允许Integer数组赋值给Number显然不是一种安全的设计。在Java的早期设计中,允许Integer数组赋值给Number变量存在缺陷,因此Java在泛型设计时进行了改进,它不在允许把List 对象赋值给List变量。例如,如下代码将会编译出错。Java泛型的设计原则是,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException异常。数组和泛型有所不同,假设Foo是Bar的一个子类型(子类或者子接口),那么Foo依然是Bar的子类型;但G不是G的子类型。注意注意为了表示各种泛型List的子类,可以使用类型通配符,类型通配符是一个问号(?),将一个问号作为类型实参传给List集合,写作:List(意思是元素类型未知的List)。这个问号(?)被称为通配符,它的元素类型可以匹配任何类型。可以将上面方法改写为如下形式:现在使用任何类型的List来调用它,程序依然可以访问集合c中的元素,其类型是Object,这永远是不安全的,因为不管List的真实类型是什么,它包含的都是Object。上面程序中使用的List,其实这种写法可以适应于任何支持泛型声明的接口和类,比如写成Set、Collection、Map等。1.1.使用类型通配符使用类型通配符但这种带通配符的List仅表示它是各种泛型的List的父类,并不能把元素加入到其中。例如,如下代码会引起编译错误。因为程序无法确定c集合中元素的类型,所以不能像其中添加对象。根据前面的List接口定义的代码可以发现:add()方法有类型参数E作为集合的元素类型,所以传给add的参数必须是E类的对象或者其子类的对象。但因为在该例中不知道E是什么类型,所以程序无法将任何对象“丢进”该集合。唯一的例外是null,它是所有引用类型的实例。另一方面,程序可以调用get()方法来返回List集合指定所引处的元素,其返回值是一个位置类型,但可以肯定的是,它总是一个Object。因此,把get()的返回值赋值给一个Object类型的变量,或者放在任何希望是Object类型的地方都可以。当直接使用List这种形式时,即表明这个List集合可以是任何泛型List的父类。但还有一种特殊的情形,程序不希望这个List是任何泛型List的父类,只希望它代表某一类泛型List的父类。考虑一个简单的绘图程序,下面定义三个形状类。2.2.设定类型通配符的上限设定类型通配符的上限List 并不是List的子类型,所以不能把List 对象当成List使用。为了表示List的父类,可以考虑使用List,把Canvas改为如下形式上面程序使用了通配符来表示所有的类型。上面的drawAll()方法可以接受List对象作为参数,问题是上满的方法实现体显得极为臃肿而繁琐:使用了泛型还需要强制类型转换。实际上需要一种泛型表示方法,它可以表示所以Shape泛型List的父类。为了满足这种需求,Java泛型提供了被限制的泛型通配符。被限制的泛型通配符表示如下。有了这种被限制的泛型通配符,就可以把上面的Canvas程序改为如下形式:将Canvas改为如上形式,就可以把List对象当成List使用。即List可以表示List、List的父类-只要List后尖括号的类型是Shape的子类型即可。List是受限制通配符的例子,此处的问号代表一个位置的类型,就像前面看到的通配符一样。但是在此处的这个未知类型一定是Shape的子类型(也可以是Shape本身),因此可以把Shape称为这个通配符的上限(upper bound)。类似的,由于程序无法确定这个受限的通配符的具体类型,所以不能把Shape对象或其子类的对象加入这个泛型集合中。与普通通配符相似的是,shape.add()的第二个参数类型是?extends Shape,它表示Shape位置的子类,程序无法确定这个类型是什么,所以无法将任何对象添加到这种集合中。Java泛型不仅允许在使用通配符形参时设定上限,而且可以在定义类型形参时设定上限。用于表示传给该类型形参的实际类型要么是该上限类型,要么是该上限类型的子类。上面程序定义了一个Apple泛型类,该Apple类的类形参的上限是Number类,这表明使用Apple类时为T形参传入的实际类型参数只能是Number或Number类的子类。在一种更极端的情况下,程序需要为类型形参设定多个上限(至少有一个父类上限,可以有多个接口上限),表明该类型形参必须是其父类的子类(是父类本身也行),并且实现多个上限接口。如下:3.3.设定类型形参的上限设定类型形参的上限与类同时继承父类,实现接口类似的是,为类型形参指定多个上限时,所有的接口上限必须位于类上限之后。也就是说,如果需要为类型形参指定类上限,类上限必须位于第一位。前面介绍了在定义类、接口时可以使用类型形参,在该类的方法定义和成员变量定义、接口的方法定义中,这些类型形参可被当成普通类型来用。在另一些情况下,定义类、接口时没有使用类型形参,但定义方法时向自己定义类型形参,这也是可以的,Java 5 还提供了对泛型方法的支持。第四节第四节 泛型方法泛型方法假设需要实现这样一个方法-该方法负责将一个Object数组的所有元素添加到一个Collection集合中。考虑如下代码来实现该方法。上面定义的方法没有任何问题,关键在于方法中的c形参,它的数据类型是Collection。正如前面介绍的,Collection不是Collection的子类型-所以这个方法的功能非常有限,它只能将Object数组的元素复制到元素位Object(Ojbect的子类不行)的Collection集合中,即下面的代码将会引起编译错误。可见上面方法的参数类型不可以使用Collection,那使用通配符Collection是否可行呢?显然不可行,因为Java不允许把对象放进一个位置类型的集合中。1.1.定义泛型方法定义泛型方法为了解决这个问题,可以使用Java 5 提供的泛型方法(Generic method)。所谓泛型方法,就是在声明方法时定义一个或多个类型形参。泛型方法的语法格式如下:把上面方法的格式和普通方法的格式进行对比,不难发现泛型方法的方法签名比普通方法的方法签名多了类型形参声明,类型形参声明以尖括号括起来,多个类型形参之间以逗号隔开,所有的类型形参声明放在方法修饰符合方法返回值类型之间。采用支持泛型的方法,就可以把上面的fromArrayToCollection方法改为如下形式:实例实例上面程序定义了一个泛型方法,该泛型方法中定义了一个T类型形参,这个T类型形参就可以在该方法内当成普通类型使用。与接口、类声明中定义的类型形参不同的是,方法声明中定义的形参只能在该方法里使用,而接口、类声明中定义的类型形参则可以在整个接口、类中使用。与类、接口中使用泛型参数不同的是,方法中的泛型参数无需显式传入实际类型参数,如上面程序所示,当程序调用fromArrayToCollection()方法时,无须在该方法前传入String、Object等类型,当系统仍然可以知道类型形参的数据类型,因为编译器根据实参推断类型形参的值,它通常推断出最直接的类型参数。实例实例上面程序中定义了上面程序中定义了test()方法,该方法用于将前一个集合里的元素复制到下一个集方法,该方法用于将前一个集合里的元素复制到下一个集合中,该方法中的两个形参合中,该方法中的两个形参from,to的类型都是的类型都是Collection,这要求调用该方,这要求调用该方法时的两个实参中的泛型类型相同,否则编译器无法准确地推断出泛型方法中类法时的两个实参中的泛型类型相同,否则编译器无法准确地推断出泛型方法中类型形参的类型型形参的类型上面程序中调用了test方法传入了两个实际参数,其中as的数据类型是List,而ao的数据类型是List,与泛型方法签名进行对比:test(Collection a,Collection c),编译器无法正确识别T所代表的实际类型。为了避免这种错误,可以将该方法改为如下形式:上面代码改变了test()方法签名,将该方法的前一个形参类型改为Collection,这种采用类型通配符的表示方式,只要test()方法的前一个Collection集合里的元素类型是后一个Collection集合里元素类型的子类即可。那么,到底何时使用泛型方法?何时使用类型通配符?接下来详细介绍泛型方法和类型通配符的区别。大多时候都可以使用泛型方法类代替类型通配符。例如,对于Java的Collection接口中两个方法定义:上面集合中两个方法的形参都采用了类型通配符的形式,也可以采用泛型方法的形式,如下所示:上面方法使用了泛型形式,这时定义类型形参时设定上限(其中E是Collection接口里定义的类型形参,在该接口里E可当成普通类型使用)。上面两个方法中类型形参T只使用了一次,类型形参T产生的唯一效果是可以在不同的调用点传入不同的实际类型。对于这种情况,应该使用通配符:通配符就是被设计用来支持灵活的子类化的。2.2.泛型方法和类型通配符的区别泛型方法和类型通配符的区别泛型方法允许类型形参被用来表示方法的一个或多个参数之间的类型依赖关系,或者方法返回值与参数之间的类型依赖关系。如果没有这样的类型依赖关系,就不应该使用泛型方法。如果某个方法中一个形参(a)的类型或返回值的类型依赖于另一个形参(b)的类型,则形参(b)的类型声明不应该使用通配符-因为形参(a)或返回值的类型依赖于该形参(b)的类型,如果形参(b)的类型无法确定,程序就无法定义形参(a)的类型,在这种情况下,只能考虑使用在方法签名中声明类型形参-也就是泛型方法。如果有需要,也可以同时使用泛型方法和通配符,如Java的Collections.copy()方法。上面copy方法中的dest和src存在明显的依赖关系,从源List中复制出来的元素,必须可以“丢进”目标List中,所以源List集合元素的类型只能是目标集合元素的类型的子类型或者它本身,但JDK定义src形参类型是使用的是类型通配符,而不是泛型方法。这是因为,该方法无须向src集合中添加元素,也无需修改src集合里的元素,所以可以使用类型通配符,无需使用泛型方法。当然,也可以将上面的方法签名改为使用泛型方法,不使用类型通配符,如下所示:这个方法签名可以代替前面的方法签名。但注意上面的类型形参S,它仅使用了一次,其他参数的类型、方法返回值的类型都不依赖于它,那类型形参S就没有存在的必要,既可以用通配符来代替S。使用通配符比使用泛型方法(在方法签名中显式声明类型形参)更加清晰和准确,因此Java设计该方法时采用了通配符,而不是泛型方法。类型通配符与泛型方法(在方法签名中显式声明类型形参)还有一个显著的区别:类型通配符既可以在方法签名中定义形参的类型,也可以用于定义变量的类型;但泛型方法中的类型形参必须在对应方法中显示声明。正如泛型方法允许在方法签名中声明类型形参一样,Java也允许在构造器签名中声明类型形参,这样就产生了所谓的泛型构造器。一旦定义了泛型构造器,接下来在调用构造器时,就不仅可以让Java根据数据参数的类型来“推断”类型形参的类型,而且程序员也可以显式地为构造器中的类型形参指定实际的类型。3.Java 73.Java 7的菱形语法与泛型构造器的菱形语法与泛型构造器前面介绍过Java7新增的“菱形”语法,它允许调用构造器时在构造器后使用一对尖括号来代表泛型信息。但如果程序显式指定了泛型构造器中声明的类型形参的实际类型,则不可以使用菱形语法。上述代码中既指定了泛型构造器中的类型是上述代码中既指定了泛型构造器中的类型是Integer类型,又想使用菱形语法,所类型,又想使用菱形语法,所以这行代码无法通过编译。以这行代码无法通过编译。假设自己实现一个工具方法:实现将src集合里的元素复制到dest集合里的功能,不管src集合元素的类型是什么,只要dest集合元素的类型与前者相同或是前者的父类即可。为了表达这种约束关系,Java允许设定通配符的下限:,这个通配符表示它必须是Type本身,或是Type的父类。下面程序采用设定通配符下限的方式改写了前面的copy()方法:4.4.设定通配符下限设定通配符下限使用这种语句,就可以保证程序的使用这种语句,就可以保证程序的调用调用后推断出最后一个被复制的元素类型是后推断出最后一个被复制的元素类型是Integer,而不是笼统的,而不是笼统的Number类型。类型。因为泛型既允许设定通配符的上限,也允许设定通配符的下限,从而允许在一个类里包含如下两个方法定义:5.5.泛型方法与方法重载泛型方法与方法重载Java8改进了泛型方法的类型推断能力,类型推断主要有如下两个方面。可通过调用方法的上下文来推断类型参数的目标类型。可在方法调用链中,将推断得到的类型参数传递到最后一个方法。6.Java 86.Java 8改进的类型推断改进的类型推断需要指出的是,虽然Java 8 增强了泛型推断的能力,但泛型推断不是万能的,例如下面的代码就是错误的:在严格的泛型代码里,带泛型声明的类总应该带着类型参数。但为了与老的Java代码保持一致,也允许在使用带泛型声明的类时不指定实际的类型参数。如果没有为这个泛型类指定实际的类型参数,则该类型被称作raw type(原始数据),默认是声明该类型参数时指定的第一个上限类型。当把一个具有泛型信息的对象赋给另一个没有泛型信息的变量时,所有在尖括号之间的类型信息都将被扔掉。比如一个List类型被转换为List,则该List对集合元素的类型检查变成了类型参数的的上限(即Object)。第五节第五节 擦除和转换擦除和转换实例实例从逻辑上来看,List是List的子类,如果直接把一个List对象赋给一个List对象应该引起编译错误,但实际上不会。对泛型而言,可以直接把一个List对象赋给一个List对象,编译器仅仅提示“未经检查的转换”,但访问里面的元素时会引起运行异常。上面程序中定义了一个List对象,这个List对象保留了集合元素的类型信息。当把这个List对象赋给一个List类型的list后,编译器就会丢失前者的泛型信息,即丢失list集合里元素的类型信息,这是典型的擦除。Java又允许直接把List对象赋给一个List类型的变量,所以程序可以通过编译,只是发出未经检查的转换警告。但对List变量实际上引用的是List集合,所以当试图把该集合里的元素当成String类型的对象取出时,将引发运行时异常。Java泛型有一个很重要的设计原则-如果一段代码在编译时没有提出“unchecked 未见检查转换”警告,则程序在运行时不会引发ClassCastException异常。正是基于这个原因,所以数组元素的类型不能包含类型变量或类型形参,除非是无上限的类型通配符。但可以声明元素类型包含类型变量或变量形参的数组。也就是说,只能声明List形式的数据,但不能创建ArrayList10这样的数组对象。假设Java支持穿件ArrayList10,则有如下程序。第六节第六节 泛型与数组泛型与数组将上面程序改为如下程序:上面程序声明了List类型的数组变量,这是允许的:但不允许创建List类型的对象,所以创建一个类型为ArrayList10的数组对象,这也是允许的。只是会有编译警告“unchecked未经检查的转换”,即编译器并不保证这段代码是安全的。Java允许创建无上限的通配符泛型数组,例如new ArrayList10,因此也可以将第一段代码改为使用无上限的通配符泛型数组,在这种情况下,程序不得不进行强制类型转换。上面程序编译不会发出任何警告,但会引发ClassCastException异常。所以程序应该通过instanceof运算符来保证它的数据类型。与此类似的是,创建元素类型是类型变量的数组对象也将导致编译错误。如下所示:由于类型变量在运行时并不存在,而编译器无法确定实际类型是什么,因此编译器在粗体字代码出报错。本章主要介绍了JDK1.5提供的泛型支持,还介绍了为何需要在编译时检查集合元素的类型,以及如何编程来实现这种检查,从而引出JDK1.5泛型给程序带来的简洁性和健壮性。本章详细讲解了如果定义泛型接口、泛型类,以及如何从泛型类、泛型接口派生子类或实现类,并深入讲解了泛型类的实质。本章介绍了类型通配符的用法,包括设定类型通配符的上限、下限等;本章重点介绍了泛型方法的知识,包括如何在方法签名是定义类型形参,以及泛型方法和类型通配符之间的区别和联系。本行最后介绍了Java不支持创建泛型数组,并深入分析了原因。第七节第七节 本章小结本章小结- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 深入 学习 Java 泛型
咨信网温馨提示:
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前自行私信或留言给上传者【精****】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时私信或留言给本站上传会员【精****】,需本站解决可联系【 微信客服】、【 QQ客服】,若有其他问题请点击或扫码反馈【 服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【 版权申诉】”(推荐),意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4008-655-100;投诉/维权电话:4009-655-100。
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前自行私信或留言给上传者【精****】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时私信或留言给本站上传会员【精****】,需本站解决可联系【 微信客服】、【 QQ客服】,若有其他问题请点击或扫码反馈【 服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【 版权申诉】”(推荐),意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4008-655-100;投诉/维权电话:4009-655-100。
关于本文