当前位置: 首页 > 后端技术 > Java

java泛型

时间:2023-04-01 14:11:12 Java

java泛型什么是泛型?泛型类型(或泛型)是Java语言类型系统的扩展,支持创建可按类型参数化的类。您可以将类型参数视为使用参数化类型时指定类型的占位符,就像方法的形参是运行时传递的值的占位符一样。泛型的动机可以在Collection框架中看到。例如,Map类允许您将任意类的对象添加到Map,即使最常见的情况是在给定的map中保存特定类型(例如String)的对象。因为Map.get()定义为返回Object,所以一般需要将Map.get()的结果强制转换为想要的类型,如下代码所示:Mapm=newHashMap();m.put("key","blarg");Strings=(String)m.get("key");要编译程序,必须将get()的结果转换为String,并希望结果真的是一个String。但有可能有人在该映射中存储了字符串以外的内容,在这种情况下,上述代码将抛出ClassCastException。理想情况下,您可能会认为m是一个将String键映射到String值的Map。这使您可以消除代码中的强制转换,同时获得额外的类型检查层,以防止有人在集合中保存错误类型的键或值。这就是泛型所做的。泛型的好处Java语言中泛型的引入是一项重大改进。不仅语言、类型系统和编译器都发生了显着变化以支持泛型,而且类库也进行了大修,因此许多重要的类,例如集合框架,都变成了泛型。这带来了很多好处:类型安全。泛型的主要目标是提高Java程序的类型安全性。通过了解用泛型定义的变量的类型约束,编译器可以在更高程度上验证类型假设。如果没有泛型,这些假设只会存在于程序员的脑海中(或者,如果幸运的话,存在于代码注释中)。Java程序中的一种流行技术是定义其元素或键属于常见类型的集合,例如“字符串列表”或“字符串到字符串的映射”。通过在变量声明中捕获这些额外的类型信息,泛型允许编译器强制执行这些额外的类型约束。类型错误现在在编译时被捕获,而不是在运行时作为ClassCastException暴露。将类型检查从运行时转移到编译时可以帮助您更轻松地发现错误并可以提高程序的可靠性。消除演员阵容。泛型的一个附带好处是它们消除了源代码中的许多转换。这使代码更具可读性,并减少了出错的机会。虽然减少转换会降低使用泛型类的代码的冗长程度,但声明泛型变量会带来相应级别的冗长程度。比较下面的两个代码示例。此代码不使用泛型:Listli=newArrayList();li.put(新整数(3));整数i=(整数)li.get(0);此代码使用泛型:Listli=newArrayList();li.put(newInteger(3));Integeri=li.get(0);在简单程序中使用一次通用变量不会减少冗长。但是对于多次使用泛型变量的大型程序,可以实现累积的冗长减少。潜在的性能增益。泛型开辟了更大优化的可能性。在泛型的初始实现中,编译器将强制转换(如果没有泛型则由程序员指定)插入到生成的字节码中。但是,更多类型信息可供编译器使用这一事实为JVM未来版本的优化提供了可能性。由于泛型的实现方式,支持泛型需要(几乎)不需要更改JVM或类文件。所有工作都在编译器中完成,编译器生成的代码类似于您在没有泛型(和强制转换)的情况下编写的代码,只是类型安全性更高。泛型使用示例许多最好的泛型示例都来自集合框架,因为泛型允许您对集合中的元素指定类型约束。考虑这个使用Map类的示例,它涉及一定程度的优化,即Map.get()返回的结果确实是一个字符串:Mapm=newHashMap();m.put("key","blarg");Strings=(String)m.get("key");如果有人在地图中放置了字符串以外的内容,上面的代码将抛出ClassCastException。泛型允许您表达类型约束,即m是一个将String键映射到String值的Map。这消除了代码中的转换,同时获得了额外的类型检查层,以防止有人在集合中保存错误类型的键或值。以下代码示例显示了JDK5.0中集合框架中Map接口的部分定义:publicinterfaceMap{publicvoidput(Kkey,Vvalue);publicVget(Kkey);}注意接口的两个附加项:类型参数K和V的类级别规范,它们表示在声明Map类型的变量时指定类型的占位符。K和V在get()、put()和其他方法的方法签名中使用。要获得使用泛型的好处,您必须在定义或实例化Map类型的变量时为K和V提供具体值。以相对直观的方式执行此操作:Mapm=newHashMap();m.put("key","blarg");Strings=m.get("key");使用Map的通用版本时,您不再需要将Map.get()的结果转换为String,因为编译器知道get()将返回一个String。使用泛型的版本中没有少打字;事实上,与使用强制转换的版本相比,需要更多的输入。使用泛型只会带来额外的类型安全性。因为编译器更了解你将放入Map的键和值的类型,所以类型检查从执行时转移到编译时,这提高了可靠性并加快了开发速度。向后兼容性将泛型引入Java语言的一个重要目标是保持向后兼容性。尽管JDK5.0标准类库中的许多类(例如集合框架)已被通用化,但是使用集合类(例如HashMap和ArrayList)的现有代码将继续在JDK5.0中不加修改地工作。当然,不利用泛型的现有代码将无法获得泛型的类型安全优势。2.泛型基本类型参??数在定义泛型类或声明泛型类的变量时,使用尖括号来指定形式类型参数。形式类型参数和实际类型参数之间的关系类似于形式方法参数和实际方法参数之间的关系,只是类型参数表示类型而不是值。泛型类中的类型参数几乎可以用在任何可以使用类名的地方。例如,下面是java.util.Map接口定义的摘录:publicinterfaceMap{publicvoidput(Kkey,Vvalue);publicVget(Kkey);}Map接口由两个类型参数化组成,这两个类型是键类型K和值类型V。(不使用泛型)接受或返回对象的方法现在使用K或V在他们的方法签名中,表明附加的类型约束位于Map的规范之下。在声明或实例化泛型对象时,必须指定类型参数的值:Mapmap=newHashMap();请注意,在此示例中,类型参数必须指定两次。一次是在声明变量映射的类型时,一次是在选择HashMap类的参数化时,以便可以实例化正确类型的实例。编译器在遇到类型为Map的变量时知道K和V现在绑定为字符串,因此它知道对此类变量调用Map.get()将产生字符串。任何类都可以有类型参数,异常类型、枚举或匿名内部类除外。命名类型参数的推荐命名约定是对类型参数使用大写单字母名称。这偏离了C++约定(请参阅附录A:与C++模板的比较),并反映了大多数泛型类将具有少量类型参数的假设。对于常见的通用模式,推荐的名称是:K-key,比如地图的key。V–Values,比如Lists和Sets的内容,或者Maps中的values。E-异常类。T-通用。