`
xiao1zhao2
  • 浏览: 40233 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java中泛型的使用

阅读更多

泛型(Generics)是由编译器来验证从客户端将一种类型传送给某一对象的机制,实现了数据类型的参数化.

 

1.在使用泛型之前,先来看一下没有泛型的java集合框架(Collection)
import java.util.ArrayList;
import java.util.List;

public class GenericsDemo1 {

	private final List list = new ArrayList();

	public void addList() {
		list.add("test");
		list.add(10);
	}

	public void showList() {
		for (Object o : list) {
			System.out.println(((String) o));
		}
	}

	public static void main(String[] args) {
		GenericsDemo g = new GenericsDemo();
		g.addList();
		g.showList();
	}
}

 

此段程序中包含两个方法,addList方法为list中增加了一个String类型和一个int类型;showList方法中,由于Collection在内部用的是Object,我们需要用String进行强制转换,运行时会出现ClassCastException.
在实际开发中,开发这必须用实际类型进行Cast,编译器无法检查,代码在运行时会有抛出ClassCastException的危险.

 

2.使用泛型

 

j2se在1.5为所有的Collection都加入了泛型的声明,例如:

public class ArrayList<E> extends AbstractList<E> {
	public void add(E element) {
	
	}
	public Iterator<E> iterator() {
	
	}
}

 

这里的E是一个类型变量,并没有对它进行具体类型的定义,只是一个类型占位符,由使用者指定类型.通过使用泛型可增加类型安全:
>>在类型没有变化时,Collection是类型安全的;
>>类型的匹配错误在编译期间就可以捕捉到;
>>内在的类型转换优于在外部的人工造型;
>>使接口更加强壮,因为它增加了类型;

使用泛型修改第1节中的程序:

 

import java.util.ArrayList;
import java.util.List;

public class GenericsDemo2 {

	private final List<String> list = new ArrayList<String>();

	public void addList() {
		list.add("test");
		// list.add(10);
	}

	public void showList() {
		for (String o : list) {
			System.out.println(o);
		}
	}

	public static void main(String[] args) {
		GenericsDemo g = new GenericsDemo();
		g.addList();
		g.showList();
	}
}

 

注意,使用泛型后,list.add(10)类型匹配错误,无法通过编译.

 

3.类型通配符

 

 通过泛型可以做到限制类型,那么能否利用'多态'的特性呢?

 

List<Object> list = new ArrayList<String>();

 

如上,定义了一个存储Object类型的List,利用'多态'的特性,创建了一个String类型的ArrayList赋给list.
实际上,这行代码是无法正常编译的,应该使用以下定义方式:

 

List<?> list3 = new ArrayList<String>();

 

其中?表示unknown类型,能与其他类型进行匹配,类似于'父类',称作类型通配符.有以下表现形式:

<E>                    >>    E类型
<? extends E>    >>    继承E的unknown类型
<? super E>       >>    E的unknown父类型
<?>                    >>    unknown类型

下面通过一个例子来了解这几种通配符:

 

import java.util.ArrayList;
import java.util.List;

public class GenericsDemo3 {

	public void a() {
		List<Object> list = new ArrayList<>();
		list.add(new Object());
		list.add("a");
		list.add(97);
		list.add(null);
	}

	public void b() {
		List<? extends Object> list = new ArrayList<String>();
		// list.add(new Object());
		// list.add("b");
		// list.add(98);
		list.add(null);
	}

	public void c() {
		List<? super String> list = new ArrayList<>();
		// list.add(new Object());
		list.add("c");
		// list.add(99);
		list.add(null);
	}

	public void d() {
		List<?> list = new ArrayList<>();
		// list.add(new Object());
		// list.add("d");
		// list.add(100);
		list.add(null);
	}
}

 

此段程序包含的四个方法中,
在a方法中,泛型类型确定为Object,可成功添加四个元素;
在b方法中,list的定义是没问题的,但list.add("b")却无法通过编译,可知list内存储的数据类型的编译类型是unknown的,因此无法添加一个String.
在c方法中,定义了一个存储String的父类的list,但list.add(new Object())却无法通过编译,而list.addd("c")却能执行通过,由此可见此时<? super String>与<String>作用相同.
在d方法中,由于?是unknown类型,所以Object,String,Integer都是无法被添加的.
由于null是所有类的对象,所以上述四个方法中的list.add(null)都是可以成功执行的.

 

4.自定义泛型<T>

 

在编程过程中,通过<T>表示一个类型,具体类型由使用者提供,如:Map<K,V>{},推荐的命名:

K  >>  key,map的键
V  >>  value,list和set的内容,map的值
E  >>  异常类
T  >>  泛型

例:

 

public class GenericsDemo4 {

	public static <T extends Comparable<T>> T max(T t1, T t2) {
		if (t1.compareTo(t2) > 0) {
			return t1;
		}
		return t2;
	}

	public static void main(String[] args) {
		System.out.println(max(98, 97));
		System.out.println(max("a", "b"));
		// System.out.println(max(97, "b"));
	}
}

 

此段程序在max方法中定义了一个泛型T,T实现了Comparable接口(不能用implements,只能用extends),Comparable比较的类型又是T,同时也将T作为参数和返回值.
在main方法中调用了3次max,只有前两次能够编译并执行,在第三次调用max(97,"b")时,传入的参数分别是Integer和String,编译器无法判断返回值的类型,无法完成编译.
执行后输出结果:  
98
b

另外注意,定义的<T>可以同时继承类和实现接口,用&连接,上述的max方法也可如下定义:

 

	public static <T extends Object & Comparable<T>> T max(T t1, T t2) {
		if (t1.compareTo(t2) > 0) {
			return t1;
		}
		return t2;
	}

 

5.小结

 

泛型(Generics),实现类数据类型的参数化,通过使用泛型,对数据类型自动检查,避免了类型转换,增加了程序的安全性.

2
0
分享到:
评论

相关推荐

    Java 实现泛型List

    Java 实现泛型List的源码,基本实现了List接口的全部所有方法。欢迎大家发表自己的观点和建议。

    Java中的泛型简析实战.zip

    Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战...

    2.java定义泛型类.zip

    2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip...

    Java中泛型的各种使用

    泛型是Java SE 5.0引入的新特性,它允许在类、接口和方法中使用类型参数。类型参数类似于函数参数,但它们代表的是类型而不是值。例如,`List&lt;T&gt;`中的`T`就是一个类型参数,`T`代表某种具体的类型,如`String`、`...

    关于C#、java泛型的看法

    在Java中,泛型同样使用尖括号表示,但它的类型擦除特性使得编译后的字节码并不包含类型参数信息,而是使用Object或其他基础类型作为替代。这意味着Java的泛型不支持协变和逆变,但可以通过通配符(如?)来放宽类型...

    java 泛型方法使用示例

    下面我们将深入探讨Java泛型方法的概念、语法以及使用示例。 **一、泛型方法概念** 泛型方法是一种具有类型参数的方法,这些类型参数可以在方法声明时指定,并在方法体内部使用。与类的泛型类似,它们提供了编译时...

    Java1.5泛型指南中文版

    感谢所有为Java泛型做出贡献的人们,包括设计者、实现者以及提供反馈和支持的社区成员。泛型是Java语言的一个重要特性,极大地提高了代码的质量和可维护性。 以上就是基于给定文件信息对Java 1.5泛型指南的主要知识...

    Java泛型使用详细分析.pdf

    在本文中,我们将详细介绍 Java 泛型的使用方法和实现原理。 一、泛型的简介 泛型是 Java 5 中引入的一种语言特性,旨在解决类型安全问题。在 Java 中,泛型可以应用于集合、类、接口和方法中。泛型的主要目的是...

    java 泛型类的类型识别示例

    4. **利用`Class&lt;T&gt;`作为泛型约束**:有时候,我们可以在泛型类中使用`Class&lt;T&gt;`作为参数或字段,这样可以在运行时获取类型信息。例如: ```java public class MyClass&lt;T&gt; { private final Class&lt;T&gt; clazz; ...

    java5泛型新特性 pdf

    2. **通配符**:泛型中使用通配符可以增加类型参数的灵活性。例如,`?`表示任何类型,`? extends Number`则限制为Number或其子类。这在处理多种类型的集合时非常有用,如方法参数的定义。 3. **类型擦除**:由于...

    JAVA泛型加减乘除

    这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...

    JAVA-泛型课件-泛型课件

    泛型接口允许在接口声明中使用类型参数,实现此接口的类或接口必须提供具体的类型。 ### 泛型的优势 引入泛型的主要目的是在编译时提供更严格的类型检查,并且减少强制类型转换的需要。使用泛型后,在集合操作中...

    Java泛型的用法及T.class的获取过程解析

    Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析。 一、泛型的基本概念 泛型是Java 5中...

    java 一个关于泛型的简单例子

    泛型允许我们在类、接口和方法中使用类型参数,这样我们可以在编译时检查类型,避免了运行时类型转换的麻烦和潜在的ClassCastException风险。 在Java中,泛型的主要目的是为了实现参数化类型,这意味着我们可以创建...

    Java反射泛型,实现数据库的动态增删改查等功能

    Java反射和泛型是两种强大的编程特性,它们在开发中有着广泛的应用,特别是在数据库操作的动态化场景下。本文将详细介绍如何结合这两种技术实现在Java中对MySQL、SQL Server或Oracle数据库进行动态的增删改查操作。 ...

    Java泛型应用实例

    类型参数是在类或方法声明中使用的占位符,用来表示任意类型。例如,`List&lt;T&gt;` 中的 `T` 就是一个类型参数。类型边界则限制了类型参数的范围,如 `class Box&lt;T extends Number&gt;` 表示 `T` 必须是 `Number` 或其子类...

Global site tag (gtag.js) - Google Analytics