文档库 最新最全的文档下载
当前位置:文档库 › java泛型

java泛型

java泛型
java泛型

一. 泛型概念的提出(为什么需要泛型)?

首先,我们看下下面这段简短的代码:

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4. List list = new ArrayList();

5. list.add("qqyumidi");

6. list.add("corn");

7. list.add(100);

8.

9.for (int i = 0; i < list.size(); i++) {

10. String name = (String) list.get(i); // 1

11. System.out.println("name:" + name);

12. }

13. }

14.}

定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer 类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“https://www.wendangku.net/doc/1a2405671.html,ng.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

在如上的编码过程中,我们发现主要存在两个问题:

1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。

2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“https://www.wendangku.net/doc/1a2405671.html,ng.ClassCastException”异常。

那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“https://www.wendangku.net/doc/1a2405671.html,ng.ClassCastException”异常呢?答案就是使用泛型。

二.什么是泛型?

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

看着好像有点复杂,首先我们看下上面那个例子采用泛型的写法。

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4./*

5. List list = new ArrayList();

6. list.add("qqyumidi");

7. list.add("corn");

8. list.add(100);

9. */

10.

11. List list = new ArrayList();

12. list.add("qqyumidi");

13. list.add("corn");

14.//list.add(100); // 1 提示编译错误

15.

16.for (int i = 0; i < list.size(); i++) {

17. String name = list.get(i); // 2

18. System.out.println("name:" + name);

19. }

20. }

21.}

采用泛型写法后,在//1处想加入一个Integer类型的对象时会出现编译错误,通过

List,直接限定了list集合中只能含有String类型的元素,从而在//2处无须进行强制类型转换,因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。

结合上面的泛型定义,我们知道在List中,String是类型实参,也就是说,相应的List接口中肯定含有类型形参。且get()方法的返回结果也直接是此形参类型(也就是对应的传入的类型实参)。下面就来看看List接口的的具体定义:

1.public interface List extends Collection {

2.

3.int size();

4.

5.boolean isEmpty();

6.

7.boolean contains(Object o);

8.

9. Iterator iterator();

10.

11. Object[] toArray();

12.

13. T[] toArray(T[] a);

14.

15.boolean add(E e);

16.

17.boolean remove(Object o);

18.

19.boolean containsAll(Collection c);

20.

21.boolean addAll(Collection c);

22.

23.boolean addAll(int index, Collection c);

24.

25.boolean removeAll(Collection c);

26.

27.boolean retainAll(Collection c);

28.

29.void clear();

30.

31.boolean equals(Object o);

32.

33.int hashCode();

34.

35. E get(int index);

36.

37. E set(int index, E element);

38.

39.void add(int index, E element);

40.

41. E remove(int index);

42.

43.int indexOf(Object o);

44.

45.int lastIndexOf(Object o);

46.

47. ListIterator listIterator();

48.

49. ListIterator listIterator(int index);

50.

51. List subList(int fromIndex, int toIndex);

52.}

我们可以看到,在List接口中采用泛型化定义之后,中的E表示类型形参,可以接收具体的类型实参,并且此接口定义中,凡是出现E的地方均表示相同的接受自外部的类型实参。

自然的,ArrayList作为List接口的实现类,其定义形式是:

1.public class ArrayList extends AbstractList

2.implements List, RandomAccess, Cloneable, java.io.Serializable {

3.

4.public boolean add(E e) {

5. ensureCapacityInternal(size + 1); // Increments modCount!!

6. elementData[size++] = e;

7.return true;

8. }

9.

10.public E get(int index) {

11. rangeCheck(index);

12. checkForComodification();

13.return ArrayList.this.elementData(offset + index);

14. }

15.

16.//...省略掉其他具体的定义过程

17.

18.}

由此,我们从源代码角度明白了为什么//1处加入Integer类型对象编译错误,且//2处get()到的类型直接就是String类型了。

三.自定义泛型接口、泛型类和泛型方法

从上面的内容中,大家已经明白了泛型的具体运作过程。也知道了接口、类和方法也都可以使用泛型去定义,以及相应的使用。是的,在具体使用时,可以分为泛型接口、泛型类和泛型方法。

自定义泛型接口、泛型类和泛型方法与上述Java源码中的List、ArrayList类似。如下,我们看一个最简单的泛型类和方法定义:

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4.

5. Box name = new Box("corn");

6. System.out.println("name:" + name.getData());

7. }

8.

9.}

10.

11.class Box {

12.

13.private T data;

14.

15.public Box() {

16.

17. }

18.

19.public Box(T data) {

20.this.data = data;

21. }

22.

23.public T getData() {

24.return data;

25. }

26.

27.}

在泛型接口、泛型类和泛型方法的定义过程中,我们常见的如T、E、K、V等形式的参数常用于表示泛型形参,由于接收来自外部使用时候传入的类型实参。那么对于不同传入的类型实参,生成的相应对象实例的类型是不是一样的呢?

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4.

5. Box name = new Box("corn");

6. Box age = new Box(712);

7.

