第8章 Java泛型与集合类
- 格式:doc
- 大小:166.00 KB
- 文档页数:27
java中集合的概念Java中的集合是一种非常重要的数据结构,用于存储和操作一组对象。
集合框架包含了许多类和接口,可以方便地进行数据的存储、查询、排序等操作,使得Java程序开发变得更加高效和便捷。
在本文中,我们将逐步介绍Java中集合的概念和用法。
一、集合框架概述Java中的集合框架是一个包含了多个接口和类的层次结构,用于表示和操作一组对象。
集合框架包含了通用的集合接口和实现,以及特定的集合类和接口,如List、Set、Map等。
集合框架的接口和类都是通过泛型实现的,可以存储任意类型的对象,比如基本类型和自定义类型的对象。
二、集合框架的接口Java中的集合框架包含了多个接口,其中包括:1. Collection:代表一组对象的集合,是其他集合接口的父接口。
它定义了一些通用的方法,如添加、删除、迭代等。
2. List:代表有序的集合,其中每个元素都有一个对应的索引。
List允许重复元素出现,并且可以通过索引访问、添加、删除元素。
3. Set:代表无序的集合,其中每个元素都是唯一的。
Set不允许重复的元素出现,可以用来去重。
4. Map:代表一组键值对的集合,其中每个键都是唯一的。
Map 允许多个值对应同一个键,可以用来快速查找和存储数据。
三、集合类的实现Java中的集合类可以通过实现集合接口来实现。
如ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是集合类的实现,我们可以通过这些集合类来方便地实现对一组对象的操作。
例如:1. 使用ArrayList来实现List接口,可以进行元素的添加、删除、查询等操作:List<String> list = new ArrayList<>();list.add("Alice");list.add("Bob");System.out.println(list.get(1));2. 使用HashSet来实现Set接口,可以去重并存储元素:Set<Integer> set = new HashSet<>();set.add(1);set.add(2);set.add(2);System.out.println(set.size());3. 使用HashMap来实现Map接口,可以快速查找并存储数据:Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("Alice", 12);hashMap.put("Bob", 18);System.out.println(hashMap.get("Bob"));四、集合的迭代Java中的集合类都实现了Iterable接口,因此可以使用迭代器来访问集合中的元素。
java集合的定义1. Java集合是一种用于存储和操作一组对象的数据结构。
它提供了一种更高级别的抽象,可以方便地进行添加、删除、查找和遍历操作。
集合可以存储多个对象,并且可以根据需要动态调整大小。
2. Java集合框架是Java编程语言提供的一组接口、类和算法,用于实现各种集合类型。
它包括了List、Set、Queue和Map等常用集合接口,以及它们的具体实现类。
集合框架提供了一种标准化的方式来处理集合,使得开发人员可以更加方便地使用和操作集合。
3. Java集合框架中的每个集合都是通过特定的接口来定义的。
例如,List接口代表了一个有序的集合,可以包含重复的元素。
Set接口代表了一个无序的集合,不允许包含重复的元素。
Queue接口代表了一个先进先出的队列,可以用于实现任务调度和事件处理等场景。
Map接口代表了一组键值对的映射,可以通过键来查找对应的值。
4. 在集合框架中,每个具体的集合类都实现了相应的接口,并提供了一套通用的方法来操作集合。
例如,ArrayList是List接口的一个实现类,它使用数组来存储元素,并提供了一系列方法来添加、删除、查找和遍历列表中的元素。
HashSet是Set接口的一个实现类,它使用哈希表来存储元素,并提供了一套方法来添加、删除和查找集合中的元素。
5. Java集合框架还提供了一些算法和工具类,可以用于对集合进行排序、查找和操作等操作。
例如,Collections类提供了一系列静态方法,可以对集合进行排序、查找和复制等操作。
Arrays类提供了一系列静态方法,可以对数组进行排序、查找和复制等操作。
这些算法和工具类可以大大简化集合的处理过程,并提高开发效率。
总结:Java集合是一种用于存储和操作一组对象的数据结构,它提供了一种更高级别的抽象,可以方便地进行添加、删除、查找和遍历操作。
Java集合框架是Java编程语言提供的一组接口、类和算法,用于实现各种集合类型,并提供了一种标准化的方式来处理集合。
java泛型语法Java泛型语法是Java编程语言中的一个重要特性,它允许我们编写更加通用和灵活的代码。
通过使用泛型,我们可以在编译时期检测类型错误,并在运行时期避免类型转换异常。
本文将介绍Java泛型的基本语法和使用方法。
一、泛型的定义和作用泛型是Java中的一种参数化类型,它允许我们在定义类、接口和方法时使用类型参数。
通过使用泛型,我们可以将类型作为参数传递给类、接口和方法,从而实现代码的复用和灵活性。
泛型的作用主要有以下几个方面:1. 类型安全:通过使用泛型,我们可以在编译时期检测类型错误,避免类型转换异常。
2. 代码复用:通过定义泛型类、接口和方法,我们可以实现对多种类型的支持,从而提高代码的复用性。
3. 简化代码:通过使用泛型,我们可以减少冗余的类型转换代码,使代码更加简洁。
4. 提高性能:通过使用泛型,我们可以避免使用Object类型,从而减少了装箱和拆箱的开销,提高了代码的执行效率。
二、泛型的基本语法Java中的泛型通过使用尖括号<>来定义类型参数。
在定义类、接口和方法时,我们可以将类型参数放在尖括号中,并在后续的代码中使用该类型参数。
1. 泛型类的定义:```public class GenericClass<T> {private T data;public T getData() {return data;}public void setData(T data) {this.data = data;}}```在上面的代码中,泛型类GenericClass使用了类型参数T。
我们可以在创建GenericClass对象时指定具体的类型,例如:```GenericClass<String> genericString = new GenericClass<>(); genericString.setData("Hello, World!");String data = genericString.getData();```上面的代码中,我们创建了一个GenericClass对象genericString,并指定了类型参数为String。
java泛型详解-绝对是对泛型⽅法讲解最详细的,没有之⼀1. 概述泛型在java中有很重要的地位,在⾯向对象编程及各种设计模式中有⾮常⼴泛的应⽤。
什么是泛型?为什么要使⽤泛型?泛型,即“参数化类型”。
⼀提到参数,最熟悉的就是定义⽅法时有形参,然后调⽤此⽅法时传递实参。
那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于⽅法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使⽤/调⽤时传⼊具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。
也就是说在泛型使⽤过程中,操作的数据类型被指定为⼀个参数,这种参数类型可以⽤在类、接⼝和⽅法中,分别被称为泛型类、泛型接⼝、泛型⽅法。
2. ⼀个栗⼦⼀个被举了⽆数次的例⼦:1 List arrayList = new ArrayList();2 arrayList.add("aaaa");3 arrayList.add(100);45for(int i = 0; i< arrayList.size();i++){6 String item = (String)arrayList.get(i);7 Log.d("泛型测试","item = " + item);8 }毫⽆疑问,程序的运⾏结果会以崩溃结束:1 ng.ClassCastException: ng.Integer cannot be cast to ng.StringArrayList可以存放任意类型,例⼦中添加了⼀个String类型,添加了⼀个Integer类型,再使⽤时都以String的⽅式使⽤,因此程序崩溃了。
为了解决类似这样的问题(在编译阶段就可以解决),泛型应运⽽⽣。
我们将第⼀⾏声明初始化list的代码更改⼀下,编译器会在编译阶段就能够帮我们发现类似这样的问题。
java中八个基本类型的包装类型-概述说明以及解释1.引言1.1 概述概述在Java编程语言中,有八个基本数据类型,即整型(byte、short、int、long)、浮点型(float、double)、字符型(char)和布尔型(boolean)。
尽管这些基本类型在编程中非常有用,但它们并不是对象,因此无法直接进行操作和传递。
为了解决这个问题,Java提供了对应的包装类型,也就是每个基本类型所对应的类。
在Java中,对于每个基本类型都有相应的包装类:Byte、Short、Integer、Long、Float、Double、Character和Boolean。
这些包装类是在Java的标准库中预先定义好的,并提供了许多有用的方法和属性,以便进行更复杂的操作。
在本文中,我们将详细探讨每个基本类型的包装类型,探索它们的作用和优势,以及它们与基本类型之间的关系。
我们还将对Java编程中使用这些包装类型的重要性和应用场景进行讨论。
接下来的章节将深入研究这些方面,并解释为什么在某些情况下使用包装类型是有益的。
我们还将总结基本类型和包装类型的特点,并探讨它们在Java编程中的重要性。
让我们开始这个有趣的探索吧!1.2文章结构1.2 文章结构本篇文章将围绕Java中八个基本类型的包装类型展开讨论。
以下是文章的主要结构:1. 引言:引言部分将提供对Java基本类型和包装类型的简要概述,介绍它们在编程中的作用和使用场景。
2. 正文:2.1 基本类型和包装类型的关系:这一部分将详细探讨基本类型和包装类型之间的关系,包括各种基本类型对应的包装类型的命名规则和特点。
2.2 包装类型的作用和优势:文章将进一步介绍包装类型的作用和优势。
我们将探讨包装类型的主要用途,如提供更多的功能和方法,和基本类型在集合操作中的应用等。
3. 结论:3.1 总结基本类型和包装类型的特点:这一部分将对前文的内容进行总结,重点强调基本类型和包装类型之间的差异和共性,以及使用时需注意的一些问题。
java泛型8泛型的内部原理:类型擦除以及类型擦除带来的问题参考:java核⼼技术⼀、Java泛型的实现⽅法:类型擦除前⾯已经说了,的泛型是伪泛型。
为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉。
正确理解泛型概念的⾸要前提是理解类型擦出(type erasure)。
Java中的泛型基本上都是在编译器这个层次来实现的。
在⽣成的Java字节码中是不包含泛型中的类型信息的。
使⽤泛型的时候加上的类型参数,会在编译器在编译的时候去掉。
这个过程就称为类型擦除。
如在代码中定义的List<object>和List<String>等类型,在编译后都会编程List。
JVM看到的只是List,⽽由泛型附加的类型信息对JVM来说是不可见的。
Java编译器会在编译时尽可能的发现可能出错的地⽅,但是仍然⽆法避免在运⾏时刻出现类型转换异常的情况。
类型擦除也是Java的泛型实现⽅法与C++模版机制实现⽅式之间的重要区别。
可以通过两个简单的例⼦,来证明java泛型的类型擦除。
例1、[java]1. public class Test4 {2. public static void main(String[] args) {3. ArrayList<String> arrayList1=new ArrayList<String>();4. arrayList1.add("abc");5. ArrayList<Integer> arrayList2=new ArrayList<Integer>();6. arrayList2.add(123);7. System.out.println(arrayList1.getClass()==arrayList2.getClass());8. }9. }在这个例⼦中,我们定义了两个ArrayList数组,不过⼀个是ArrayList<String>泛型类型,只能存储字符串。
java集合总结一、数组、集合数组、集合:都是一种容器,用一个对象管理多个对象;数组:不能自动增长;只能存放同类型的元素集合:能自动扩容;部分集合允许存放不同类型的元素;二、学习这些集合类要把握哪些东西:1〕怎样得到〔选择〕集合对象;2〕怎样添加元素3〕怎样删除元素4〕怎样循环遍历没一个元素三、list、set、mapcollection:父接口;Set:接口一个实现类:HashSetList:接口三个实现类:LinkedList,Vector,ArrayListSortedSet:接口实现类:TreeSet1、List:List:有序列表,允许存放重复的元素;实现类:ArrayList:数组实现,查询快,增删慢,线程担心全,轻量级;下标也是从0开头;LinkedList:链表实现,增删快,查询慢Vector:数组实现,线程平安,重量级2.Set:无序集合,不允许存放重复的元素;实现类HashSet:equals返回true,hashCode返回相同的整数;哈希表;子接口SortedSet:对Set排序实现类:TreeSet:二叉树实现的;看API:E泛型:表示一个对象;Iterator:接口,迭代器;java.util;hasNext();next();remove();Iterable:可迭代的,访问的;ng;实现了可迭代的接口就可以用迭代的方式访问;只需实现iterator();方法即可;Iteratoriterator();三种循环的访问方式:只有实现了Iterable接口的才能用第三种;能用其次种的也肯定能用第三种;ArrayList:自动扩容,是数组照搬过来的;3.MapHashMap:键值对,key不能重复,但是value可以重复;key 的实现就是HashSet;value对应着放;HashSet的后台有一个HashMap;初始化后台容量;只不过生成一个HashSet的话,系统只供应key的访问;假如有两个Key重复,那么会掩盖之前的;Hashtable:线程平安的Properties:java.util.Properties;key和value都是String 类型,用来读配置文件;HashMap与Hashtable区分:HashMap线程担心全的,允许null作为key或value;Hashtable线程平安的,不允许null作为key或value;TreeMap:对key排好序的Map;key就是TreeSet,value对应每个key;key要实现Comparable接口或TreeMap有自己的构造器;HashSet:remove(Objecto)的原则看这个对象O的Hashcode和equals是否相等,并不是看是不是一个对象;定义一个Map;key是课程名称,value是Integer表示选课人数;map.put(cou,map.get(cou)+newInteger(1));四、Hashtable、Properties1,Hashtable:实现了Map接口,此类实现一个哈希表,作用和HashMap相同。
Java中泛型ClassT、T与Class?、Object类和Class类、object.。
⼀.区别单独的T 代表⼀个类型(表现形式是⼀个类名⽽已),⽽ Class<T>代表这个类型所对应的类(⼜可以称做类实例、类类型、字节码⽂件), Class<?>表⽰类型不确定的类Class<T>表⽰T类型的字节码⽂件,意思是:Class<T> 相当于Class<T> c=T.class,T t new T() ;或者Class<T> c= t.getClass();通过以上可以获取类名为c.getName();解释:Class<T> ct=T.class,T t new T() ; 与Class c=T.class,T t new T() ;ct泛型指的是ct只能是T的字节码,⽽c可以是任何类的字节码。
所以⽤ct⽤法更好E - Element (在集合中使⽤,因为集合中存放的是元素)T - Type(Java 类)K - Key(键)V - Value(值)N - Number(数值类型)- 表⽰不确定的java类型举例说明:Set<T> 表⽰集合⾥是 T类的实例List<E> 表⽰集合⾥是 E类的实例List<?> 表⽰集合⾥的对象类型不确定,未指定List 同 List<?> 是⼀样的。
的作⽤: 1、⽤泛型:Java代码收藏代码List<T> list=new ArrayList<T>();T t=list.get(0); 2、不⽤泛型:Java代码收藏代码List list=new ArrayList();T t=(T).get(0);⼆、如何创建⼀个Class<T>类型的实例?就像使⽤⾮泛型代码⼀样,有两种⽅式:调⽤⽅法 Class.forName() 或者使⽤类常量X.class。
泛型(⼀)泛型类和泛型⽅法⼀、泛型的概念 Java5引⼊参数化类型(Parameterized Type)的概念,也称为泛型(Generic)。
泛型:就是允许在定义类、接⼝、⽅法时使⽤类型形参。
这个类型形参将在声明变量、创建对象、调⽤⽅法时动态指定,即传⼊实际的类型参数(也叫传⼊类型实参)。
传⼊的类型实参的类型必须是引⽤类型。
⼆、泛型类 2.1、定义泛型类public class A<T> { // 泛型类:定义类的时候指定类型形参T,在类⾥⾯T就可以当成类型使⽤private T a;public T getA() {return a;}public void setA(T a) {this.a = a;}} 2.2、继承泛型类的⼏种⽅式class B1 extends A<String> {}class B2<E> extends A<String> {}class B3<E> extends A<E> {}class B4<E1, E2> extends A<E1> {} 2.3、使⽤泛型类public static void main(String[] args) {B1 b1 = new B1();b1.setA("b1");System.out.println(b1.getA());A<String> a1 = new B1();a1.setA("a1");System.out.println(a1.getA());//B2<?> b2 = new B2<String>();//B2<String> b2:声明变量时已经指定了B2的类型形参E为String,//new B2<>():创建对象时可以使⽤菱形语法(泛型推断)B2<String> b2 = new B2<>();//菱形语法b2.setA("b2");System.out.println(b2.getA());// ⽆法通过A<String>推断出B2的类型形参E的类型,不可以使⽤菱形语法A<String> a2 = new B2<Object>();a2.setA("a2");System.out.println(a2.getA());B3<String> b3 = new B3<>();//菱形语法b3.setA("b3");System.out.println(b3.getA());A<String> a3 = new B3<>();//菱形语法a3.setA("a3");System.out.println(a3.getA());} 2.4、JDK7新特性:菱形语法(泛型推断) 菱形语法(泛型推断):从JDK 7 开始,Java允许在构造器后不需要带完整的泛型信息,只要给出⼀对尖括号<>即可,Java可以推断出尖括号⾥⾯应该是什么类型。
java8新特性,使⽤流遍历集合 在这篇“Java 8新特性教程”系列⽂章中,我们会深⼊解释,并通过代码来展⽰,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值。
在之前的⽂章“遍历、过滤、处理集合及使⽤Lambda表达式增强⽅法”中,我已经深⼊解释并演⽰了通过lambda表达式和⽅法引⽤来遍历集合,使⽤predicate接⼝来过滤集合,实现接⼝的默认⽅法,最后还演⽰了接⼝静态⽅法的实现。
源代码都在我的Github上:可以从克隆。
内容列表使⽤流来遍历集合。
从集合或数组创建流。
聚合流中的值。
1. 使⽤流来遍历集合简介:Java的集合框架,如List和Map接⼝及Arraylist和HashMap类,让我们很容易地管理有序和⽆序集合。
集合框架⾃引⼊的第⼀天起就在持续的改进。
在Java SE 8中,我们可以通过流的API来管理、遍历和聚合集合。
⼀个基于流的集合与输⼊输出流是不同的。
如何⼯作?它采⽤⼀种全新的⽅式,将数据作为⼀个整体,⽽不是单独的个体来处理。
当你使⽤流时,你不需要关⼼循环或遍历的细节。
你可以直接从⼀个集合创建⼀个流。
然后你就能⽤这个流来许多事件了,如遍历、过滤及聚和。
我将从项⽬ Java8Features 的com.tm.java8.features.stream.traversing 包下的例⼦开始。
代码在⼀个SequentialStream 类中,Java SE 8 中有两种集合流,即串⾏流和并⾏流。
List<person> people = new ArrayList<>();people.add(new Person("Mohamed", 69));people.add(new Person("Doaa", 25));people.add(new Person("Malik", 6));Predicate<person> pred = (p) -> p.getAge() > 65;displayPeople(people, pred);...........private static void displayPeople(List<person> people, Predicate<person> pred) {System.out.println("Selected:");people.forEach(p -> {if (pred.test(p)) {System.out.println(p.getName());}});}在这两种流中,串⾏流相对⽐较简单,它类似⼀个迭代器,每次处理集合中的⼀个元素。
第1章Java概述1.编译java application源程序文件将产生相应的字节码文件,这些字节码文件别的扩展名为.java2.执行一个java程序fristapp的方法是运行java fristapp3.main()方法的返回类型是void4.在java代码中,public static void main方法的参数描述正确的是string args【】,string【】args5.内存的回收程序负责释放无用内存√6.java体系主要分为java ME,Java SE,JavaEE三大块第2章Java基础1.Java语言中,下列标识符错误的是40name2.java变量中,以下不属于引用类型的数据类型是字符型3.double d=5.3E12 ×4.C5.A6.for循环的一般形式为;for(初值;终值;增量),以下对for循环的叙述,正确的是初值和增量都是赋值语句,终值是条件判断语句7.当输入下面选项中3值时,将会输出default8.下面哪种方法能够支持javadoc命令/**…*/9.下面声明一个string类型的数组正确的是string str[]10.下面定义一个整型数组,不合法的是int[][]array=new int[][4];11.给定代码;。
下面叙述正确的是输出的结果为:012.java语言规定,标示符只能由字母,数字美元符$和下划线租成,并且第一个字符不能是数字;java是区分大小写的。
13.表达式1/2*3的计算结果是0;设x=2,则表达式(x++)/3的值是014.数组的长度可以用其属性lengt h获得;创建一个数组对象可以使用new关键字创建第3章面向对象基础1.在java中引用对象变量和对象间有什么关系?引用变量是指向对象的一个指针2.对象是面向对象技术的核心所在,在面向对象程序设计中,对象是累的抽象×3.构造方法何时被调用?创建对象时4.A,B,D5.在java语言中在包p1中包含包p2,类A直接隶属于p1,类B直接隶属于包p2.在类c中要使用类a的方法和类b的方法b,需要选择import p1.*; import p1.p2,*;6.java中,访问修饰符限制最高的是private第4章类之间的关系1.在java中,下面关于类的描述正确的是一个父类可以有多个子类2.在java语言中,类worker是类person的子类,worker的构造方法中有一句“super()”,该语句是调用person的构造法法。
第8章 Java 泛型与集合类核心内容:1. 集合的作用与概念2. 泛型的作用与用法。
3. Set 、List 、Map 的用法4. Iterator 、Enumeration 的用法8.1 早期的集合类集合可理解为一个容器,该容器主要指映射(map )、集合(set )、列表(list )、散列表(hashtable )等抽象数据结构。
容器可以包含有多个元素,这些元素通常是一些Java 对象。
针对上述抽象数据结构所定义的一些标准编程接口称之为集合框架。
集合框架主要是由一组精心设计的接口、类和隐含在其中的算法所组成,通过它们可以采用集合的方式完成Java 对象的存储、获取、操作以及转换等功能。
集合框架的设计是严格按照面向对象的思想进行设计的,它对上述所提及的抽象数据结构和算法进行了封装。
封装的好处是提供一个易用的、标准的编程接口,使得在实际编程中不需要再定义类似的数据结构,直接引用集合框架中的接口即可,提高了编程的效率和质量。
此外还可以在集合框架的基础上完成如堆栈、队列和多线程安全访问等操作。
在集合框架中有几个基本的集合接口,分别是Collection 接口、List 接口、Set 接口和Map 接口,它们所构成的层次关系如图8-1所示。
图8-1 集合框架层次关系图(1) Collection 接口是一组允许重复的对象。
(2) Set 接口继承Collection ,但不允许集合中出现重复元素。
(3) List 接口继承Collection ,允许集合中有重复,并引入位置索引。
(4)Map 接口与Collection 接口无任何关系,Map 的典型应用是访问按关键字存储的值,所包含的是键—值对,而不是单个独立的元素。
作为对上述接口的实现,Java 语言目前主要提供下述类的定义,如表8-1所示Collection 接口Set 接口 List 接口Map 接口表8-1 集合接口及其类的实现接口集合类的实现历史集合类Set HashSetTreeSetList ArrayList V ectorLinkedList StackMap HashMap HashtableTreeMap由于在JDK1.5当中增加了泛型,我们把JDK1.5之前不支持泛型的集合类称之为早期集合类。
早期的集合有个缺点:当我们把一个对象存放到集合里后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型。
早期的集合之所以被设计成这样,是因为设计集合的程序员不知道我们需要用它来保存什么类型的对象。
所以他们把集合设计成能保存任何类型的对象。
但这样做也带来了两个问题:一、集合对元素类型没有任何限制,例如只想创建一个保存String类型的集合,但是程序也允许把boolean类型的对象存放在该集合当中,这样容易引发异常。
二、由于把对象保存在集合当中时,集合忘记了对象的数据类型,只知道它存放的是Object类型,因此取出集合元素后通常要进行强制类型转换。
这种强制类型转换既会增加程序的复杂度,也可能引发ClassCastException。
【例8-1】Test.java 早期集合类1 import java.util.ArrayList;2 import java.util.Iterator;3 import java.util.List;4 public class Test {5 public static void main(String[] args) {6 List list=new ArrayList();7 list.add("beijing");8 list.add("wuhan");9 list.add("shanghai");10 //list.add(4);11 for(int i=0;i<list.size();i++){12 String s=(String)list.get(i);13 System.out.println(s);14 }15 }16 }输出结果:D:\JA V A\8>java Testbeijingwuhanshanghai程序说明:上述程序的第6行是创建一个List集合对象,第7、8、9行是向该集合当中添了一个3个String类型的对象元素,第11、12、13、14行是通过for循环将集合当中的元素取出,转换为String类型并输出。
上述程序只是创建了一个List对象,而且只用List对象来保存字符串对象。
但是对于保存在List对象当中的数据类型我们不能做任何的限制。
如果在程序的第10行,我们不小心把一个int类型的数据保存到List当中,就将导致程序在第12行出现ClassCastException 异常。
自JDK1.5以后,Java引入了泛型的概念,允许我们在创建集合时指定集合元素的类型。
这样添加数据元素到集合中时会做类型检查。
如果要添加的数据元素与指定的数据类型不匹配,编译时会报错。
8.2 泛型在面向对象编程语言中,多态算是一种泛化机制。
例如,你可以将方法的参数类型设为基类,那么该方法就可以接受从这个基类中导出的任何类作为参数。
这样的方法更加通用一些,可应用的地方也多一些。
但有时候,拘泥于类的单继承体系,也会使程序受限太多。
如果方法的参数是一个接口,而不是一个类,这种限制就放松了许多。
因为任何实现了该接口的类都能够满足该方法。
可是有时候,即便使用了接口,对程序的约束也还是太强了。
因为一旦指明了接口,就要求你的代码必须使用特定的接口。
而我们希望达到的目的是编写更通用的代码,要使代码能够应用于“某种不具体的类型”,而不是一个具体的接口或类。
在Java SE 5中增加了泛型机制。
“泛型”这个术语的意思是:“适用于许多的类型”。
泛型实现了参数化类型的概念,使代码可以应用于多种类型。
8.2.1 泛型类一个泛型类就是具有一个或多个类型变量的类。
本节使用一个简单的Pair类作为例子。
public class Pair<T>{private T first;private T second;public Pair(){first=null; second=null;}public Pair(T first,T second){this.first=first; this.second=second;}public T getFirst(){return first;}public T getSecond(){return second;}public void setFirst(T newV alue){first=newV alue;}public void setSecond(T newV alue){second=newV alue;}}Pair类引入了一个类型变量T,用尖括号< >括起来,并放在类名的后面。
泛型类可以有多个类型变量。
例如,可以定义Pair类,其中第一个成员变量和第二个成员变量使用不同的类型:public clas s Pair<T ,U>{…..}类定义中的类型变量指定方法的返回类型以及成员变量和局部变量的类型。
例如:private T first;用具体的类型替换类型变量就可以实例化泛型类型,例如:Pair<String>可以将结果想像成带有构造器的普通类:public class Pair{private String first;private String second;public Pair(){first=null; second=null;}public Pair(String first,String second){this.first=first; this.second=second;}public String getFirst(){return first;}public String getSecond(){return second;}public void setFirst(String newV alue){first=newV alue;}public void setSecond(String newV alue){second=newV alue;}}【例8-2】PairTest.java 泛型类1 public class PairTest{2 public static void main(String[] args){3 Pair<String> pair=new Pair<String>("Hello","Java");4 System.out.println("first="+pair.getFirst());5 System.out.println("second="+pair.getSecond());6 }7 }输出结果:D:\JA V A\8>java PairTestfirst=Hellosecond=Java程序分析:上述程序的第3行创建了一个泛型类对象pair,并指定该对象的成员变量的类型为String 类型。
并调用其带String类型参数的构造方法对其进行初始化。
将pair对象的第一个成员变量first的值设置为"Hello",第二个成员变量second的值设置为"Java"。
第4,5行分别调用pair对象的getFirst()、getSecond()方法获得成员变量first、second的值并输出到控制台。
8.2.2 泛型方法前面已经介绍了如何定义一个泛型类。
实际上,还可以定义一个带有参数类型的方法即泛型方法。
泛型方法使得该方法能够独立于类而产生变化,泛型方法所在的类可以是泛型类,也可以不是泛型类。
创建一个泛型方法常用的形式如下:[访问修饰符] [static] [final] <参数类型列表> 返回值方法名( [形式参数列表] )下面我们在GenericMethod类当中声明一个f ( )泛型方法,用于返回调用该方法时,所传入的参数类型的类名。
【例8-3】GnericMethodTest.java 泛型方法1 class GenericMethod{2 public <T> void f(T x){3 System.out.println(x.getClass().getName());4 }5 }67 public class GenericMethodTest{8 public static void main(String[] args){9 GenericMethod gm=new GenericMethod();10 gm.f(" ");11 gm.f(1);12 gm.f(1.0f);13 gm.f('c');14 gm.f(gm);15 }16 }输出结果:D:\JA V A\8>java GenericMethodTestng.Stringng.Integerng.Floatng.CharacterGenericMethod程序分析:上述程序的第9行创建了一个GenericMethod类型的对象gm。