泛型(Generic) 作用
解决元素存储的安全性问题
解决获取数据元素时,需要类型强转的问题
1 2 3 4 5 6 7 8 9 10 11 12 List list= new ArrayList<>(); list.add(12 ); list.add(24 ); list.add(48 ); list.add(new String("AA" )); for (int i = 0 ; i < list.size(); i++){ int score = (Integer)list.get(i); System.out.println(score); }
1 2 3 4 5 6 7 8 9 List<Integer> list= new ArrayList<>(); list.add(12 ); list.add(24 ); list.add(48 ); for (int i = 0 ; i < list.size(); i++){ int score = list.get(i); System.out.println(score); }
使用 泛型的声明 interface List<T>
和 class TestGen<K,V>
,其中,T、K、V不代表值,而是表示类型。这里使用任意字母都可以。常用T表示,是Type的缩写。
泛型的实例化 一定要在类名后面指定类型参数的值(类型)。如:
1 2 List<String> strList = new ArrayList<String>(); Iterator<Customer> iterator = customers.iterator();
T只能是类,不能用基本数据类型填充。
几个重要的使用
在集合中使用泛型
自定义泛型类
泛型方法
泛型接口
总结 泛型,JDK1.5新加入的,解决数据类型的安全性问题 ,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。
泛型类(含集合类)
对象实例化时不指定泛型,默认为:Object
泛型不同的引用不能相互赋值
加入集合中的对象类型必须与指定的泛型类型一致
静态方法中不能使用类的泛型
如果泛型类是一个接口或抽象类,则不可创建泛型类的对象
不能在catch中使用泛型
从泛型类派生子类,泛型类型需具体化
把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想
自定义泛型类 1 2 3 4 5 6 7 8 9 10 11 class Person <T > { private T info; public T getInfo () { return info; } public void setInfo (T info) { this .info = info; } }
泛型方法 方法,也可以被泛型化,不管此时定义在其中的类是不是泛型化的。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
1 2 3 4 5 6 public class DAO { public <E> E get (int id, E e) { E result = null ; return result; } }
泛型和继承的关系 如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G<B>
并不是G<A>
的子类型! 比如:String是Object的子类,但是List<String>
并不是List<Object>
的子类。
通配符
有限制的通配符
<?>
:允许所有泛型的引用调用
<? extends Number>
: **(无穷小, Number]**,只允许泛型为Number及Number子类的引用调用
<? super Number>
: **[Number , 无穷大)**,只允许泛型为Number及Number父类的引用调用
<? extends Comparable>
:只允许泛型为实现Comparable接口的实现类的引用调用
应用 练习1 用户在设计类的时候往往会使用类的关联关系,例如,一个人中可以定义一个信息的属性,但是一个人可能有各种各样的信息(如联系方式、基本信息等),所以此信息属性的类型就可以通过泛型进行声明,然后只要设计相应的信息类即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 public class GenericPerson { public static void main (String[] args) { Person<Contact> person = null ; person = new Person<>(new Contact("南京市" ,"18866668888" ,"10088" )); System.out.println(person); Person<Introduction> person2 = null ; person2 = new Person<>(new Introduction("小新" ,"男" ,22 )); System.out.println(person2); } } interface Info { } class Contact implements Info { private String address ; private String telephone ; private String zipcode ; public Contact (String address,String telephone,String zipcode) { this .address = address; this .telephone = telephone; this .zipcode = zipcode; } public void setAddress (String address) { this .address = address ; } public void setTelephone (String telephone) { this .telephone = telephone ; } public void setZipcode (String zipcode) { this .zipcode = zipcode; } public String getAddress () { return this .address ; } public String getTelephone () { return this .telephone ; } public String getZipcode () { return this .zipcode; } @Override public String toString () { return "Contact [address=" + address + ", telephone=" + telephone + ", zipcode=" + zipcode + "]" ; } } class Introduction implements Info { private String name ; private String sex ; private int age ; public Introduction (String name,String sex,int age) { this .name = name; this .sex = sex; this .age = age; } public void setName (String name) { this .name = name ; } public void setSex (String sex) { this .sex = sex ; } public void setAge (int age) { this .age = age ; } public String getName () { return this .name ; } public String getSex () { return this .sex ; } public int getAge () { return this .age ; } @Override public String toString () { return "Introduction [name=" + name + ", sex=" + sex + ", age=" + age + "]" ; } } class Person <T extends Info > { private T info ; public Person (T info) { this .info = info; } public void setInfo (T info) { this .info = info ; } public T getInfo () { return info ; } @Override public String toString () { return "Person [info=" + info + "]" ; } }
练习2
定义一个Employee类,该类包含:private成员变量name、age、birthday,其中 birthday 为 MyDate 类的对象;并为每一个属性定义 getter、setter 方法;并重写 toString 方法输出 name、age、birthday
MyDate类包含:private成员变量month、day、year;并为每一个属性定义 getter、setter 方法;
创建该类的 5 个对象,并把这些对象放入 TreeSet 集合中(TreeSet 需使用泛型来定义),分别按以下两种方式对集合中的元素进行排序,并遍历输出:
使Employee 继承 Comparable 接口,并按 name 排序
创建 TreeSet 时传入 Comparator对象,按生日日期的先后排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;public class TestTreeSet { public static void main (String[] args) { Comparator comparator = new Comparator() { @Override public int compare (Object o1, Object o2) { if (o1 instanceof L07.exer2.Employee2 && o2 instanceof L07.exer2.Employee2){ L07.exer2.Employee2 e1 = (L07.exer2.Employee2) o1; L07.exer2.Employee2 e2 = (L07.exer2.Employee2) o2; L07.exer2.MyDate birthday1 = e1.getBirthday(); L07.exer2.MyDate birthday2 = e2.getBirthday(); if (birthday1.getYear() != birthday2.getYear()){ return birthday1.getYear() - birthday2.getYear(); } else { if (birthday1.getMonth() != birthday2.getMonth()){ return birthday1.getMonth() - birthday2.getMonth(); } else { return birthday1.getDay() - birthday2.getDay(); } } } return 0 ; } }; Employee2 employee = new Employee2("小新" ,22 ,new MyDate(1999 ,10 ,29 )); Employee2 employee2 = new Employee2("小鑫" ,24 ,new MyDate(1997 ,6 ,13 )); Employee2 employee3 = new Employee2("小伟" ,21 ,new MyDate(2000 ,10 ,28 )); Employee2 employee4 = new Employee2("小宇" ,23 ,new MyDate(1998 ,7 ,12 )); Employee2 employee5 = new Employee2("小创" ,22 ,new MyDate(1999 ,3 ,18 )); TreeSet<Employee2> treeSet = new TreeSet<Employee2>(comparator); treeSet.add(employee); treeSet.add(employee2); treeSet.add(employee3); treeSet.add(employee4); treeSet.add(employee5); Iterator<Employee2> iterator = treeSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }
练习3
定义个泛型类 DAO<T>
,在其中定义一个Map 成员变量,Map 的键为 String 类型,值为 T 类型。分别创建以下方法:
public void save(String id,T entity)
: 保存 T 类型的对象到 Map 成员变量中
T get(String id)
:从 map 中获取 id 对应的对象
void update(String id,T entity)
:替换 map 中key为id的内容,改为 entity 对象
List<T> list()
:返回 map 中存放的所有 T 对象
void delete(String id)
:删除指定 id 对象
定义一个 User 类:该类包含:private成员变量(int类型)id、age;(String 类型)name
创建 DAO 类的对象, 分别调用其 save、get、update、list、delete 方法来操作 User 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class DAO <T > { Map<String,T> map = new HashMap<>(); public void save (String id,T entity) { map.put(id,entity); } public T get (String id) { return map.get(id); } public void update (String id,T entity) { map.put(id, entity); } public List<T> list () { List<T> list = new ArrayList<>(); for (String s : map.keySet()){ list.add(map.get(s)); } return list; } public void delete (String id) { map.remove(id); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import java.util.Objects;public class User { private int id; private int age; private String name; public User (int id, int age, String name) { this .id = id; this .age = age; this .name = name; } public int getId () { return id; } public void setId (int id) { this .id = id; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } @Override public String toString () { return "User{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}' ; } @Override public boolean equals (Object o) { if (this == o) return true ; if (!(o instanceof User)) return false ; User user = (User) o; return getId() == user.getId() && getAge() == user.getAge() && Objects.equals(getName(), user.getName()); } @Override public int hashCode () { return Objects.hash(getId(), getAge(), getName()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.HashMap;import java.util.List;public class TestDAO { public static void main (String[] args) { DAO<User> dao = new DAO<>(); dao.map = new HashMap<>(); dao.save("1001" ,new User(1 ,22 ,"小新" )); dao.save("1002" ,new User(2 ,23 ,"小鑫" )); dao.save("1003" ,new User(3 ,21 ,"小伟" )); User user = dao.get("1002" ); System.out.println(user); dao.update("1002" ,new User(2 ,26 ,"黄景瑜" )); dao.delete("1003" ); List<User> list = dao.list(); System.out.println(list); } }