8. System.out.println("name class:" + name.getClass()); // com.qqy

umidi.Box

9. System.out.println("age class:" + age.getClass()); // com.qqy

umidi.Box

10. System.out.println(name.getClass() == age.getClass()); // true

11.

12. }

13.

14.}

由此,我们发现,在使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,即还是原来的最基本的类型(本实例中为Box),当然,在逻辑上我们可以理解成多个不同的泛型类型。

究其原因,在于Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。

对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。

四.类型通配符

接着上面的结论,我们知道,Box和Box实际上都是Box类型,现在需要继续探讨一个问题,那么在逻辑上,类似于Box和Box是否可以看成具有父子关系的泛型类型呢?

为了弄清这个问题,我们继续看下下面这个例子:

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4.

5. Box name = new Box(99);

6. Box age = new Box(712);

7.

8. getData(name);

9.

10.//The method getData(Box) in the type GenericTest is

11.//not applicable for the arguments (Box)

12. getData(age); // 1

13.

14. }

15.

16.public static void getData(Box data){

17. System.out.println("data :" + data.getData());

18. }

19.

20.}

我们发现,在代码//1处出现了错误提示信息:The method getData(Box) in the t ype GenericTest is not applicable for the arguments (Box)。显然,通过提示信息,我们知道Box在逻辑上不能视为Box的父类。那么,原因何在呢?

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4.

5. Box a = new Box(712);

6. Box b = a; // 1

7. Box f = new Box(3.14f);

8. b.setData(f); // 2

9.

10. }

11.

12.public static void getData(Box data) {

13. System.out.println("data :" + data.getData());

14. }

15.

16.}

17.

18.class Box {

19.

20.private T data;

21.

22.public Box() {

23.

24. }

25.

26.public Box(T data) {

27. setData(data);

28. }

29.

30.public T getData() {

31.return data;

32. }

33.

34.public void setData(T data) {

35.this.data = data;

36. }

37.

38.}

这个例子中,显然//1和//2处肯定会出现错误提示的。在此我们可以使用反证法来进行说明。

假设Box在逻辑上可以视为Box的父类,那么//1和//2处将不会有错误提示了,那么问题就出来了,通过getData()方法取出数据时到底是什么类型呢?Integer? Float? 还是Number?且由于在编程过程中的顺序不可控性,导致在必要的时候必须要进行类型判断,且进行强制类型转换。显然,这与泛型的理念矛盾,因此,在逻辑上Box不能视为Box的父类。

好,那我们回过头来继续看“类型通配符”中的第一个例子,我们知道其具体的错误提示的深层次原因了。那么如何解决呢?总部能再定义一个新的函数吧。这和Java中的多态理念显然是违背的,因此,我们需要一个在逻辑上可以用来表示同时是Box和Box的父类的一个引用类型,由此,类型通配符应运而生。

类型通配符一般是使用 ? 代替具体的类型实参。注意了,此处是类型实参,而不是类型形参!且Box在逻辑上是Box、Box...等所有Box<具体类型实参>的父类。由此,我们依然可以定义泛型方法,来完成此类需求。

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4.

5. Box name = new Box("corn");

6. Box age = new Box(712);

7. Box number = new Box(314);

8.

9. getData(name);

10. getData(age);

11. getData(number);

12. }

13.

14.public static void getData(Box data) {

15. System.out.println("data :" + data.getData());

16. }

17.

18.}

有时候,我们还可能听到类型通配符上限和类型通配符下限。具体有是怎么样的呢?

在上面的例子中,如果需要定义一个功能类似于getData()的方法,但对类型实参又有进一步的限制:只能是Number类及其子类。此时,需要用到类型通配符上限。

1.public class GenericTest {

2.

3.public static void main(String[] args) {

4.

5. Box name = new Box("corn");

6. Box age = new Box(712);

7. Box number = new Box(314);

8.

9. getData(name);

10. getData(age);

11. getData(number);

12.

13.//getUpperNumberData(name); // 1

14. getUpperNumberData(age); // 2

15. getUpperNumberData(number); // 3

16. }

17.

18.public static void getData(Box data) {

19. System.out.println("data :" + data.getData());

20. }

21.

22.public static void getUpperNumberData(Box data){

23. System.out.println("data :" + data.getData());

24. }

25.

26.}

此时,显然,在代码//1处调用将出现错误提示,而//2 //3处调用正常。

类型通配符上限通过形如Box形式定义,相对应的,类型通配符下限为Box形式,其含义与类型通配符上限正好相反,在此不作过多阐述了。

五.话外篇

本文中的例子主要是为了阐述泛型中的一些思想而简单举出的,并不一定有着实际的可用性。另外,一提到泛型,相信大家用到最多的就是在集合中,其实,在实际的编程过程中,自己可以使用泛型去简化开发,且能很好的保证代码质量。并且还要注意的一点是,Java 中没有所谓的泛型数组一说。

对于泛型,最主要的还是需要理解其背后的思想和目的。

java泛型详解

