java核心卷轴之泛型程序设计

  本文根据《Java核心卷轴》第十二章总结而来,更加详细的内容请查看《Java核心卷轴》

1. 泛型类型只能是引用类型,不可以使用基本数据类型。

2. 类型变量含义

   E : 集合    K : 关键字    V : 值      T : 任意类型

3. 泛型类

  3.1  注意事项

    类型变量声明放在类名的后面

  3.2 示例

package com.BlueStarWei.generic;

public class Pair<T> {

    private T first;
private T second; public Pair(T first, T second) {
this.first = first;
this.second = second;
} public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
}

4. 泛型方法

  4.1 注意事项

    类型变量放在修饰符的后面,返回类型的前面

  4.2 示例

package com.BlueStarWei.generic;

public class GenericMethodDemo{
public static void main(String[] args) {
String s = getMiddle("Hello","world","Happy");
System.out.println(s);//World
} //T... 表示可以输入任意个数的参数
public static <T> T getMiddle(T... a){
return a[a.length / 2];
}
}

5. 类型变量的限定<T extends BoundingType>

  5.1 T应该是绑定类型的子类型。T和绑定类型可以是类,也可以是接口。

  5.2 一个类型变量可以有多个限定;如: T extends Comparable &  Serializable

  5.3 示例

package com.BlueStarWei.generic;

public class BoundingTypeDemo {
public static void main(String[] args) {
Integer[] a = new Integer[]{1,2,3,4};
int max = getMax(a);
System.out.println(max); } public static <T extends Comparable<T>> T getMax(T[] a){
if(a == null || a.length == 0) return null;
T max = a[0];
for (int i = 0; i < a.length; i++) {
if(max.compareTo(a[i]) < 0){
max = a[i];
}
}
return max;
} }

6. 运行时类型检查只适用于原始类型

  6.1 校验情况

if(a instanceof Pair<String>) //编译报错
if(a instanceof Pair<T>) //编译报错
if(a instanceof Pair) //true

  6.2 getClass返回的是原始类型

Pair<String> a = new Pair<String>("Hello", "World");
Pair<Integer> b = new Pair<Integer>(1,2);
if(a.getClass().equals(b.getClass())){
System.out.println("true");
//class com.ebao.gs.pol.nb.test.Pair
System.out.println(a.getClass());
}else{
System.out.println("false");
}

7. Java不支持泛型类型的数组

  7.1 示例

Pair<String>[] as = new Pair<String>[10]; //编译报错

  7.2 解决方案: 将参数化对象放入ArrayList

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

8. 通配符的限定

  8.1 子类型限定

    8.1.1 Pair<? Extends Employee>不能调用setFirst方法,但是可以调用getFirst方法

? extends Employee  getFirst()
void setFirst(? extends Employee)

   调用setFirst方法时,编译器只知道需要某个Employee的子类型,但是不知道具体什么类型。它拒绝传递任何特定类型(?不能用来匹配)。调用getFirst方法时,只是将getFirst的返回值赋值给一个Employee的引用,完全合法。

    8.1.2 示例

public static void minMaxBonus(Manager[] manager, Pair<?
extends Manager> result) {
if(manager.length == 0 || manager == null) return;
Manager minManager = manager[0];
Manager maxManager = manager[0];
for (int i = 0; i < manager.length; i++) {
if(manager[i].getBonus() < minManager.getBonus())
minManager = manager[i];
if(manager[i].getBonus() > maxManager.getBonus())
maxManager = manager[i];
}
result.setFirst(minManager);//编译报错
result.setSecond(maxManager);//编译报错
Manager m = (Manager)result.getFirst();
System.out.println(m.getBonus());

  8.2 超类型限定

    8.2.1 Pair<? super Manager>可以调用setFirst方法,但是调用getFirst方法会返回Object对象(可以类型强转)

void setFirst(? super Manager)
? super Manager getFirst()

  编译器不知道setFirst方法的确切类型,但是可以用任意Manager对象(或子类型)调用它。然而,如果调用getFirst方法,返回的对象类型就得不到保证。只能把它赋值给一个Object(但是可以类型强制转换)。

    8.2.2 示例

public static void minMaxBonus(Manager[] manager, Pair<?
super Manager> result) {
  if(manager.length == 0 || manager == null) return;
  Manager minManager = manager[0];
  Manager maxManager = manager[0];
  for (int i = 0; i < manager.length; i++) {
  if(manager[i].getBonus() < minManager.getBonus())
  minManager = manager[i];
  if(manager[i].getBonus() > maxManager.getBonus())
  maxManager = manager[i];
    }
  result.setFirst(minManager);
  result.setSecond(maxManager);
  Manager m = (Manager)result.getFirst();
  System.out.println(m.getBonus()); }

  8.3 总结

    通常而言:带有超类型限定的通配符可以向泛型对象中写入,带有子类型限定的通配符可以从泛型对象中读取。

  8.4 附表(Manager类)

package com.ebao.gs.pol.nb.test;

public class Manager {
private Long id;
private String name;
private Double bonus; public Manager(Long id, String name, Double bonus){
super();
this.id = id;
this.name = name;
this.bonus = bonus;
} public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getBonus() {
return bonus;
}
public void setBonus(Double bonus) {
this.bonus = bonus;
} }

9.泛型的意义

  减少强制类型转换的使用

更多内容,请关注:http://www.cnblogs.com/BlueStarWei/

上一篇:Ubuntu安装微信开发者工具


下一篇:MySQL中函数、游标、事件、视图