1

2

3

4

5

public class Box {

private String boxname;

public void set(String boxname) { this.boxname = boxname; }

public String get() { return boxname; }

}

1

2

3

4

5

6

public class Box<T> {

// T stands for "Type"

private T t;

public void set(T t) { this.t = t; }

public T get() { return t; }

}

1

2

3

Box<Integer> integerBox = new Box<Integer>();

Box<Double> doubleBox = new Box<Double>();

Box<String> stringBox = new Box<String>();

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public class Util {

public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {

return p1.getKey().equals(p2.getKey()) &&

p1.getValue().equals(p2.getValue());

}

}

public class Pair<K, V> {

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; }

}

1

2

3

Pair<Integer, String> p1 = new Pair<>(1, "apple");

Pair<Integer, String> p2 = new Pair<>(2, "pear");

boolean same = Util.<Integer, String>compare(p1, p2);

1

2

3

Pair<Integer, String> p1 = new Pair<>(1, "apple");

Pair<Integer, String> p2 = new Pair<>(2, "pear");

boolean same = Util.compare(p1, p2);

1

2

3

4

5

6

7

public static <T> int countGreaterThan(T[] anArray, T elem) {

int count = 0;

for (T e : anArray)

if (e > elem)  // compiler error

++count;

return count;

}

>，所以编译器报错，那怎么解决这个问题呢？答案是使用边界符。

1

2

3

public interface Comparable<T> {

public int compareTo(T o);

}

1

2

3

4

5

6

7

public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T
elem) {

int count = 0;

for (T e : anArray)

if (e.compareTo(elem) > 0)

++count;

return count;

}

1

<T extends Object&Comparable&Serializable>

1

public void boxTest(Box<Number> n) { /* ... */ }

1

2

3

class Fruit {}

class Apple extends Fruit {}

class Orange extends Fruit {}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

static List<Apple> apples = Arrays.asList(new Apple());

static List<Fruit> fruit = Arrays.asList(new Fruit());

return list.get(0);

}

}

static void f1() {

// Errors: List<Fruit> cannot be applied to List<Apple>.

}

public static void main(String[] args) {

f1();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

T readCovariant(List<? extends T> list) {

return list.get(0);

}

}

static void f2() {

}

public static void main(String[] args) {

f2();

}

PECS原则

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public class GenericsAndCovariance {

public static void main(String[] args) {

// Wildcards allow covariance:

List<? extends Fruit> flist = new ArrayList<Apple>();

// Compile Error: can't add any type of object:

// We Know that it returns at least Fruit:

Fruit f = flist.get(0);

}

}

1

2

3

List<? extends Fruit> flist = new ArrayList<Fruit>();

List<? extends Fruit> flist = new ArrayList<Apple>();

List<? extends Fruit> flist = new ArrayList<Orange>();

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public class GenericWriting {

static List<Apple> apples = new ArrayList<Apple>();

static List<Fruit> fruit = new ArrayList<Fruit>();

static <T> void writeExact(List<T> list, T item) {

}

static void f1() {

writeExact(apples, new Apple());

writeExact(fruit, new Apple());

}

static <T> void writeWithWildcard(List<? super T> list, T item) {

}

static void f2() {

writeWithWildcard(apples, new Apple());

writeWithWildcard(fruit, new Apple());

}

public static void main(String[] args) {

f1(); f2();

}

}

super Apple> list，它可以有下面几种含义：

1

2

3

List<? super Apple> list = new ArrayList<Apple>();

List<? super Apple> list = new ArrayList<Fruit>();

List<? super Apple> list = new ArrayList<Object>();

* “Producer Extends” – 如果你需要一个只读List，用它来produce T，那么使用? extends T。
* “Consumer Super” – 如果你需要一个只写List，用它来consume T，那么使用? super T。
* 如果需要同时读取以及写入，那么我们就不能使用通配符了。

1

2

3

4

5

6

public class Collections {

public static <T> void copy(List<? super T> dest, List<? extends T> src) {

for (int i=0; i<src.size(); i++)

dest.set(i, src.get(i));

}

}

* 在Java中不允许创建泛型数组
* 无法对泛型代码直接使用instanceof关键字
* 利用类型参数创建实例的做法编译器不会通过：

1

2

3

4

public static <E> void append(List<E> list) {

E elem = new E();  // compile-time error

}

1

2

3

4

public static <E> void append(List<E> list, Class<E> cls) throws Exception {

E elem = cls.newInstance();   // OK

}