java泛型详解 泛型(Generic type 或者generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。 可以在集合框架(Collection framework)中看到泛型的动机。例如,Map类允许您向一个Map添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如String)的对象。 因为Map.get()被定义为返回Object,所以一般必须将Map.get()的结果强制类型转换为期望的类型,如下面的代码所示: Map m = new HashMap(); m.put("key", "blarg"); String s = (String) m.get("key"); 要让程序通过编译,必须将get()的结果强制类型转换为String,并且希望结果真的是一个String。但是有可能某人已经在该映射中保存了不是String的东西,这样的话,上面的代码将会抛出ClassCastException。 理想情况下,您可能会得出这样一个观点,即m是一个Map,它将String键映射到String值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。 泛型的好处 Java 语言中引入泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了。这带来了很多好处: · 类型安全。泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。 Java 程序中的一种流行技术是定义这样的集合,即它的元素或键是公共类型的,比如“Str ing列表”或者“String到String的映射”。通过在变量声明中捕获这一附加的类型信息,泛型允许编译器实施这些附加的类型约束。类型错误现在就可以在编译时被捕获了,而不是在运行时当作 ClassCastException展示出来。将类型检查从运行时挪到编译时有助于您更容易找到错误,并可提高程序的可靠性。

看一下Java泛型的设计

