关于泛型的一些问题

简介: 一、泛型在任何运行时需要知道确切类型信息的操作都将无法工作 package generics;//: generics/Erased.java// {CompileTimeError} (Won't compile)public class Erased ...

一、泛型在任何运行时需要知道确切类型信息的操作都将无法工作

package generics;
//: generics/Erased.java
// {CompileTimeError} (Won't compile)

public class Erased<T> {
  private final int SIZE = 100;
  public static void f(Object arg) {
    if(arg instanceof T) {}          // Error
    T var = new T();                 // Error
    T[] array = new T[SIZE];         // Error
    T[] array = (T)new Object[SIZE]; // Unchecked warning
  }
} ///:~

二、泛型类型参数在声明什么类型就必须实例化什么类型,类型继承和多态不能用于泛型类型参数。

class Fruit {}
class Apple extends Fruit {}
class Orange extends Fruit {}
public class NonCovariantGenerics {
  // Compile Error: incompatible types:
  List<Fruit> flist = new ArrayList<Apple>();
} ///:~
在实例化一个List的时候 指定一个泛型类型,如果这个类型是Fruit,那么就代表后面所有继承Fruit的子类都可以添加到当前的集合中;但是在赋值的时候却是使用的 Apple,那么这个ArrayList 中的泛型定义就是 Apple类型,也就意味着后面对 这个 ArrayList 进行Add等操作都必须是Apple类型或者是Apple的子类;也就和前面的Fruit以及Fruit的子类自相矛盾了;所以不允许这样进行擦除。

三、List<? extends T> 这里的T可以是任何类或者接口,?可以是T代表的这个类本身或子类;List<? super T>这里?可以是T代表的这个类本身或它的父类;

四、泛型对象的泛型参数类型在声明的时候确定

Holder<?> unbounded = new Holder<Long>();

这里unbounded的泛型类型参数是未知的;因为进行了泛型转型 擦除掉了

五、泛型类对象做参数,使用方法的时候,传递的对象的泛型参数必须一致

package generics;
public class Wildcards {
  
  static <T> T wildSubtype(Holder<? extends T> holder, T arg) {
    T t = holder.get();
    return t;
  }	
  static <T> void wildSupertype(Holder<? super T> holder, T arg) {
    holder.set(arg);
    Object obj = holder.get();
  }
  public static void main(String[] args) {
    Holder<Long> qualified = new Holder<Long>();
    Holder<?> unbounded = new Holder<Long>();
    Holder<? extends Long> bounded = new Holder<Long>();
    Long lng = 1L;

    Long r10 = wildSubtype(qualified, lng);
    // OK, but can only return Object:
    Object r11 = wildSubtype(unbounded, lng);//Error
    Long r12 = wildSubtype(bounded, lng);
	
    wildSupertype(qualified, lng);
     wildSupertype(unbounded, lng); // Error:
    //   wildSupertype(Holder<? super T>,T) cannot be
    //   applied to (Holder<capture of ?>,Long)
     wildSupertype(bounded, lng); // Error:
    //   wildSupertype(Holder<? super T>,T) cannot be
    //  applied to (Holder<capture of ? extends Long>,Long)
  }
} ///:~

 Object r11 = wildSubtype(unbounded, lng);//Error
wildSupertype(unbounded, lng); // Error:
wildSupertype(bounded, lng); // Error:
这三句话都是因为参数的泛型参数类型不对出错。


Long r12 = wildSubtype(bounded, lng);

这句没出错,说明参数可以为参数类型不确定的泛型。

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

七、要用到泛型的方法必须在方法声明的时候声明为泛型方法。

格式为:

