Java基础之泛型 2023-5-2

本文笔记来源于本人自学尚硅谷java最新基础课程而来

1. 泛型在集合和比较器中的使用!

1.1 什么是泛型?
  • 所谓泛型,就是允许在定义类、接口时通过一个“标识”表示类中的某个“属性的类型”或者是某个方法的“返回值或参数的类型”。
  • 这个类型参数在使用时(如:继承或实现这个接口、创建对象或调用方法)确定,即传入实际的类型参数、也成为类型实参
1.2 在集合中使用泛型之前可能存在的问题
  • 问题1:类型不安全。因为add()的参数是Object类型,意味着任何类型的对象都可以添加成功
  • 问题2:需要使用强转操作,反锁。还有可能导致CastClassException异常
1.3 在集合、比较器中使用泛型 (重点)
  • 见代码
//在集合中使用泛型的例子  
    @Test  
    public void test2(){  
        List<Integer> list = new ArrayList<>(); //新特性  
        list.add(52);  
        list.add(645);  
        list.add(54);  
        list.add(20);  
  
//        list.add("aAA");  //编译报错,保证了类型的安全  
  
        Iterator<Integer> iterator = list.iterator();  
        while (iterator.hasNext()){  
            //因为添加的都是Integer类型,避免了强转操作  
            Integer i = iterator.next();  
            int score = i;  
            System.out.println(score);  
        }  
    }
/**  
     * 泛型在Map中使用的离职  
     */  
  
    @Test  
    public void test3(){  
//        HashMap<String,Integer> map = new HashMap<String, Integer>();  
        //新特性后如下  
        HashMap<String, Integer> map = new HashMap<>();  
  
        map.put("Tom",89);  
        map.put("Jerry",88);  
        map.put("Jack",70);  
  
        //遍历entry  
//        Set<Map.Entry<String,Integer>> entry = map.entrySet();  
//        Iterator<Map.Entry<String,Integer>> iterator = entry.iterator();  
  
        var entrySet = map.entrySet();  
        var iterator = entrySet.iterator();  
  
        while (iterator.hasNext()){  
            Map.Entry<String,Integer> entry1 = iterator.next();  
            System.out.println(entry1.getKey() + "--->" + entry1.getValue());  
        }  
  
    }
  • 重点是在Map中使用的例子
1.4 使用说明
  • 集合框架在声明接口和其实现类时,使用了泛型(jdk5.0),
  • 在实例化集合对象时,如果没有使用泛型,则认为操作的是Object的数据
  • 如果使用了泛型,则需要指明泛型的具体类型
  • 一旦确定了泛型的类型,则在集合的相关的方法中,凡是使用类的泛型的位置,都替换为具体的类型。

2. 自定义泛型

2.1 自定义泛型类接口
2.1.1 格式
class A<T>{}  

interface B<T1,T2>{}  
2.1.2 使用说明
  • 我们在声明完自定义泛型类以后,可以在类的内部(如:属性、方法、构造器中)使用类的泛型
  • 在创建自定义泛型类的对象时,可以指明泛型参数类型,一旦指明,那么类中使用了泛型的地方都要具体化为指定的泛型类型
  • 在创建自定义泛型类的对象时,没有指明泛型参数类型的,一律按Object类型处理,但不等价与Object!!!
  • 所以泛型要么全使用,要么都不用
  • 泛型的指定类型必须是引用类型!!!所以基本数据类要用包装类
2.1.3 子类或继承类的使用说明
  • 除创建泛型类对象外,子类继承泛型类,实现类实现泛型接口,也可以确定泛型结构中的泛型参数
  • 如果我们在给泛型提供子类是,子类也不确定泛型类型,则可以继续使用泛型参数
  • 可以在现有父类的泛型参数的基础上,新增泛型参数
2.1.4 注意点
  • 泛型可能有多个参数,应将多个参数一起放在尖括号内。比如<E1,E2,E3>
  • JDK7.0 开始,泛型开始简化操作:
ArrayList<String> list = new ArrayList<>(); 
  • 如果泛型接口是一个接口或抽象类,则不可创建泛型类的对象
  • 不能使用new E[]。 但是可以:E[] elements = (E[]) new Object[capacity]
  • 参考:ArrayList源码中声明: Object[] elementData,而非泛型参数类型数组
  • 在类/接口声明的泛型,在本类或本接口中即代表某种类,但不可以在静态方法中使用类的泛型。
  • 异常类不能是带泛型的
2.2 自定义泛型方法
2.2.1 问题:在泛型类的方法中,使用了类的泛型参数。那么此方法是泛型方法吗?
  • 不一定是
2.2.2 格式
权限修饰符 <T> 返回值类型 方法名(形参列表){  
	方法体         //通常在形参列表或返回值类型的位置会出现泛型参数T  
}  
2.2.3 举例
public <E> E method(E e){  
}  

2.2.4 说明
  • 声明泛型方法时,一旦要添加泛型参数<\T>
  • 泛型参数在方法调用时,指明其具体的类型
  • 泛型方法可以根据需要,声明为static的
  • 泛型方法所属的类是否是一个泛型类,都可以的!!!

3. 泛型在继承上的体现

3.1 类SuperA是类A的父类,则G<SuperA>G<A>的关系:
  • G<SuperA>G<A> 是并列的两个类,没有任何子父类的关系

  • 如:ArrayList<Object> ArrayList<String> 没有关系

3.2 类SuperA是类A的父类或接口,SuperA<G> A<G>的关系:
  • SuperA<G> A<G> 有继承或实现的关系

  • A<G>的实例可以赋值给SuperA<G>类型的引用(变量)

  • 如:List<String>ArrayList<String>

4. 通配符的使用

4.1 通配符:
4.2 使用说明:
  • 举例:ArrayList<?>

  • G<?>可以看做是G<A>类型的父类,即可将G<A>的对象赋值给G<?>类型的引用(变量)

4.3 读写数据的特点(以ArrayList<?>为例说明)
  • 读取数据:允许的,读取的值的类型为Object类型
  • 写入数据:不允许的,特例是null
4.4 有限制条件的通配符
  • List<? extends A> : 可以将List<A>List<B>赋值给List<? extends A> 其中B是A的子类
    - List <? super A> : 可以将List<A>List<B>赋值给List <? super A> 其中B是A的父类
5.4 有限制条件的统配符的读写操作(难、了解)
  • 技巧:开发中,遇到了带限制条件的通配符,在赋值时,如果没报错,那就正常使用。
    如果报错了,知道不能这样写。改改!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值