ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java 泛型

2021-06-15 08:32:25  阅读:113  来源: 互联网

标签:Java void list id 泛型 null public


泛型

1. 泛型是jdk 5.0新增的特性

2. 在集合中使用泛型

总结:

  • 集合接口或集合类在jdk5.0之后都修改为带泛型的结构。
  • 在实例化集合类时,可以指明具体的泛型类型。
  • 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)
    使用到类的泛型的位置,都指定为实例化是泛型类型。
    比如:add(E e) ---> 实例化以后:add(Integer e)
  • 注意点:泛型的类型必须是类,不能是基本数据类型,需要用到基本数据类型的位置,拿到包装类替换
  • 如果实例化时,没有指明泛型的类型。默认类型为java.lang.object类型。

3. 如何自定义泛型结构

泛型类、泛型接口;泛型方法。见OrderTest.java

/**
 * 自定义泛型类
 *
 * @param <T>
 */
public class Order<T> {
    T OrderName;
    T OrderAge;

    // 类的内部结构就可以使用类的泛型
    T OrderT;

    // 静态方法中不能使用类的泛型。
//    public static void show(T OrderT){
//        System.out.println(OrderT);
//    }

    public Order() {
        // 编译不通过
        //T[] arr = new T[10];
        // 通过
        T[] arr = (T[]) new Object[10];
    }

    /*
    泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系
    换句话说,泛型方法所属的类是不是泛型类都没有关系。
    泛型方法,可以声明为静态的,原因:泛型参数是在调用方法时确定的,并非在实例化类是确定。
     */
    public <E> List<E> cpList(E[] arr) {
        ArrayList<E> list = new ArrayList<>();

        for (E e : arr) {
            list.add(e);
        }
        return list;
    }

    public Order(T orderName, T orderAge) {
        OrderName = orderName;
        OrderAge = orderAge;
    }

    public void OrderT() {
    }

    public void setOrderT(T orderT) {
        OrderT = orderT;
    }
}
// 异常类不能声明为泛型类
//class MyException<T> extends Exception{}
/**
 * 如何自定义泛型结构:泛型类、泛型接口;泛型方法。
 * 
 * 1. 关于自定义泛型类、接口:
 */
public class OrderTest {
    @Test
    public void test1() {
        // 如果定义了泛型类,实例化没有指定类的泛型,则默认为此泛型类型为Object类型
        // 要求:如果定义了类是带泛型的,建议实例化时要指明类的泛型。
        Order order = new Order();
        order.setOrderT("Tom");

        // 建议:实例化时指明类的泛型。
        Order<Integer> order1 = new Order<>();
        order1.setOrderT(123);

        SubOrder<String> order2 = new SubOrder<>();
        order2.test2("Tom");
    }


    @Test
    public void test2() {
        ArrayList<Integer> list1 = null;
        ArrayList<String> list2 = null;
        // 泛型不同的引用不能互相赋值
        //list1 = list2;

        String s1 = null;
        String s2 = null;
        s1 = s2;
    }

    // 测试泛型方法
    @Test
    public void test3() {
        Order<String> order = new Order<>();
        // 泛型方法在调用时,指明泛型参数的类型。
        Integer[] integers = new Integer[]{1, 2, 3, 4};
        List<Integer> list = order.cpList(integers);
        System.out.println(list);
    }
}

class SubOrder<T> extends Order<Integer> { //SubOrder<T>:仍是泛型类。
    public void test1() {
        SubOrder<Integer> subOrder = new SubOrder<>();
        // 由于子类在继承带有泛型的父类时,指明了泛型类型。则实例化子类对象时,不在需要指明泛型。
        subOrder.OrderT();
    }

    public T test2(T name) {
        return name;
    }
}

静态方法 中不能使用类的泛型。

自定义泛型方法:

[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常

    public class DAO {
        public <E> E get(int id, E e) {
            E result = null;
            return result;
        }
    }
自定义泛型类、泛型接口
class Father<T1, T2> { }
// 子类不保留父类的泛型
// 1)没有类型 擦除
class Son1 extends Father {// 等价于class Son extends Father<Object,Object>{
}
// 2)具体类型
class Son2 extends Father<Integer, String> { }
// 子类保留父类的泛型
// 1)全部保留
class Son3<T1, T2> extends Father<T1, T2> { }
// 2)部分保留
class Son4<T2> extends Father<Integer, T2> { }
class Father<T1, T2> {}
// 子类不保留父类的泛型
// 1)没有类型 擦除
class Son<A, B> extends Father{//等价于class Son extends Father<Object,Object>{
}
// 2)具体类型
class Son2<A, B> extends Father<Integer, String> { }
// 子类保留父类的泛型
// 1)全部保留
class Son3<T1, T2, A, B> extends Father<T1, T2> { }
// 2)部分保留
class Son4<T2, A, B> extends Father<Integer, T2> { }
class Person<T> {
    // 使用T类型定义变量
    private T info;
    // 使用T类型定义一般方法
    public T getInfo() {return info;}
    public void setInfo(T info) {this.info = info; }
    // 使用T类型定义构造器
    public Person() { }
    public Person(T info) {this.info = info;}
// static的方法中不能声明泛型
//public static void show(T t) { }
// 不能在try-catch中使用泛型定义
//public void test() {
//try {} catch (MyException<T> ex) { }
//}
}

4. 泛型的继承方面体现

泛型在继承方面的体现:
虽然类A是类B的父类,但是 G 和 G 二者不具备子父类关系,二者是并列关系。
补充:如果类A是类B的父类,那么 A是B 的父类。

public class GenericTest {
    /*
    1. 泛型在继承方面的体现
        虽然类A是类B的父类,但是 G<A> 和 G<B> 二者不具备子父类关系,二者是并列关系。
        补充:如果类A是类B的父类,那么 A<G>是B<G> 的父类。
     */
    @Test
    public void test1(){
        Object obj1 = null;
        String obj2 = null;
        obj1 = obj2;
        Object[] str1 = null;
        String[] str2 = null;
        str1 = str2;
        // 编译不通过
//        Date date = new Date();
//        obj2 = date;

        List<Object> list1 = null;
        List<String> list2 = null;
        // 此时list1和list2不具备子父类关系
        // 编译不通过
        //list1 = list2;
        /*
        反证法:
        假设list1 = list2;
            list1.add(123); 导致list2混入非String的数据,出错。
         */
    }

    @Test
    public void test2(){
        Collection<String> list1 = null;
        List<String> list2 = null;
        list1 = list2;
    }

5. 通配符的使用

通配符:?

类A是类B的父类,G 和 G 是并列关系,二者的共同父类是G<?>

限制条件的通配符的使用
? extend A: G<? extend A> 可以作为G
和G的父类,其中B是A的子类。
? super A: G<? super A> 可以作为G
和G的父类,其中B是A的父类

		/*
     类A是类B的父类,G<A> 和 G<B> 是并列关系,二者的共同父类是G<?>
     */
    @Test
    public void test3(){
        List<Object> list1 = null;
        List<String> list2 = null;

        List<?> list = null;
        list = list1;
        list = list2;

        ArrayList<String> list3 = new ArrayList<>();
        list3.add("AA");
        list3.add("BB");
        list3.add("CC");
        list = list3;

        //添加(写入):对于List<?> 就不能向其他内部添加数据。
        //除了添加null之外。
//        list.add("DD");
        list.add(null);

        //获取(读取):允许读取数据,读取的数据类型为Object。
        Object o = list.get(0);
        System.out.println(o);

        // 编译通过
//        print(list1);
//        print(list2);
    }

    public void print(List<?> list){
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }
    }

    /*
    3. 限制条件的通配符的使用
        ? extend A: G<? extend A> 可以作为G<A>和G<B>的父类,其中B是A的子类。
        ? super A:  G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类
     */
    @Test
    public void test4(){
        List<? extends Person> list1 = null; // 最下限是Person (Person<=)
        List<? super Person> list2 = null;   // 最上限是Person (<=Person)

        List<Student> list3 = null;
        List<Person> list4 = null;
        List<Object> list5 = null;

        list1 = list3;
        list1 = list4;
//        list1 = list5;

//        list2 = list3;
        list2 = list4;
        list2 = list5;
    }
}
class Person{}
class Student extends Person{}

小练习

/**
 * 定义个泛型类 DAO<T>,在其中定义一个 Map 成员变量,Map 的键
 * 为 String 类型,值为 T 类型。
 * 分别创建以下方法:
 * public void save(String id,T entity): 保存 T 类型的对象到 Map 成员
 * 变量中
 * public T get(String id):从 map 中获取 id 对应的对象
 * public void update(String id,T entity):替换 map 中 key 为 id 的内容,
 * 改为 entity 对象
 * public List<T> list():返回 map 中存放的所有 T 对象
 * public void delete(String id):删除指定 id 对象
 * @param <T>
 */
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(){
        //错误的
//        Collection<T> values = map.values();
//        return (List<T>) values;
        //正确的
        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);
    }
}
/**
 * 定义一个 User 类:
 * 该类包含:private 成员变量(int 类型) id,age;(String 类型)name。
 */
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;
    }
}
/**
 * 定义一个测试类:
 * 创建 DAO 类的对象, 分别调用其 save、get、update、list、delete 方
 * 法来操作 User 对象,
 * 使用 Junit 单元测试类进行测试。
 */
public class DAOTest {
    public static void main(String[] args) {
        DAO<User> dao = new DAO<>();
        dao.save("1001",new User(1001,48,"三张"));
        dao.save("1002",new User(1002,24,"四李"));
        dao.save("1003",new User(1003,45,"五王"));
        dao.save("1004",new User(1004,36,"麻二"));


        User user1 = dao.get("1002");
        System.out.println(user1); //User{id=1002, age=24, name='四李'}
        dao.update("1003",new User(2003,66,"王孙"));
        List<User> list1 = dao.list();
        System.out.println(list1);
        dao.delete("1001");
        System.out.println("---------------------------------");
        List<User> list = dao.list();
        for (User user : list) {
            System.out.println(user);
        }
    }
}

标签:Java,void,list,id,泛型,null,public
来源: https://www.cnblogs.com/kin02/p/14884041.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有