泛型的使用

在集合中使用泛型

  1. 集合接口或集合类在jdk5.0时都修改为带泛型的结构

  2. 在实例化集合类时,可以指明具体的泛型类型

  3. 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构使用泛型的位置,都指定为实例化时泛型的类型(比如:add(E e)---->实例化以后:add(Integer e))

  4. 泛型的类型必须是类,不能是基本数据类型。

    p.567

package com.yicurtain.SETS;

import org.junit.Test;

import java.sql.Array;
import java.util.*;

public class GenericTest {
    @Test
    public void test1(){
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(78);
        list.add(87);
        list.add(88);
        list.add(89);
//        因为使用了泛型,所以只允许添加Integer类型的数据
//        list.add("TOM")
//        方式一 使用增强for循环
//        for (Integer score:list
//             ) {
//            System.out.println(score);
//        }
//        方式二 使用迭代器的方式
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println(next);

        }

    }
    @Test
    public void test3(){
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Jerry",87);
        map.put("Hery",78);
        map.put("Jack",77);
        map.put("Rose",89);

        Set<Map.Entry<String, Integer>> entry = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> next = iterator.next();
            String key = next.getKey();
            Integer value = next.getValue();

            System.out.println("集合:"+next+",键:"+key+",值:"+value);

        }


    }
}

自定义泛型类

  1. public class Order{} ----->Order类就具备了泛型的特性
  2. 由于子类在继承带泛型的父类时,父类指明了泛型的类型,则实例化子类的对象时,不再需要指明泛型(相当于泛型具有继承性)

注意点

  1. 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如:
    <E1,E2,E3>

  2. 泛型类的构造器如下:public GenericClass(){}。
    而下面是错误的:public GenericClass(){}

  3. 实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致。

  4. 泛型不同的引用不能相互赋值

    1. 尽管在编译时ArrayList和ArrayList是两种类型,但是,在运行时只有
      一个ArrayList被加载到JVM中。
  5. 泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价
    于Object。经验:泛型要使用一路都用。要不用,一路都不要用。

  6. 如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。

  7. jdk1.7,泛型的简化操作:ArrayList flist = new ArrayList<>();

  8. 泛型的指定中不能使用基本数据类型,可以使用包装类替换。

  9. 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态
    属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法
    中不能使用类的泛型。

  10. 异常类不能是泛型的

  11. 不能使用new E[]。但是可以:E[] elements = (E[])new Object[capacity];
    参考:ArrayList源码中声明:Object[] elementData,而非泛型参数类型数组。

  12. 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
     子类不保留父类的泛型:按需实现
     没有类型 擦除
     具体类型
     子类保留父类的泛型:泛型子类
     全部保留
     部分保留
    结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自
    己的泛型

泛型方法

  1. 在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系
  2. 泛型方法可以声明为静态的。原因:泛型参数在调用方法时是确定的,并非在实例化时确定。

泛型在继承方面的体现

  1. 类A是类B的父类,但是G、G不具备子父类关系,二者是并列关系。
  2. 类A是类B的父类,那么A也是B的父类。

通配符的使用

  1. 通配符:“?”

  2. 类A是类B的父类,但是G、G不具备子父类关系;二者共同的父类:G<?>.

  3. 有限制条件的通配符的使用

    1. (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用
    2. [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用

练习

package com.yicurtain.Generic;

import java.util.*;

public class DAO <T>{
    private Map<String,T> map = new HashMap<>();
//    保存 T 类型的对象到 Map 成员变量中

    public void save(String id,T entity){
    map.put(id, entity);
    }
//    从 map 中获取 id 对应的对象
public T get(String id){
        return  map.get(id);
}
//    替换 map 中 key 为 id 的内容,
//    改为 entity 对象
public void update(String id,T entity){
    if (map.containsKey(id)){
        map.put(id, entity);
    }
}
//    返回 map 中存放的所有 T 对象
public List<T> list(){
    ArrayList<T> list = new ArrayList<>();
    Collection<T> values = map.values();
    for (T t:values
         ) {
        list.add(t);
    }
    return list;
}
//    删除指定 id 对象
public void delete(String id){
    map.remove(id);
}
}

package com.yicurtain.Generic;

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 int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setAge(int age) {
        this.age = age;
    }

    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;
    }
}


package com.yicurtain.Generic;

import java.util.Iterator;
import java.util.List;

public class GenericTest {
    public static void main(String[] args) {
        DAO<User> dao = new DAO<>();
       dao.save("1001",new User(1001,25,"周杰伦"));
       dao.save("1002",new User(1002,18,"昆凌"));
       dao.save("1003",new User(1003,25,"方文山"));
        dao.update("1003",new User(1003,19,"蔡依林"));
        dao.delete("1003");
        List<User> list = dao.list();
        Iterator<User> iterator = list.iterator();
        while(iterator.hasNext()){
            User next = iterator.next();
            System.out.println(next);
        }


    }
}

posted on 2021-07-12 16:40  yicurtain  阅读(100)  评论(0)    收藏  举报