您的位置:首页 > 编程语言 > Java开发

Java泛型

2016-04-07 17:07 387 查看

Java泛型

泛型介绍

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

假定我们有这样一个需求:写一个排序方法,能够对整形数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?

答案是可以使用 Java 泛型。

使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整型数组、浮点数数组、字符串数组等进行排序。

泛型方法

你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
下面是定义泛型方法的规则:

· 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的<E>)。
· 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
· 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
· 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。

泛型作用

提高了程序的安全性
将运行期遇到的问题转移到了编译期
省去了类型强转的麻烦
泛型类的出现优化了程序设计
泛型在集合中得到了广泛应用

泛型类

单参数:

public class Genericity<T> {
private T t;

//空参构造函数
public Genericity() {

}
//带有T类型参数的构造函数
public Genericity(T t) {
this.t = t;
}
//打印
public void print(T t){
System.out.println(t);
}

public static void main(String[] args) {
//打印Integer类型
Genericity<Integer> intGen = new Genericity<Integer>();
intGen.print(360);

//打印String类型
Genericity<String> strGen = new Genericity<String>();
strGen.print("Hello World");
}
}


多参数:

public class Genericity<T,V> {

//空参构造函数
public Genericity() {

}

//打印
public void print(T t, V v){
System.out.println(t + " : " + v);
}

public static void main(String[] args) {
//打印<Integer,String>类型
Genericity<Integer,String> intGen = new Genericity<Integer,String>();
intGen.print(360,"Hello World");
}
}


泛型接口

//泛型接口
interface InterfaceGen<T> {
T getT();
void setT(T t);
}

public class Genericity implements InterfaceGen<Integer> {

private Integer t;
//空参构造函数
public Genericity() {

}
//获取值
public Integer getT(){
return t;
}
//设置t的值
public void setT(Integer t) {
this.t = t;
}

public static void main(String[] args) {
Genericity gen = new Genericity();
gen.setT(18);
System.out.println(gen.getT());
}
}


类型通配符

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

public class Genericity  {
public static void main(String[] args) {
ArrayList<Worker> workers = new ArrayList<>();
workers.add(new Worker("zhangsan", 18));
workers.add(new Worker("lisi", 22));
workers.add(new Worker("wangwu", 31));
printList(workers);

ArrayList<Integer> integers = new ArrayList<>();
integers.add(3);
integers.add(9);
integers.add(81);
printList(integers);
}

public static void printList(List<?> list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}

class Worker {
String name;
int age;

public Worker(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "Worker{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}

打印结果:
Worker{name='zhangsan', age=18}

Worker{name='lisi', age=22}

Worker{name='wangwu', age=31}

3

9

81


泛型方法

/**
* 在我们类中方法上定义泛型
* 1、如果类上面定义了泛型,可以直接使用类上面定义的泛型
* 2、如果方法有返回值,而且返回值不确定是什么类型,我们也可以使用泛型来作为方法的返回值
* 返回值的类型不一定和我们类上面的泛型一直
* 3、如果方法是静态方法的时候,那么就需要在static和返回值中间指定要使用的泛型
* 我们发现,泛型也是有局限性的:一旦指定类上的泛型之后,在方法调用的时候就只能使用指定类型
*
* @param <T>
*/
class Tool<T> {

public void print(T t) {
System.out.println("print :" + t);
}

/**
* 方法的泛型,避免了和类上面定义的泛型的一致,做到了调用的灵活性
*
* @param <E>
* @param e
*/
public <E> void show(E e) {
System.out.println("show :" + e);
}

/**
* 定义了有返回值的方向方法
*
* @param <E>
* @param e
* @return
*/
public <E> E show1(E e) {
return e;
}

/**
* 如何在没有返回值的静态方法上定义泛型
*
* @param <T>
* @param t
*/
public static <T> void show2(T t) {
System.out.println("show2 :" + t);
}

/**
* 如何在静态有返回值的方法上定义泛型
*
* @param <T>
* @param t
* @return
*/
public static <T> T show3(T t) {
return t;
}
}


类型通配符限定

向上限定

? extends E:接收E类型或者E的子类型
程序示例:
/**
* 在我们类中方法上定义泛型
* 1、如果类上面定义了泛型,可以直接使用类上面定义的泛型
* 2、如果方法有返回值,而且返回值不确定是什么类型,我们也可以使用泛型来作为方法的返回值
* 返回值的类型不一定和我们类上面的泛型一直
* 3、如果方法是静态方法的时候,那么就需要在static和返回值中间指定要使用的泛型
* 我们发现,泛型也是有局限性的:一旦指定类上的泛型之后,在方法调用的时候就只能使用指定类型
*
* @param <T>
*/
class Tool<T> {

public void print(T t) {
System.out.println("print :" + t);
}

/**
* 方法的泛型,避免了和类上面定义的泛型的一致,做到了调用的灵活性
*
* @param <E>
* @param e
*/
public <E> void show(E e) {
System.out.println("show :" + e);
}

/**
* 定义了有返回值的方向方法
*
* @param <E>
* @param e
* @return
*/
public <E> E show1(E e) {
return e;
}

/**
* 如何在没有返回值的静态方法上定义泛型
*
* @param <T>
* @param t
*/
public static <T> void show2(T t) {
System.out.println("show2 :" + t);
}

/**
* 如何在静态有返回值的方法上定义泛型
*
* @param <T>
* @param t
* @return
*/
public static <T> T show3(T t) {
return t;
}
}


向下限定

? super E:接收E类型或E的超(父|基)类
//使用上例的Animal和Dog类
public class Genericity {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Animal());
animals.add(new Animal());
sop(animals);
}

//这里使用了泛型中类型通配符的向下限定 :? 对应的类型必须为Dog类或Dog的父类
public static void sop(List<? super Dog> list){
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: