总体内容
1.什么是泛型
2.使用泛型
|--集合框架中的泛型
|--泛型的向后兼容性
3.泛型进阶
|--类型参数 定义自己的泛型类
|--类型通配符
|--泛型方法
|--受限制的类型参数
一、什么是泛型
泛型的实质就是将原本确定不变的数据类型参数化,作为对原有类型体系的扩充 泛型可以提高Java程序类型的安全性,可维护性和可靠性
二、使用泛型
|-- 集合框架中泛型的使用
一般而言,再向一个集合中添加元素时,都会添加同一种元素,而集合容器会将添加的每个元素作为 Object来处理。这样可以保证在从集合中取出元素时都是同一种元素.因此在创建集合容器时,就规定好其可以保存的元素的类型,然后由编译器负责添加元素类型合法性的检查,这样在取用集合中的元素时就不必再进行类型转换了.
public class Test { //使用注解关闭编译提示或警告信息 @SuppressWarnings ({"unchecked"}) public static void main(String[] args) { //不使用泛型约束 List aList = new ArrayList(); aList.add("Tom"); aList.add("Billy"); aList.add(new Date()); aList.add(new Integer(20)); aList.add(500); Iterator iter = aList.iterator(); while(iter.hasNext()) { Object object = iter.next(); System.out.println(object); } String str = (String)aList.get(1); //将集合中下标为1的元素转换为大写 输出 System.out.println(str.toUpperCase()); } } | public class GenericTest { public static void main(String[] args) { List<String> aList = new ArrayList<String>(); aList.add("Tom"); aList.add("Jack"); for(String name:aList) { System.out.println(name); } List<Integer> bList = new ArrayList<Integer>(); bList.add(1); bList.add(500); //Integer 也可以写成int =>自动拆箱 for(int num:bList) { System.out.println(num); } } }
|
将不同类型的元素添加到集合中,取出时需要类型转换 | 使用泛型对集合元素类型约束,取出元素时 不需要类型转换 |
再来看一个泛型的应用
public class Employee { //id常量 private final int id; private String name; private double salary; public Employee(int id,String name,double salary) { this.id = id; this.name = name; this.salary = salary; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
public int getId() { return id; } public void showInfo() { System.out.println("编号:"+this.id+",姓名:"+this.name+",薪水:"+this.salary); } } | public class EmployeeHashMap { public static void main(String[] args) {
Map<Integer, Employee> hashMap = new HashMap<Integer, Employee>();
hashMap.put(001, new Employee(001,"Tom",2000)); hashMap.put(002, new Employee(002,"Jack",3000)); hashMap.put(003, new Employee(003,"Sky",4000));
//通过键来获得值 Employee employee = hashMap.get(001); employee.showInfo(); } }
|
|--泛型的向后兼容性
在包声明之后 ,所有类类容之前使用注解
//使用注解关闭编译提示或警告信息
@SuppressWarnings ({"unchecked"})
三、泛型进阶
|--泛型进阶(一)
泛型类就是由类型参数约束的类 是为泛型类
public class Person<T> { //因为id是常量 应该它没有setter方法 private final int id; private T secrecy; //构造方法不能使用泛型约束 public Person(int id) { this.id = id; } public T getSecrecy() { return secrecy; } public void setSecrecy(T secrecy) { this.secrecy = secrecy; } public int getId() { return id; } } | public class PersonTest { public static void main(String[] args) {
Person<String> p1 = new Person<String>(001); p1.setSecrecy("芝麻开门"); String str = p1.getSecrecy(); System.out.println(p1.getId()+":"+"密码是:"+str);
Person<Double> p2 = new Person<Double>(002); p2.setSecrecy(4832.89); double num = p2.getSecrecy(); System.out.println(p2.getId()+":"+"密码金额是:"+num); } }
|
|--泛型进阶(二)
|--同一个泛型类搭配不同的参数类型符合而成的类型属于同一个类 但却属于不同类型 例:Person(String) Person(Double)
|--同一泛型类如果其参数类型存在继承关系,与泛型类是否存在继承关系没有任何联系.例:Person(String) Person(Object) 参数类型存 在继承关系 当类不存在继承关系
问题:引入泛型之后 是否影响代码的通用性?
来看一个例子:
public class City { public static void main(String[] args) { List<String> aList = new ArrayList<String>(); aList.add("北京"); aList.add("上海"); aList.add("台湾"); aList.add("新加坡");
for(String city:aList) { System.out.println(city); } } } |
此时,如果要遍历List<Double> 或List<Person> 集合时 就必须每次都新建一个相应类型约束的泛型类.
当然也可以在遍历时 不启用泛型检查,但是这样就破坏了程序的安全性.
此时就可以使用泛型的通配符来解决
|
|--泛型进阶(三)
类型的通配符?,使用?来作为类型的通配符 解决泛型通用性的问题
List<?>是任何List泛型的父类型
public class Wildcard {
public static void main(String[] args) {
Wildcard wc = new Wildcard();
List<String> aList = new ArrayList<String>();
aList.add("北京");
aList.add("上海");
aList.add("台湾");
aList.add("新加坡");
List<Integer> bList = new ArrayList<Integer>();
bList.add(001);
bList.add(002);
bList.add(003);
bList.add(004);
wc.showInfo(aList);
wc.showInfo(bList);
}
public void showInfo(List<?> list) {
//凡是必须知道具体类型才能进行的操作都是被禁止的
//list.add("a");
//list.add(005);
for(Object o:list) {
System.out.println(o);
}
//因为remove(Object o) clear() 两方法均没有明确方法中传入的具体类型 因此可以使用
list.remove(004);
list.clear();
}
}
|--泛型进阶(四)
受限制的类型参数,泛型机制允许开发者对类型参数进行附加约束,例如泛型的类型可以继承自特定的类型
public class Point<T extends Number> { private T x; private T y; public Point(T x,T y) { this.x = x; this.y = y; }
public T getX() { return x; }
public void setX(T x) { this.x = x; }
public T getY() { return y; }
public void setY(T y) { this.y = y; } public void showInfo() { System.out.println("x="+this.x+",y="+this.y); } } |
public class PointTest { public static void main(String[] args) {
Point<Integer> p1 = new Point<Integer>(12,21); p1.setX(p1.getX()+100); p1.showInfo();
Point<Double> p2 = new Point<Double>(2.3,4.5); p2.showInfo(); } }
泛型类型参数可以继承父类 T extends Number即是对泛型的类型进行了一定的约束
同样的 泛型的类型参数也可以实现接口 T implements OneInnterface
这些都是对泛型参数类型的约束 |
受限制的类型通配符
public class LimitedWildcard {
public static void main(String[] args) {
LimitedWildcard lw = new LimitedWildcard();
List<Integer> aList = new ArrayList<Integer>();
aList.add(12);
aList.add(13);
List<Double> bList = new ArrayList<Double>();
bList.add(2.3);
bList.add(3.2);
List<String> cList = new ArrayList<String>();
cList.add("Tom");
cList.add("Jack");
lw.showInfo(aList);
lw.showInfo(bList);
//lw.showInfo(cList);
}
//只允许打印类型是Number的集合元素
public void showInfo(List<? extends Number > list) {
for(Object object:list) {
System.out.println(object);
}
}
}