Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
在Class中应用
传统实现方法
1 2 3 4 5 6 7 8 9 10 11
| public class StringPrinter { String content; public StringPrinter(String content) { this.content = content; } public void print() { System.out.println(content); } }
|
1 2 3 4 5 6 7 8 9 10 11
| public class IntegerPrinter { Integer content; IntegerPrinter(Integer content) { this.content = content; } public void print() { System.out.println(content); } }
|
我们测试下这两个类
1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void testStringPrinter(){ StringPrinter printer = new StringPrinter("Hello World"); printer.print(); } @Test public void testIntegerPrinter(){ IntegerPrinter printer = new IntegerPrinter(123); printer.print(); }
|
上面的例子是我们传统思维的解决方法,下面使用泛型来重构代码
1 2 3 4 5 6 7 8 9 10 11
| public class Printer<T> { T content; Printer(T content) { this.content = content; } public void print() { System.out.println(content); } }
|
1 2 3 4 5 6 7 8 9 10 11
| @Test public void testStringGenericsPrinter(){ Printer<String> printer = new Printer<>("Hello World"); printer.print(); } @Test public void testIntegerGenericsPrinter(){ Printer<Integer> printer = new Printer<>(123); printer.print(); }
|
T占位符号可以是任何字符,也可以传入多个
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Printer<T, K> { T content; K content2; public Printer(T content, K content2) { this.content = content; this.content2 = content2; } public void print() { System.out.println(content); System.out.println(content2); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void testStringGenericsPrinter() { Printer<String, Integer> printer = new Printer<>("Hello World", 123); printer.print(); }
@Test public void testIntegerGenericsPrinter() { Printer<Integer, Integer> printer = new Printer<>(123, 456); printer.print(); }
|
我们也可以对泛型进行一些约束(bounded generics),比如规定传入的泛型类型必须是某一个类型的子类型
1 2 3 4 5 6 7 8 9 10 11
| public class Printer<T extends Vehicle> { T content; public Printer(T content) { this.content = content; } public void print() { System.out.println(content); } }
|
1 2 3 4 5 6 7 8 9 10 11
| @Test public void testCarGenericsPrinter() { Printer<Car> printer = new Printer<>(new Car(290000, "Model X")); printer.print(); } @Test public void testBusGenericsPrinter() { Printer<Bus> printer = new Printer<>(new Bus(35)); printer.print(); }
|
同时我们可以在约束继承类的同时,可以同样加入到接口实现的约束,但是要注意先后顺序,继承类在前,接口在后
1 2 3 4 5 6 7 8 9 10 11 12
| public class Printer<T extends Vehicle & Thing> { T content; public Printer(T content) { this.content = content; } public void print() { System.out.println(content); } }
|
Method 中的应用
1 2 3 4 5 6 7 8 9 10
| public static <T> void print(T content) { System.out.println(content); } public static void main(String[] args) { print("Hello World"); print(1234567); print(12L); print(new Car(150000,"X5")); }
|
1 2 3 4 5 6 7 8 9 10
| public static <T extends Vehicle & Thing> void print(T content ) { System.out.println(content); }
public static <T,K> void print(T content, K content2) { System.out.println(content); System.out.println(content2); }
|
在List中我们可以使用通配符(wildcard)来处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static void print(List<?> list) { System.out.println(list); } public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); list.add(123); list.add(456); print(list); ArrayList<String> list2 = new ArrayList<>(); list2.add("Hello"); list2.add("World"); print(list2); }
|
通配符的使用场景下我们同样可以引入约束
1 2 3 4 5 6 7 8 9 10 11
| public static void print(List<? extends Vehicle> list) { System.out.println(list); } public static void main(String[] args) { ArrayList<Car> list = new ArrayList<>(); list.add(new Car(300000,"320")); list.add(new Car(700000,"750")); print(list); }
|
1 2 3 4 5
| public static void print(List<? super Vehicle> list) { System.out.println(list); }
|
1 2 3 4 5 6
| 备注:博文涉及到的英文单次小结: Generics Wildcard {} Curly Braces <> Angle Brackets ? Question Mark
|