在之前学过的集合框架中,List和Map都使用了泛型技术来确认其内容的数据类型。
如果不使用泛型,在程序运行阶段,会带来数据类型转型的错误风险。
List<String> list = new ArrayList<String>();list.add("tom");for (int i = 0; i < list.size(); i++) {String obj = list.get(i);System.out.println(obj);}List list2 = new ArrayList();list2.add("helen");list2.add(2); // 自动装箱成Integerlist2.add(true); // 自动装箱成Booleanfor (int i = 0; i < list2.size(); i++) {String obj = (String)list2.get(i); // 此处是有风险的}
在Java中,使用变量之前,必须要先定义变量的数据类型,存在一种特殊的现象,就是多态(数据类型是父类,实现对象是子类),变量赋值不一定要完全和数据类型一致,可以赋予子类对象给它。
public class Client2 {public static void main(String[] args) {Point point = new Point();point.x = "东经102°";point.y = "北纬32°";point.x = 102;point.y = 32;String s = (String) point.x;point.print();}}class Point {Object x;Object y;public void print() {System.out.println(x + "" + y);}}
向下转型会带来数据风险的(ClassCastException)
不使用泛型的缺点:需要强制转换;可向集合中添加任意类型的对象,存在风险
泛型的使用:在接口/类名后的尖括号内加上类型,如 List list=new ArrayList();同时,变量声明时的泛型类和其实现类时的泛型类必须相同,即“=”前后的尖括号中的类型需要一致
class Animal{}class Cat extends Animal {}List<Animal> list = new ArrayList<Cat>();这样是不允许的。变量声明的类型必须匹配传递给实际对象的类型
泛型作为方法参数
泛型作为方法参数
案例: 定义一个抽象类Goods,包含抽象方法sell(); 分别定义各类商品Book,Clothes和Shoes继承Goods,并实现sell()方法,输出一句话,如sell books 定义一个商品销售类GoodsSeller,模拟销售,包括方法:public void sellGoods(List goods),循环调用list对象的sell() 方法
public abstract class Goods {public abstract void sells();}public class Books extends Goods{@Overridepublic void sells() {System.out.println("sell books");}}public class Clothes extends Goods {@Overridepublic void sells() {System.out.println("sell clothes");}}public class Shoes extends Goods {@Overridepublic void sells() {System.out.println("sell shoes");}}public class GoodsSeller {//代表只要goods参数保存的元素是Goods或者Goods的子类,都可以public void sellGoods(List<? extends Goods> goods) {//调用集合中的sell方法for(int i = 0; i < goods.size(); i++) {Goods g = goods.get(i);g.sells();}}}public class Test {public static void main(String[] args) {//定义books相关的listList<Books> bookLst = new ArrayList<Books>();bookLst.add(new Books());bookLst.add(new Books());//定义Shoes相关的listList<Shoes> shoesLst = new ArrayList<Shoes>();shoesLst.add(new Shoes());shoesLst.add(new Shoes());//定义Clothes相关的listList<Clothes> clothesLst = new ArrayList<Clothes>();clothesLst.add(new Clothes());clothesLst.add(new Clothes());GoodsSeller gdSeller = new GoodsSeller();gdSeller.sellGoods(bookLst);}}
自定义泛型类
public class Demo {public static void main(String[] args) {Point<Integer, Integer> p = new Point<Integer, Integer>();p3.x = 1;p3.x = 2;}}public class Point<T1, T2> {T1 x;T2 y;}
类的泛型在className之后定义,只有定义的泛型类型才能在类中使用。
即我们定义只有先定义类名后的泛型标志符的时候,才能使该泛型类使用泛型定义方法和成员变量。
自定义泛型方法
泛型方法不一定要写在泛型类中
/*** 定义泛型方法**/public class GenericMethod {//定义泛型方法的时候需要将泛型放在访问修饰符和返回值中间public <T extends Number> void print(T t) {System.out.println(t.toString());}public static void main(String[] args) {GenericMethod gm = new GenericMethod();//可以通过泛型方法实现一个方法传递不同的参数//gm.print("123");规定泛型的继承限定之后,该行语句就是错误的了gm.print(123);gm.print(123f);}}
泛型一般使用于框架设计,在实际的应用开发中较少运行
Java泛型中的标记符含义:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型<K,V>就是代表键值对的泛型
