JAVA泛型
为什么要有泛型
集合不限制类型的问题:
public void test1(){
ArrayList list = new ArrayList();
list.add(78);
list.add(76);
list.add(77);
list.add(99);
//问题一:类型不安全
list.add("sss");
for (Object score:list){
//问题二:强制转换时会出异常:ClassCastException
int stuScore = (int) score;
System.out.print(stuScore+" ");
}//78 76 77 99
}
- 使用泛型之后:(泛型不能用基本数据类型)
public void test2() {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(78);
list.add(76);
list.add(77);
list.add(99);
//编译时就会进行类型检查,保证数据安全
//list.add("sss");//此处会报错
for (Integer score : list) {
int stuScore = score;
System.out.print(stuScore + " ");
}
System.out.println();
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
int stuScore = iterator.next();
System.out.print(stuScore + " ");
}
}
-
Map中的泛型
public void test3() { HashMap<String, Integer> map = new HashMap<String, Integer>(); map.put("Meiko",99); map.put("Scout",80); map.put("Viper",80); map.put("Flandre",88); map.put("Jiejie",90); //map.put(11,"1esa");//报错 Set<Map.Entry<String, Integer>> entry = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entry.iterator(); while (iterator.hasNext()){ Map.Entry<String, Integer> entry1 = iterator.next(); String key = entry1.getKey(); Integer value = entry1.getValue(); System.out.print(key+ " = " + value + " "); } }
自定义泛型类
-
Order泛型类
public class Order<T> { String orderName; int orderId; //类的内部结构就可以使用类的泛型 T orderT; public Order() { } public Order(String orderName, int orderId, T orderT) { this.orderName = orderName; this.orderId = orderId; this.orderT = orderT; } public T getOrderT() { return orderT; } public void setOrderT(T orderT) { this.orderT = orderT; } @Override public String toString() { return "Order{" + "orderName='" + orderName + '\'' + ", orderId=" + orderId + ", orderT=" + orderT + '}'; } }
-
测试
public void test4() { //如果定义了泛型类,实例化没有指明类的泛型,则认为泛型的典型类型为Object类型 Order<String> order = new Order<String>("AA",001,"333"); System.out.println(order); //Order{orderName='AA', orderId=1, orderT=333} }
-
子类继承父类
public class SubOrder extends Order<Integer>{ }
public class SubOrder1<T> extends Order<T>{ }
-
测试
public void test5() { SubOrder subOrder = new SubOrder(); //由于子类在继承带泛型的父类时,指明了泛型类型,则实例化时不需要指明泛型 //如:public class SubOrder extends Order<Integer> subOrder.setOrderT(1122); //subOrder.setOrderId("12321");//此处会报错 //如果不指名泛型类型则需要指明 //如:public class SubOrder1<T> extends Order<T> SubOrder1<String> subOrder1 = new SubOrder1<>(); subOrder1.setOrderT("123"); //subOrder1.setOrderT(123);//会报错 }
-
注意事项
自定义泛型方法:
在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系
即泛型方法所属的类是不是泛型类都没有关系
-
定义示例:可以是静态方法
原因:泛型方法中的泛型参数是在调用方法时确定的,并非是实例化时确定的,所以可以是静态方法
public static <E> List<E> copyFromArrayToList(E[] arr){ //将此方法加在之前Order类的里面,可以是静态方法 ArrayList<E> list = new ArrayList<>(); for(E e:arr){ list.add(e); } return list;}
-
调用示例:泛型方法调用时,指明泛型参数的类型
//测试泛型方法public void test5() { Order<String> order = new Order<>(); Integer[] arr = new Integer[]{1,2,3,4}; List<Integer> list = order.copyFromArrayToList(arr); System.out.println(list);//[1, 2, 3, 4]}
使用用泛型类、泛型方法的实际情景
- DAO: data(base) access object 数据访问对象
import java.util.List;public class DAO<T> { //添加一条记录 public void add(T t){ } //删除一条记录 public boolean remove(int index){ return false; } //修改一条记录 public void update(int index,T t){ } //查询一条记录 public T getIndex(int index){ return null; } //查询多条记录 public List<T> getForList(int index){ return null; }}
- Customer类(相当于一个表)
public class Customer {//此类对应数据库中的一个表}
-
CustomerDAO类:指定该类只能对Customer进行相关操作
public class CustomerDAO extends DAO<Customer>{}
-
Student类:相当于另一个表
public class Student {}
-
StudentDAO类:指定该类只能对Student进行相关操作
public class StudentDAO extends DAO<Student>{}
-
泛型方法
//泛型方法//举例:获取表中一共有多条记录?获取最大的员工入职时间public <E> E getValue(){ return null;}
泛型在继承方面的体现
-
虽然类A是类B的父类,但是G 和G 二者不具备父子关系,二者是并列关系
public void test1(){ Object obj = null; String str = null; obj = str;//多态,子类可以赋值给父类 Object[] arr1 = null; String[] arr2 = null; arr1 = arr2;//多态,子类可以赋值给父类 List<Object> list1 = null; List<String> list2 = null; //list1 = list2;//此处报错,不能赋值,list1和list2的类型不具有子父类关系 }
-
补充:类(接口)A是类(接口)B的父类,A
是B 的父类 public void test2(){ List<String> list1 = null; ArrayList<String> list2 = null; list1 = list2; }
通配符的使用
通配符:?
类A是类B的父类,但是G 和G 二者不具备父子关系,二者共同的父类是 G<?>
public void test3(){
List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
//下面的程序可以编译通过
// myPrint(list1);
// myPrint(list2);
// list = list1;
// list = list2;
//添加操作:(写入)
//对于List<?>就不能向其内部添加数据,除了添加null之外
ArrayList<String> list3 = new ArrayList<>();
list3.add("AA");
list3.add("BB");
list3.add("CC");
list = list3;
list.add(null);
//获取(读取):
Object o = list.get(0);
System.out.println(o);//AA
}
public void myPrint(List<?> list){
Iterator<?> iterator = list.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
有限制条件的通配符使用
-
?extends A: (理解: (-∞,A)) 相当于<=
G<? extends A> 的意思是:可以作为G和G的父类,其中B是A的子类
-
? super A: (理解:(A,+∞)) 相当于>=
G<? super A> 的意思是:可以作为G和G的父类,其中B是A的父类
public void test4(){
List<? extends Person> list1 = null;
List<? super Person> list2 = null;
List<Student> list3 = new ArrayList<Student>();
List<Person> list4 = new ArrayList<Person>();
List<Object> list5 = new ArrayList<Object>();
list1 = list3;
list1 = list4;
//list1 = list5;//会报错
//list2 = list3;//会报错
list2 = list4;
list2 = list5;
//读取数据
list1 = list3;
Person p = list1.get(0);
//Student stu = list1.get(0);//会报错
list2 = list4;
Object o = list2.get(0);
//Person p1 = list2.get(0);//会报错
//写入数据
//list1.add(new Student());
//会报错,父类不能赋值给子类,list1有可能是比Student更小的继承Person的子类,
list2.add(new Student());//不会报错
list2.add(new Person());
}
练习
- 自定义泛型类DAO
import java.util.*;
public class DAO<T> {
private Map<String,T> map = new HashMap<String,T>();
public DAO() {
}
public DAO(Map<String, T> map) {
this.map = map;
}
//保存T类型的对象到Map成员变量中
public void save(String id,T entity){
this.map.put(id,entity);
}
//从map 中获取id对应的对象
public T get(String id){
return this.map.get(id);
}
//替换map中的key为id的内容,改为entity对象
public void update(String id,T entity){
if(this.map.containsKey(id)){//判断是否有这个id
this.map.put(id, entity);
}
}
//返回map中存放的所有T对象
public List<T> list(){
ArrayList<T> listValues = new ArrayList<>();
Collection<T> values = this.map.values();
//不能使用强转去返回List
//例如:return (List<T> )values
//原因:一般强转需要先new的对象就是List,之后才能强转
//例如 Collection c = new ArrayList();
// ArrayList listValues = (ArrayList) c;
Iterator<T> iterator = values.iterator();
while(iterator.hasNext()){
listValues.add(iterator.next());
}
return listValues;
}
//删除指定的id对象
public void delete(String id){
this.map.remove(id);
}
}
- 自定义类
/*
定义一个user类
*/
public class User {
private int id;
private int age;
private String name;
public User() {
}
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 == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (id != user.id) return false;
if (age != user.age) return false;
return name != null ? name.equals(user.name) : user.name == null;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + age;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
}
- 测试类
import java.util.List;
public class DAOTest {
public static void main(String[] args) {
DAO<User> dao = new DAO<User>();
dao.save("1001",new User(1001,23,"XiaoHu"));
dao.save("1002",new User(1002,20,"Wei"));
dao.save("1003",new User(1003,20,"Cryin"));
dao.save("1004",new User(1004,19,"Gala"));
dao.save("1005",new User(1005,22,"Ming"));
List<User> list = dao.list();
for (User user : list) {
System.out.println(user);
}
/*
User{id=1005, age=22, name='Ming'}
User{id=1004, age=19, name='Gala'}
User{id=1003, age=20, name='Cryin'}
User{id=1002, age=20, name='Wei'}
User{id=1001, age=23, name='XiaoHu'}
*/
System.out.println();
dao.update("1002",new User(1002,19,"Wei"));
dao.delete("1003");
System.out.println("1001号的信息为:"+dao.get("1001"));
List<User> list1 = dao.list();
System.out.println("删除1003号之后的全员信息为:");
for (User user : list1) {
System.out.println(user);
}
/*
User{id=1005, age=22, name='Ming'}
User{id=1004, age=19, name='Gala'}
User{id=1002, age=19, name='Wei'}
User{id=1001, age=23, name='XiaoHu'}
*/
}
}