从零开始来看一下Java泛型的设计 泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java泛型的设计,将会涉及到通配符处理,以及让人苦恼的类型擦除。 作者:ziwenxie来源:ziwenxie|2017-03-03 10:37 收藏 分享 引言 泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java 泛型的设计,将会涉及到通配符处理,以及让人苦恼的类型擦除。 泛型基础 泛型类 我们首先定义一个简单的Box类: public class Box {

private String object; public void set(String object) { this.object = object; } public String get() { return object; } } 这是最常见的做法,这样做的一个坏处是Box里面现在只能装入String类型的元素,今后如果我们需要装入Integer 等其他类型的元素,还必须要另外重写一个Box,代码得不到复用,使用泛型可以很好的解决这个问题。 public class Box { // T stands for "Type" private T t; public void set(T t) { this.t = t; } public T get() { return t; } } 这样我们的Box类便可以得到复用,我们可以将T替换成任何我们想要的类型: Box integerBox = new Box(); Box doubleBox = new Box(); Box stringBox = new Box(); 泛型方法 看完了泛型类,接下来我们来了解一下泛型方法。声明一个泛型方法很简单,只要在返回类型前面加上一个类似的形式就行了: public class Util { public static boolean compare(Pair p1, Pair p2) { return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue()); } }

java泛型

Java为什么要有泛型? 答: ①在没有泛型之前,一旦把一个对象添加到java集合中去,集合就会忘记对象的类型,把所有 的对象当成Object来处理.当程序从集合中取出对象后,就需要进行强制转换类型.这种类型转换不仅代码臃肿而且容易引起ClassCastException异常. ②增加了泛型支持后的集合,完全可以记住集合中的元素类型,并可以在编译时检查集合中 元素的类型,如果试图想集合中添加不满足类型要求的对象,编译器就会提示错误.增加泛型的集合,可以让代码更加简洁,程序更加健壮(java泛型可以保证如果程序在编译时候没有警告,运行时就不会产生ClassCastException). ③如果不设计泛型,那么集合中就可以装任何类型,所有可能引起异常。由于把对象丢进 集合时,集合失去了对象的状态信息,集合只知道它装的是Object类型元素,因此不仅麻烦还容易引起异常。 泛型 所谓泛型,就是允许在定义类、接口时指定类型形参,这个类型参数将在申明变量。创建对象时确定(既传入实际的类型参数,也可称为类型参数)。 代码欣赏:

上面三个接口定义的比较简单,除了尖括号中的内容—这就是泛型的实质:允许在定义接口、类时指定类型形参。类型形参在整个接口。类体内中可以当成类型使用,几乎所有可以使用其他普通类型的地方都可以使用这种类型参数。 泛型到底是什么?: 上面程序定义了一个带泛型声明的Apple类(先不要理会这个类型参数是否具有实际意义),实际使用Apple类的使用,必须给T传入实际类型。这样就生成了如Apple,Apple…等形式的逻辑子类(逻辑上不存在的子类)。 怎么使用泛型? 在开放中当我们需要一个父类,而父类中的方法或字段需要用到子类类型但是并不能确定到底要使用那一个子类类型或者遇到不知道子类具体类型,或者子类太多,不能写死一种子类时既可以给父类定义泛型,当实例化父类对象(或者使用父类对象创建子类对象时—多态)时再传入指定子类类型。

16JAVA第六单元练习题 泛型与集合

6泛型与集合 6.1单项选择题 1.可实现有序对象的操作是?() A.HashMap B.HashSet C.TreeMap D.Stack 2.不是迭代器接口(Iterator)所定义的方法是()。 A.hasNext()B.next() C.remove()D.nextElement() 3.下面说法不正确的是() A.列表(List)、集合(Set)和映射(Map)都是java.util包中的接口。 B.List接口是可以包含重复元素的有序集合。 C.Set接口是不包含重复元素的集合。 D.Map接口将键映射到值,键可以重复,但每个键最多只能映射一个值。 4.下面那些方法不是接口Collection中已声明的方法() A.添加元素的add(Object obj)方法 B.删除元素的remove(Object obj)方法 C.得到元素个数的length()方法 D.返回迭代器的iterator()方法,迭代器用于元素遍历 5.下列关于容器的描述中,错误的是() A.容器是由若干个组建和容器组成的 B.容器是对图形界面中界面元素的一种管理 C.容器是一种对指定宽和高的矩形范围 D.容器都是可以独立的窗口 6.下列界面元素中,不是容器的是() A.List B.JFrame C.JDialog D.Panel 7.应用程序的main方法中有以下语句,则输出的结果是()。

Hashtable hashtable=new Hashtable(); hashtable.put("100","aaa"); hashtable.put("200","bbb"); hashtable.put("300","ccc"); System.out.println(hashtable.get("300").toString() +hashtable.get("200").toString() +hashtable.get("100").toString()); A)aaa B)bbb C)ccc D)cccbbbaaa 6.2判断题 1.Map接口是自Collection接口继承而来。(×) 2.集合Set是通过键-值对的方式来存储对象的。(×) 3.Integer i=(Integer.valueOf("926")).intValue();(√) 4.String s=(Double.valueOf("3.1415926")).toString();(√) 5.Integer I=Integer.parseInt("926");(√) 6.Arrays类主要对数组进行操作。(√) 7.在集合中元素类型必须是相同的。(√) 8.集合中可以包含相同的对象。(×) 9.枚举接口定义了具有删除功能的方法。(×) 6.3程序阅读题 1.阅读下面的程序,回答问题。 import java.util.*; public class T{ public static void main(String args[]){ Set set=new TreeSet(); set.add(new Integer(10)); set.add(new Integer(5)); set.add(new Integer(15)); set.add(new Integer(5)); set.add(new Integer(10)); System.out.println("size="+set.size()); Iterator it=set.iterator(); while(it.hasNext()){ System.out.print(it.next()+""); } }

Java泛型详解

Java 泛型 1 什么是泛型 (2) 2 泛型类跟接口及泛型方法 (3) 2.1 泛型类跟接口及继承 (3) 2.1.1泛型类 (3) 2.1.2继承 (3) 2.1.3接口 (3) 2.2 泛型方法 (3) 2.2.1 方法 (3) 2.2.2 类型推断 (4) 3 泛型实现原理 (5) 4 泛型数组 (6) 5边界 (7) 6通配符 (8) 7 泛型的问题及建议 (9) 7.1问题 (9) 7.2 建议 (9)

1 什么是泛型 从jdk1.5开始,Java中开始支持泛型了。泛型是一个很有用的编程工具,给我们带来了极大的灵活性。在看了《java核心编程》之后,我小有收获,写出来与大家分享。 所谓泛型,我的感觉就是,不用考虑对象的具体类型,就可以对对象进行一定的操作,对任何对象都能进行同样的操作。这就是灵活性之所在。但是,正是因为没有考虑对象的具体类型,因此一般情况下不可以使用对象自带的接口函数,因为不同的对象所携带的接口函数不一样,你使用了对象A的接口函数,万一别人将一个对象B传给泛型,那么程序就会出现错误,这就是泛型的局限性。所以说,泛型的最佳用途,就是用于实现容器类,实现一个通用的容器。该容器可以存储对象,也可以取出对象,而不用考虑对象的具体类型。因此,在学习泛型的时候,一定要了解这一点,你不能指望泛型是万能的,要充分考虑到泛型的局限性。下面我们来探讨一下泛型的原理以及高级应用。首先给出一个泛型类: public class Pair { 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 newValue) { first = newValue; } public void setSecond(T newValue) { second = newValue; } private T first; private T second; } 我们看到,上述Pair类是一个容器类(我会多次强调,泛型天生就是为了容器类的方便实现),容纳了2个数据,但这2个数据类型是不确定的,用泛型T来表示。关于泛型类如何使用,那是最基本的内容,在此就不讨论了。

java泛型接口,泛型类泛型方法

泛型可提高代码的高扩展性和重用率. 1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。 2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。 3、泛型的类型参数可以有多个。 4、泛型的参数类型可以使用extends语句,例如。习惯上称为“有界类型”。 5、泛型的参数类型还可以是通配符类型。例如Class classType = Class.forName("https://www.wendangku.net/doc/1a2405671.html,ng.String"); 泛型可以用在接口,类方法,集合上面. 泛型接口: interface testGenerics{ T getT(T t); String assume(T t); } 泛型类:

public class GenericsFoo { private T x; public GenericsFoo(T x) { this.x = x; } public T getX() { return x; } public void setX(T x) { this.x = x; } } 使用来声明一个类型持有者名称,然后就可以把T当作一个类型代表来声明成员、参数和返回值类型。 当然T仅仅是个名字,这个名字可以自行定义。 泛型方法: 是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。如: public class ExampleA { public void f(T x) {

System.out.println(x.getClass().getName()); } 使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了定义不同,调用就像普通方法一样。 限制泛型的可用类型: 在上面的例子中,由于没有限制class GenericsFoo类型持有者T的范围,实际上这里的限定类型相当于Object,这和“Object泛型”实质是一样的。限制比如我们要限制T为集合接口类型。只需要这么做: class GenericsFoo,这样类中的泛型T 只能是Collection接口的实现类,传入非Collection接口编译会出错。 注意:这里的限定使用关键字extends,后面可以是类也可以是接口。但这里的extends已经不是继承的含义了,应该理解为T类型是实现Collection接口的类型,或者T是继承了XX类的类型。 下面继续对上面的例子改进,我只要实现了集合接口的类型: public class CollectionGenFoo { private T x; public CollectionGenFoo(T x) { this.x = x;

实验七:Java集合与泛型

实验七Java集合与泛型 一、实验目的 1)掌握集合的概念、体系结构、分类及使用场景 2)了解Set接口及主要实现类(HashSet、TreeSet) 3)了解List接口及主要实现类(ArrayList、LinkedList、Vector) 4)掌握ArrayList的使用 5)掌握ArrayList与Vector的区别 6)了解Map接口及主要实现类(HashMap、TreeMap、HashTable) 7)掌握HashMap的使用 8)掌握HashMap与HashTable的区别 二、实验环境 JDK1.6+Eclpise3.2 三、实验准备 1)复习课件中理论知识 2)练习课堂所讲的例子 四、实验内容 1、编写程序练习List集合的基本使用: 1) 创建一个只能容纳String对象名为names的ArrayList集合; 2)按顺序往集合中添加5个字符串对象:“张三”、“李四”、“王五”、“马六”、“赵七”; 3)对集合进行遍历,分别打印集合中的每个元素的位置与内容; 4)首先打印集合的大小,然后删除集合中的第3个元素,并显示删除元素的内容,然后再打印目前集合中第3个元素的内容,并再次打印集合的大小。 2、编写程序练习Map集合的基本使用: 1)创建一个只能值只能容纳String对象的person的HashMap集合; 2)往集合中添加5个“键-值”对象:id—>”1”、name—>”张三”、sex—>”男”、age—>”25”、love—>”爱学Java” 3)对集合进行遍历,分别打印集合中的每个元素的键与值; 4)首先打印集合的大小,然后删除集合中的键为age的元素,并显示删除元素的内容,并再次打印集合的大小。 五、验过程及结果 第1题调试结果如下图:

java泛型详解

Java 泛型详解 泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java 泛型的设计,将会涉及到通配符处理,以及让人苦恼的类型擦除。 泛型基础 泛型类 我们首先定义一个简单的Box类: public class Box { private String object; public void set(String object) { this.object = object; } public String get() { return object; }}这是最常见的做法,这样做的一个坏处是Box里面现在只能装入String类型的元素,今后如果我们需要装入Integer等其他类型的元素,还必须要另外重写一个Box,代码得不到复用,使用泛型可以很好的解决这个问题。 public class Box { // T stands for 'Type' private T t; public void set(T t) { this.t = t; } public T get() { return t; }} 这样我们的Box类便可以得到复用,我们可以将T替换成任何我们想要的类型: Box integerBox = new Box();Box doubleBox = new

Box();Box stringBox = new Box(); 泛型方法 看完了泛型类,接下来我们来了解一下泛型方法。声明一个泛型方法很简单,只要在返回类型前面加上一个类似的形式就行了: public class Util { public static boolean compare(Pair p1, Pair p2) { return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue()); }}public class Pair { private K key; private V value; public Pair(K key, V value) { this.key = key; this.value = value; } public void setKey(K key) { this.key = key; } public void setValue(V value) { this.value = value; } public K getKey() { return key; } public V getValue() { return value; }} 我们可以像下面这样去调用泛型方法: Pair p1 = new Pair(1, 'apple');Pair p2 = new Pair(2, 'pear');boolean same = https://www.wendangku.net/doc/1a2405671.html,pare(p1, p2); 或者在Java1.7/1.8利用type inference,让Java自动推导出相应的类型参数: Pair p1 = new Pair(1, 'apple');Pair p2 = new Pair(2, 'pear');boolean same = https://www.wendangku.net/doc/1a2405671.html,pare(p1, p2);

JavaEE考试题