public static <T> void fromArrayToCollection(T[] a, Collection<T> c){//方法实现}//其中T不能是类的泛型

八、泛型通配符

泛型通配符的主要作用是为了在方法调用时,泛型参数使用通配符就可以让该参数类型不受限制。

1.使用类型 通配符:?,比如:List<?> ,Map<?,?>
List<?>是List<String>、List<Object>等各种泛型List的父类。
2. 读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
3. 写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。唯一的例外是null,它是所有类型的成员。


•  将任意元素加入到其中不是类型安全的:
• Collection<?> c = new ArrayList<String>();
• c.add(new Object()); // 编译时错误
•  因为我们不知道c 的元素类型,我们不能向其中添加对象

• add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。
•  唯一的例外的是null ,它是所有类型的成员。
•  另一方面,我们可以调用get() 方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object

public static void main(String[] args) {
List<?> list = null;
list = new ArrayList<String>();
list = new ArrayList<Double>();
//list.add(3);
list.add(null);
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
l1.add(“ 六星教育");
l2.add(15);
read(l1);
read(l2); }
static void read(List<?> list){
for(Object o : list){
System.out.println(o);
} }
• <?>
• 允许所有泛型的引用调用
• 举例:
• <? extends Number> ( 无穷小 , Number]
• 只允许泛型为Number及Number子类的引用调用
• <? super Number> [Number ,  无穷大)
• 只允许泛型为Number及Number父类的引用调用
• <? extends Comparable>
• 只允许泛型为实现Comparable接口的实现类的引用调用

public static void printCollection3(Collection<?
extends Person> coll){
//Iterator只能用Iterator<?>或Iterator<? extends
Person>.why?
Iterator<?> iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
} }
public static void printCollection4(Collection<? super
Person> coll){
Iterator<?> iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
} }

目录
相关文章
|
运维 Kubernetes Cloud Native
云原生基本概念,核心技术、现状与前景|学习笔记
快速学习云原生基本概念,核心技术、现状与前景
1553 0
云原生基本概念,核心技术、现状与前景|学习笔记
|
9月前
|
传感器 人工智能 物联网
穿戴科技新风尚:智能服装设计与技术全解析
穿戴科技新风尚:智能服装设计与技术全解析
709 85
|
DataWorks 数据可视化 搜索推荐
DataWorks产品体验与评测报告
DataWorks是一款全面的大数据开发治理平台,通过最佳实践测评,展示了其在用户画像分析、数据管理和开发效率提升等方面的强大功能。体验过程中,虽遇到开通流程繁琐、文档不足等问题,但整体功能满足预期。建议增强实时数据处理能力和数据可视化功能,以进一步提升用户体验。与同类工具相比,DataWorks在功能全面性、性能和开放性上表现突出,但也需优化界面设计和价格策略。新版Data Studio中的Notebook和智能助手Copilot提供了优秀的交互式编程和智能辅助,但仍需改善稳定性和集成度。
|
机器学习/深度学习 人工智能 监控
智能建筑管理系统:建筑能效的优化
【10月更文挑战第23天】智能建筑管理系统(IBMS)通过集成信息技术、自动化和通信技术,实现对建筑内设施的综合监控与管理,优化能效,提升舒适性和安全性。本文介绍IBMS的功能特点、应用成效及未来发展趋势,展示其在建筑能效优化中的重要作用。
|
数据采集 机器学习/深度学习 存储
【数据说话】当下的Python就业前景如何
以上便是我们做的一些微小工作,希望能给大家带来些帮助。当然,本案例中所有数据来自上述招聘网站的公开数据,与真实的市场需求有可能存在偏差,仅供参考。
|
SQL 关系型数据库 MySQL
深入解析MySQL视图、索引、数据导入导出:优化查询和提高效率
索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列。否则,数据库系统将读取每条记录的所有信息进行匹配。索引可以根据一个或多个列的值进行排序和搜索,提高查询时的效率。MySQL索引(Index)是一种特殊的数据结构,建立在表的列上,旨在加快数据库查询的速度通过在索引列上创建索引,数据库可以更快地定位和访问特定值,而无需扫描整个数据表。索引可以应用于单个列或多个列的组合,可以按升序或。
|
SQL 存储 Oracle
Oracle之3种表连接方式(排序合并连接、嵌套循环、哈希连接)
Oracle之3种表连接方式(排序合并连接、嵌套循环、哈希连接) 排序合并连接 1.2.4.2.1  排序合并连接 排序合并连接(Sort Merge Join)是一种两个表在做表连接时用排序操作(Sort)和合并操作(Merge)来得到连接结果集的表连接方法。
3661 0
|
人工智能 Linux 算法框架/工具
便捷、快速、稳定、高性能,以 GPU 实例演示 Alibaba Cloud Linux 3 对 AI 生态的支持龙蜥技术
在多维度的优化加持下,Alibaba Cloud Linux 3 解决了 AI 开发人员的痛点问题,让 AI 开发体验更容易更高效。
|
前端开发 JavaScript
路径中“./”、“../”、“/”代表的含义
路径中“./”、“../”、“/”代表的含义
762 0
|
人工智能 安全 算法
隐语小课|隐私求交(PSI)及其应用场景
隐语小课|隐私求交(PSI)及其应用场景
1095 0