泛型概述
泛型的意义
在Java中增加泛型之前,泛型程序设计使用继承来实现的。这种方式有以下坏处,而使用泛型不存在这些坏处。
坏处1:需要强制转换
坏处2:可向集合中添加任意类型的对象,存在风险
具体例子参见上一篇文章:Java集合 => 在HashSet中操作自定义对象
泛型的使用
- List
list = new ArrayList (); - Java SE7及以后的版本中,构造方法中可以省略泛型类型。
即:List
多态与泛型
变量声明的类型必须匹配传递给实际对象的类型
class Animal{}class Cat extends Animal{}List<Animal> list = new ArrayList<Cat> (); // 错误List<Object> list = new ArrayList<String> (); // 错误List<Number> list = new ArrayList<Integer> (); // 错误
泛型作为方法参数
Book.java
package com.generic;public class Book extends Goods {@Overridepublic void sell() {// TODO Auto-generated method stubSystem.out.println("sell books");}}
Clothes.java
package com.generic;public class Clothes extends Goods {@Overridepublic void sell() {// TODO Auto-generated method stubSystem.out.println("sell clothes");}}
—-Version1.0:———————————————————————————————————————————————————
在这个版本中,我们可以看到GoodsTest.java中的goodsSeller.sellGoods(books);是会报错的。原因就在与,sellGoods方法在定义的时候,接受的泛型是Goods类,但是实际传递过来的缺失Book类,所以类型不匹配导致编译报错。怎么解决这个编译报错呢?请看Version2.0
GoodsSeller.java
package com.generic;import java.util.List;public class GoodsSeller {public void sellGoods(List<Goods> goods) {// 调用集合中的sell方法for (Goods good : goods) {good.sell();}}}
GoodsTest.java
package com.generic;import java.util.ArrayList;import java.util.List;public class GoodsTest {public static void main(String[] args) {// 定义book相关的ListList<Book> books = new ArrayList<Book>();books.add(new Book());books.add(new Book());// 定义clothes相关的ListList<Clothes> clothes = new ArrayList<Clothes>();clothes.add(new Clothes());clothes.add(new Clothes());GoodsSeller goodsSeller = new GoodsSeller();goodsSeller.sellGoods(books); // 报错}}
—-Version2.0:———————————————————————————————————————————————————
为了解决Version1.0中的编译报错问题,我们可以用都用Goods类实例化books对象和clothes对象。
但是这样的话,无法区分Book类对象和Clothes类对象,泛型的意义就不大了。有没有办法既可以解决编译报错,有能保留泛型呢?请看Version3.0
GoodsSeller.java
package com.generic;import java.util.List;public class GoodsSeller {public void sellGoods(List<Goods> goods) {// 调用集合中的sell方法for (Goods good : goods) {good.sell();}}}
GoodsTest.java
package com.generic;import java.util.ArrayList;import java.util.List;public class GoodsTest {public static void main(String[] args) {// 定义book相关的ListList<Goods> books = new ArrayList<Goods>();books.add(new Book());books.add(new Book());// 定义clothes相关的ListList<Goods> clothes = new ArrayList<Goods>();clothes.add(new Clothes());clothes.add(new Clothes());GoodsSeller goodsSeller = new GoodsSeller();goodsSeller.sellGoods(books);goodsSeller.sellGoods(clothes);}}
sell books
sell books
sell clothes
sell clothes
—-Version3.0:———————————————————————————————————————————————————
注意sellGoods方法中的参数设置,(List<? extends Goods> goods),这就是泛型作为参数的好处
GoodsSeller.java
package com.generi;import java.util.List;public class GoodsSeller {public void sellGoods(List<? extends Goods> goods) {// 调用集合中的sell方法for (Goods good : goods) {good.sell();}}}
GoodsTest.java
package com.generic;import java.util.ArrayList;import java.util.List;public class GoodsTest {public static void main(String[] args) {// 定义book相关的ListList<Book> books = new ArrayList<Book>();books.add(new Book());books.add(new Book());// 定义clothes相关的ListList<Clothes> clothes = new ArrayList<Clothes>();clothes.add(new Clothes());clothes.add(new Clothes());GoodsSeller goodsSeller = new GoodsSeller();goodsSeller.sellGoods(books);goodsSeller.sellGoods(clothes);}}
sell books
sell books
sell clothes
sell clothes
自定义泛型类
package com.generic;public class NumGeneric<T> {private T num;public T getNum() {return num;}public void setNum(T num) {this.num = num;}public static void main(String[] args) {NumGeneric<Integer> intNum = new NumGeneric<>();intNum.setNum(10);System.out.println("Integer:"+intNum.getNum());NumGeneric<Float> floatNum = new NumGeneric<>();floatNum.setNum(5.0f);System.out.println("Float:"+floatNum.getNum());}}
Integer:10
Float:5.0
package com.generic;public class NumGeneric<T,X> {private T num1;private X num2;public void genNum(T num1, X num2) {this.num1 = num1;this.num2 = num2;}public T getNum1() {return num1;}public void setNum1(T num1) {this.num1 = num1;}public X getNum2() {return num2;}public void setNum2(X num2) {this.num2 = num2;}public static void main(String[] args) {NumGeneric<Integer,Float> numObj = new NumGeneric<> ();numObj.genNum(25, 5.0f);System.out.println("num1="+numObj.getNum1());System.out.println("num2="+numObj.getNum2());}}
num1=25
num2=5.0
自定义泛型方法
泛型方法不一定要写在泛型类里面
package com.generic;public class GenericMethod {public <T> void printValue(T t) {System.out.println(t);}public static void main(String[] args) {GenericMethod gm = new GenericMethod();gm.printValue("hello");gm.printValue(123);gm.printValue(5.0f);}}
hello
123
5.0
package com.generic;public class GenericMethod {public <T extends Number> void printValue(T t) {System.out.println(t);}public static void main(String[] args) {GenericMethod gm = new GenericMethod();gm.printValue("hello"); // 出错,因为是继承自Number类的泛型gm.printValue(123);gm.printValue(5.0f);}}