一、填空题 1.企业级应用程序通常应具备快速适应性、分布式、高安全性、可扩展性和集成 化等特性。P(6) 2.两层体系结构由客户层和服务器层构成,即所谓的C/S 模式。P(7) 3.三层体系结构通常包括客户层、服务器层和应用服务器层三个层 次。P(7) 4.典型Java EE 应用包括:客户层、表示层(Web层)、业务逻辑层和企业信息 系统层四个层次。P(8) 5.Java EE技术框架大致包括组件技术、服务技术和通信技术三个 部分。P(11) 6.Java EE组件主要包括客户端组件、Web组件和EJB组件三大类。 P(10) 7.按打包粒度从小至大的顺序,Java归档包的类型分别是JAR 、WAR 和 EAR 。(PPT) 8.程序错误可分为语法错、语义错和逻辑错三类。P(20) 9.JSP指令元素主要包括include 、page 和taglib 三个。P(34) 10.include指令的基本语法为<%@ include file=”URL” %> 。P(34) 11.taglib指令的基本语法为<%@ taglib uri=”taglibURI” prefix=”pre” %> 。P(35) 12.JSP参数标记的基本语法为 P(39) 13.读取request单值参数的方法是getParameter() ,读取多值参数的方法是 getParameterValues()。获取所有参数名称的方法是getParameterNames() 。P(44) 14.request作用范围变量可以通过setAttribute() 和getAttribute() 方法设置和读取变量的数据。P(45) 15.调用response对象的addCookie(Cookie cookie)方法可将一个 Cookie对象传回客户端保存。P(48) 16.调用request 对象的getCookies() 方法可以读取保存在客户端的所有 Cookie对象。P(48) 17.在web.xml文件中定义Web应用初始化参数的标记是 和子标记。(源于PPT)

java中的泛型

Java中的泛型 JDK1.5令我们期待很久,可是当他发布的时候却更换版本号为5.0。这说明Java已经有大幅度的变化。本文将讲解JDK5.0支持的新功能-----Java的泛型. 1、Java泛型 其实Java的泛型就是创建一个用类型作为参数的类。就象我们写类的方法一样,方法是这样的method(String str1,String str2 ),方法中参数str1、str2的值是可变的。而泛型也是一样的,这样写class Java_Generics<K,V>,这里边的K和V就象方法中的参数str1和str2,也是可变。下面看看例子: 正确输出:value 这只是个例子(Java中集合框架都泛型化了,这里费了2遍事.),不过看看是不是创建一个用类型作为参数的类,参数是K,V,传入的“值”是String类型。这个类他没有特定的待处理型别,以前我们定义好了一个类,在输入输入参数有所固定,是什么型别的有要求,但是现在编写程序,完全可以不制定参数的类型,具体用的时候来确定,增加了程序的通用性,像是一个模板。 呵呵,类似C++的模板(类似)。 1.1. 泛型通配符 下面我们先看看这些程序:

看看这个方法有没有异议,这个方法会通过编译的,假如你传入String,就是这样List <String>。 接着我们调用它,问题就出现了,我们将一个List<String>当作List传给了方法,JVM会给我们一个警告,说这个破坏了类型安全,因为从List中返回的都是Object类型的,而让我们再看看下面的方法。 因为这里的List<String>不是List<Object>的子类,不是String与Object的关系,就是说List<String>不隶属于list<Object>,他们不是继承关系,所以是不行的,这里的extends是表示限制的。 类型通配符是很神奇的,List<?>这个你能为他做什么呢?怎么都是“?”,它似乎不确定,他总不能返回一个?作为类型的数据吧,是啊他是不会返回一个“?”来问程序员的?JVM会做简单的思考的,看看代码吧,更直观些。 这段代码没问题的,l1.get(0)将返回一个Object。 1.2. 编写泛型类要注意: 1) 在定义一个泛型类的时候,在“<>”之间定义形式类型参数,例如:“class TestGen <K,V>”,其中“K” , “V”不代表值,而是表示类型。 2) 实例化泛型对象的时候,一定要在类名后面指定类型参数的值(类型),一共要有两次书写。例如: TestGen<String,String> t=new TestGen<String,String>();

Java泛型使用详细分析

Java 泛型使用详细分析 、泛型的简介 1、为什么要使用泛型? 一般使用在集合上,比如现在把一个字符串类型的值放入到集合里面,这个时候,这个值放到集合之后,失去本身的类型,只能是object 类型。这时,如果想要对这个值进行类型转换,很容易出现类型转换错误,怎么解决这个问题,可以使用泛型来解决。 2、在泛型里面写是一个对象,String 不能写基本的数据类型比如int, 要写基本的数据类型对应的包装类 、在集合上如何使用泛型 - 常用集合list set map - 泛型语法:集合 比如list // 泛型在list 上的使用 @Test

public void testList() { List list = new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); //for 循环 for (int i = 1;i it = list.iterator(); while (it.hasNext()){ System.out.println(it.next()); } // 泛型在set 上的使用 @Test public void testSet() {

Java泛型实现单链表

学号11710115 天津城建大学 Java 语言程序设计C 实验报告 实验3:泛型实现链表 学生姓名路江飞 班级11卓越七班

一、实验内容 1.掌握使用Java语言进行结构化程序设计; 2.熟悉Java泛型。 3.熟悉Eclipse开发环境,编写简单的Application程序,并编译和执行。 二、实验要求 1.调试程序、编译,运行后得到正确的结果; 2.写出实验报告,要求记录编译和执行Java程序当中的系统错误信息提示,并给出解决办法。 三、实验结果 文件1: package _List; class Node{ E e; Node next; Node(E e){ this.e=e; next=null; } } 文件2: package _List; public class Show { void print(){ System.out.println("*************************************"); System.out.println("* 1.按位查找*"); System.out.println("* 2.按值查找*"); System.out.println("* 3.插入*"); System.out.println("* 4.按位删除*"); System.out.println("* 5.按值删除*"); System.out.println("* 6.修改*"); System.out.println("* 7.遍历*");

System.out.println("* 8.查看链表长度*"); System.out.println("* 9.退出*"); System.out.println("*************************************"); } } 文件3: package _List; import java.util.Scanner; public class List { Node head; List(){ this.head=null; } List(E e[],int n){ //构造函数 this.head=new Node (e[0]); Node r=this.head; for(int i=1;is=new Node (e[i]); r.next=s; r=s; } r.next=null; } void add (E e){//按位置插入 int index,b=1; Scanner input=new Scanner(System.in); for(int j=0;b==1;j++){ System.out.print("请输入插入的位置(第一个数据之前是0号位置,以此类推):");

C++模板函数与Java泛型

C++模板函数 #include "iostream" using namespace std; intint_ab(inta,int b) { returna+a*b; } doubledouble_ab(double a,double b) { returna+a*b; } int main(){ cout<或者template来定义一个任意类型的数据T,定义后的函数必须紧跟着。 #include "iostream" using namespace std; template T1 ab(T1 a,T1 b) { returna+a*b; } int main(){ cout< T1 ab(T1 a,T1 b)

8. Java基础_泛型

泛型 1. 介绍 下面是那种典型用法: List myIntList = new ArrayList();// 1 myIntList.add(new Integer(0));// 2 Integer x = (Integer) myIntList.iterator().next();// 3 第3 行的类型转换有些烦人。通常情况下,程序员知道一个特定的list 里边放的是什么类型的数据。但是,这个类型转换是必须的(essential)。编 译器只能保证iterator 返回的是Object 类型。为了保证对Integer 类型变量赋值的类型安全,必须进行类型转换。 当然,这个类型转换不仅仅带来了混乱,它还可能产生一个运行时错误(run time error),因为程序员可能会犯错。 程序员如何才能明确表示他们的意图,把一个list(集合) 中的内容限制 为一个特定的数据类型呢?这就是generics 背后的核心思想。这是上面程序片断的一个泛型版本: List myIntList = new ArrayList(); // 1 myIntList.add(new Integer(0)); // 2 Integer x = myIntList.iterator().next(); // 3 注意变量myIntList 的类型声明。它指定这不是一个任意的List,而是 一个Integer 的List,写作:List。我们说List 是一个带一个类型参数的泛型接口(a generic interface that takes a type parameter),本 例中,类型参数是Integer。我们在创建这个List 对象的时候也指定了一个类型参数。 另一个需要注意的是第 3 行没了类型转换。 现在,你可能认为我们已经成功地去掉了程序里的混乱。我们用第1 行的类型参数取代了第 3 行的类型转换。然而,这里还有个很大的不同。编译器现在能够在编译时检查程序的正确性。当我们说myIntList 被声明为List类型,这告诉我们无论何时何地使用myIntList 变量,编译器保证其中的元素的正确的类型。 实际结果是,这可以增加可读性和稳定性(robustness),尤其在大型的 程序中。 2. 定义简单的泛型 下面是从java.util包中的List接口和Iterator 接口的定义中摘录的片断:public interface List { void add(E x); Iterator iterator(); } public interface Iterator {

java基础面试知识点

java 基础面试知识点 java 中== 和equals 和hashCode 的区别 int 、char 、long 各占多少字节数 byte 1字节最小值是-128(-2八7); 最大值是127(2八7-1); boolean 至少1 字节这种类型只作为一种标志来记录true/false 情况; short 2 字节最小值是-32768(-2X5); 最大值是32767(2X5 - 1); char 2 字节最小值是\u0000( 即为0);最大值是?(即为65,535); int 4字节最小值是-2,147,483,648(-2^31); 最大值是 2,147,483,647(2^31-1); float 4 字节单精度浮点数字长32 位,尾数长度23 ,指数长度8 ,指数偏移量127; long 8 字节最小值是-9,223,372,036,854,775,808(-2^63); 最大值是9,223,372,036,854,775,807(2^63 -1);

double 8 字节双精度浮点数字长64位,尾数长度52 ,指数长度11,指 数偏移量1023; 英文字母字节数: 1; 编码GB2312 字节数: 1; 编码GBK 字节数: 1; 编码ISO-8859-1 字节数: 1; 编码UTF-8 中文汉字字节数: 2; 编码GB2312 字节数: 2; 编码GBK 字节数: 1; 编码ISO-8859-1 字节数: 3; 编码UTF-8 int 与integer 的区别 Ingeter 是int 的包装类,int 的初值为0,Ingeter 的初值为null; 初始化的时候,int i=1;Integer i=new Integer(1);(要把integer 当做一个

Java泛型的规则和限制

Java泛型的规则和限制 在学习编程的过程中,我觉得不止要获得课本的知识, 更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,更多Java学习,请登陆疯狂java官网。 我们在学习Java的过程中,对Java泛型的理解至关重要。Java中的泛型的本质是参数化类型。也就是说,所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。安全、简单是Java引入泛型的好处 Java工程师介绍,在Java SE 1.5之前,没有泛型的情况的下,通过对类型ObJect的引用来实现参数的“任意化” “任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。 泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。 泛型在使用中的规则和限制 1、泛型的类型参数可以有多个。 2、泛型的参数类型可以使用extends语句,例如。习惯上成为“有界类型”。 3、泛型的参数类型还可以是通配符类型。例如Class classType = Class.forName(https://www.wendangku.net/doc/1a2405671.html,ng.String); 4、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。 5、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。 疯狂Java培训专注软件开发培训,提升学员就业能力,重点提升实践动手能力。技术知识沉淀深厚的老师,让你感受Java的魅力,激发你对于编程的热爱,让你在半年的时间内掌握8-10万的代码量,掌握Java核心技术,成为真正的技术高手;通过大量全真企业项目疯狂训练,迅速积累项目经验。让你成为技能型的现代化高端人才,迅速获得高薪就业!时间不等人,赶紧联系我们吧!

2019年10道关于Java泛型的面试题-word范文 (4页)

本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除! == 本文为word格式,下载后可方便编辑和修改! == 10道关于Java泛型的面试题 1. Java中的泛型是什么 ? 使用泛型的好处是什么? 这是在各种Java泛型面试中,一开场你就会被问到的问题中的一个,主要集中在初级和中级面试中。那些拥有Java1.4或更早版本的开发背景的人都知道,在集合中存储对象并在使用前进行类型转换是多么的不方便。泛型防止了那种 情况的发生。它提供了编译期的类型安全,确保你只能把正确类型的对象放入 集合中,避免了在运行时出现ClassCastException。 2. Java的泛型是如何工作的 ? 什么是类型擦除 ? 这是一道更好的泛型面试题。泛型是通过类型擦除来实现的,编译器在编译时 擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如List在运行时仅用一个List来表示。这样做的目的,是确保能和 Java 5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。根据你对这个泛型问题的回答 情况,你会得到一些后续提问,比如为什么泛型是由类型擦除来实现的或者给你展示一些会导致编译器出错的错误泛型代码。请阅读我的Java中泛型是如何工作的来了解更多信息。 3. 什么是泛型中的限定通配符和非限定通配符 ? 这是另一个非常流行的Java泛型面试题。限定通配符对类型进行了限制。有两种限定通配符,一种是它通过确保类型必须是T的子类来设定类型的上界,另一种是它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另 一方面表示了非限定通配符,因为可以用任意类型来替代。更多信息请参阅我的文章泛型中限定通配符和非限定通配符之间的区别。 4. List和List 之间有什么区别 ? 这和上一个面试题有联系,有时面试官会用这个问题来评估你对泛型的理解, 而不是直接问你什么是限定通配符和非限定通配符。这两个List的声明都是 限定通配符的例子,List可以接受任何继承自T的类型的List,而List可以接受任何T的父类构成的List。例如List

Java1.5泛型指南中文版

Java1.5泛型指南中文版(Java1.5 Generic Tutorial) 1.介绍 JDK1.5中引入了对java语言的多种扩展,泛型(generics)即其中之一。 这个教程的目标是向您介绍java的泛型(generic)。你可能熟悉其他语言的泛型,最著名的是C++的模板(templates)。如果这样,你很快就会看到两者的相似之处和重要差异。如果你不熟悉相似的语法结构,那么更好,你可以从头开始而不需要忘记误解。 Generics允许对类型进行抽象(abstract over types)。最常见的例子是集合类型(Container types),Collection的类树中任意一个即是。 下面是那种典型用法: List myIntList = new ArrayList();// 1 myIntList.add(new Integer(0));// 2 Integer x = (Integer) myIntList.iterator().next();// 3 第3行的类型转换有些烦人。通常情况下,程序员知道一个特定的list里边放的是什么类型的数据。但是,这个类型转换是必须的(essential)。编译器只能保证iter ator返回的是Object类型。为了保证对Integer类型变量赋值的类型安全,必须进行类型转换。 当然,这个类型转换不仅仅带来了混乱,它还可能产生一个运行时错误(run ti me error),因为程序员可能会犯错。 程序员如何才能明确表示他们的意图,把一个list(集合) 中的内容限制为一个特定的数据类型呢?这就是generics背后的核心思想。这是上面程序片断的一个泛型版本: List myIntList = new ArrayList(); // 1 myIntList.add(new Integer(0)); // 2 Integer x = myIntList.iterator().next(); // 3 注意变量myIntList的类型声明。它指定这不是一个任意的List,而是一个Int eger的List,写作:List。我们说List是一个带一个类型参数的泛型接口(a generic interface that takes a type parameter),本例中,类型参数是Integer。我们在创建这个List对象的时候也指定了一个类型参数。

相关文档