java泛型方法 通配符_Java泛型教程–示例类,接口,方法,通配符等

java泛型方法 通配符

泛型是Java编程的核心功能之一,它是Java 5中引入的。如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它。 将泛型与集合类一起使用非常容易,但是它提供了比仅创建集合类型更多的功能,我们将在本文中尝试学习泛型的功能。 如果我们使用专业术语,对泛型的理解有时会变得混乱,因此我将尽量保持其简单易懂。
在本教程中,我们将研究泛型的以下主题。 java-generics-tutorial

  1. Java泛型示例
  2. 具有类和接口的泛型
  3. 泛型类型命名约定
  4. 方法和构造函数中的泛型
  5. 泛型有界类型参数
  6. 泛型与继承
  7. 通用类和子类型
  8. 通用通配符
    1. 泛型上界通配符
    2. 泛型无界通配符
    3. 泛型下界通配符
  9. 使用泛型通配符进行子类型化
  10. 类型擦除

Java泛型示例

Java 5中添加了泛型,以提供编译时类型检查并消除使用集合类时常见的ClassCastException风险。 整个收集框架都进行了重写,以使用泛型进行类型安全。 让我们看看泛型如何帮助我们安全地使用集合类。

List list = new ArrayList();
list.add("abc");
list.add(new Integer(5)); //OKfor(Object obj : list){String str=(String) obj; //type casting leading to ClassCastException at runtime
}

上面的代码可以很好地编译,但是在运行时抛出ClassCastException,因为我们试图将列表中的Object强制转换为String,而其中一个元素是Integer类型。 在Java 5之后,我们使用如下收集类。

List<String> list1 = new ArrayList<String>(); // java 7 ? List<String> list1 = new ArrayList<>(); 
list1.add("abc");
//list1.add(new Integer(5)); //compiler errorfor(String str : list1){//no type casting needed, avoids ClassCastException
}

请注意,在创建列表时,我们已指定列表中元素的类型为String。 因此,如果我们尝试在列表中添加任何其他类型的对象,则该程序将引发编译时错误。 还要注意,在for循环中,我们不需要类型转换列表中的元素,因此在运行时删除了ClassCastException。

具有类和接口的泛型

我们可以使用泛型类型定义自己的类和接口。 泛型类型是通过类型进行参数化的类或接口。 我们使用尖括号(<>)来指定type参数。

为了了解其好处,可以说我们有一个简单的类:

package com.journaldev.generics;public class GenericsTypeOld {private Object t;public Object get() {return t;}public void set(Object t) {this.t = t;}public static void main(String args[]){GenericsTypeOld type = new GenericsTypeOld();type.set("Pankaj"); String str = (String) type.get(); //type casting, error prone and can cause ClassCastException}
}

请注意,在使用此类时,我们必须使用类型转换,并且它可以在运行时产生ClassCastException。 现在,我们将使用泛型来重写具有泛型类型的相同类,如下所示。

package com.journaldev.generics;public class GenericsType<T> {private T t;public T get(){return this.t;}public void set(T t1){this.t=t1;}public static void main(String args[]){GenericsType<String> type = new GenericsType<>();type.set("Pankaj"); //validGenericsType type1 = new GenericsType(); //raw typetype1.set("Pankaj"); //validtype1.set(10); //valid and autoboxing support}
}

注意main方法中GenericsType类的使用。 我们不需要进行类型转换,并且可以在运行时删除ClassCastException。 如果我们在创建时未提供类型,则编译器将发出警告,“ GenericsType是原始类型。 泛型类型GenericsType <T>的引用应参数化”。 当我们不提供类型时,该类型将成为Object ,因此它同时允许String和Integer对象,但是我们应始终尝试避免这种情况,因为在处理会产生运行时错误的原始类型时,我们将必须使用类型转换。

提示 :我们可以使用@SuppressWarnings("rawtypes")注释来取消编译器警告,请参阅Java注释教程

还要注意,它支持Java自动装箱 。

可比接口是接口中泛型的一个很好的例子,它写为:

package java.lang;
import java.util.*;public interface Comparable<T> {public int compareTo(T o);
}

以类似的方式,我们可以在接口和类中使用泛型。 我们也可以像在Map界面中那样具有多个类型参数。 同样,我们也可以为参数化类型提供参数化值,例如new HashMap<String, List<String>>(); 已验证。

泛型类型命名约定

命名约定可以帮助我们轻松地理解代码,拥有命名约定是Java编程语言的最佳实践之一。 因此,泛型也带有它自己的命名约定。 通常,类型参数名称是单个大写字母,以使其易于与Java变量区分开。 最常用的类型参数名称为:

  • E –元素(由Java Collections Framework广泛使用,例如ArrayList,Set等)
  • K –键(在地图中使用)
  • N –数字
  • T –类型
  • V –值(在地图中使用)
  • S,U,V等–第二,第三,第四类型

方法和构造函数中的泛型

有时我们不希望对整个类进行参数化,在这种情况下,我们也可以在方法中使用泛型类型。 由于构造函数是一种特殊的方法,因此我们也可以在构造函数中使用泛型类型。

这是一个类,显示方法中的泛型类型的示例。

package com.journaldev.generics;public class GenericsMethods {//Generics in methodpublic static <T> boolean isEqual(GenericsType<T> g1, GenericsType<T> g2){return g1.get().equals(g2.get());}public static void main(String args[]){GenericsType<String> g1 = new GenericsType<>();g1.set("Pankaj");GenericsType<String> g2 = new GenericsType<>();g2.set("Pankaj");boolean isEqual = GenericsMethods.<String>isEqual(g1, g2);//above statement can be written simply asisEqual = GenericsMethods.isEqual(g1, g2);//This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets.//Compiler will infer the type that is needed}
}

注意isEqual方法签名显示了在方法中使用泛型类型的语法。 还要注意如何在我们的java程序中使用这些方法。 我们可以在调用这些方法时指定类型,也可以像普通方法一样调用它们。 Java编译器足够聪明,可以确定要使用的变量的类型,这种功能称为类型推断

泛型有界类型参数

假设我们想限制可以在参数化类型中使用的对象的类型,例如,在比较两个对象的方法中,并且我们要确保接受的对象是可比较的。 要声明一个有界的类型参数,请列出该类型参数的名称,然后是extends关键字,然后是其上限,类似于下面的方法。

public static <T extends Comparable<T>> int compare(T t1, T t2){return t1.compareTo(t2);}

这些方法的调用与无界方法类似,不同之处在于,如果我们尝试使用任何非Comparable的类,则会引发编译时错误。

绑定类型参数可以与方法以及类和接口一起使用。

泛型也支持多个范围,即<T扩展A&B&C>。 在这种情况下,A可以是接口或类。 如果A是类,则B和C应该是接口。 在多个范围内,我们不能有多个类。

泛型与继承

我们知道,如果A是B的子类,则Java继承允许我们将变量A分配给另一个变量B。因此,我们可能认为可以将A的任何泛型类型分配给B的泛型类型,但事实并非如此。 让我们用一个简单的程序看看。

package com.journaldev.generics;public class GenericsInheritance {public static void main(String[] args) {String str = "abc";Object obj = new Object();obj=str; // works because String is-a Object, inheritance in javaMyClass<String> myClass1 = new MyClass<String>();MyClass<Object> myClass2 = new MyClass<Object>();//myClass2=myClass1; // compilation error since MyClass<String> is not a MyClass<Object>obj = myClass1; // MyClass<T> parent is Object}public static class MyClass<T>{}}

我们不允许将MyClass <String>变量分配给MyClass <Object>变量,因为它们不相关,实际上MyClass <T>的父对象是Object。

通用类和子类型

我们可以通过扩展或实现来泛型一个通用类或接口。 一个类或接口的类型参数与另一类或接口的类型参数之间的关系由extend和Implements子句确定。

例如,ArrayList <E>实现扩展Collection <E>的List <E>,因此ArrayList <String>是List <String>的子类型,而List <String>是Collection <String>的子类型。

只要不更改type参数,子类型关系就会保留,下面显示了多个type参数的示例。

interface MyList<E,T> extends List<E>{
}

List <String>的子类型可以是MyList <String,Object>,MyList <String,Integer>等。

通用通配符

问号(?)是泛型中的通配符,表示未知类型。 通配符可以用作参数,字段或局部变量的类型,有时还可以用作返回类型。 在调用通用方法或实例化通用类时,我们不能使用通配符。 在以下各节中,我们将学习上界通配符,下界通配符和通配符捕获。

泛型上界通配符

上限通配符用于放松方法中对变量类型的限制。 假设我们要编写一个将返回列表中数字总和的方法,那么我们的实现将是这样的。

public static double sum(List<Number> list){double sum = 0;for(Number n : list){sum += n.doubleValue();}return sum;}

现在,上述实现的问题在于它不适用于List of Integers或Doubles,因为我们知道List <Integer>和List <Double>不相关,这在使用上限通配符很有用时。 我们将泛型通配符与extends关键字和上限类或接口一起使用,这将允许我们传递上限或其子类类型的参数。

可以像下面的程序一样修改上面的实现。

package com.journaldev.generics;import java.util.ArrayList;
import java.util.List;public class GenericsWildcards {public static void main(String[] args) {List<Integer> ints = new ArrayList<>();ints.add(3); ints.add(5); ints.add(10);double sum = sum(ints);System.out.println("Sum of ints="+sum);}public static double sum(List<? extends Number> list){double sum = 0;for(Number n : list){sum += n.doubleValue();}return sum;}
}

就像按照接口编写代码一样,在上面的方法中,我们可以使用上限类Number的所有方法。 请注意,对于上界列表,除null之外,我们不允许将任何对象添加到列表中。 如果我们尝试在sum方法内将元素添加到列表中,则该程序将无法编译。

泛型无界通配符

有时,我们希望通用方法适用于所有类型,在这种情况下,可以使用无界通配符。 与使用<?相同 扩展Object>。

public static void printData(List<?> list){for(Object obj : list){System.out.print(obj + "::");}}

我们可以为printData方法提供List <String>或List <Integer>或任何其他类型的Object列表参数。 与上限列表类似,我们不允许在列表中添加任何内容。

泛型下界通配符

假设我们要在方法中将整数添加到整数列表中,我们可以将参数类型保持为List <Integer>,但它将与Integers捆绑在一起,而List <Number>和List <Object>也可以容纳整数,因此我们可以使用下限通配符来实现此目的。 我们使用带有super关键字和下限类的泛型通配符(?)来实现此目的。

在这种情况下,我们可以传递下界或下界的任何超级类型作为参数,java编译器允许将下界对象类型添加到列表中。

public static void addIntegers(List<? super Integer> list){list.add(new Integer(50));}

使用泛型通配符进行子类型化

List<? extends Integer> intList = new ArrayList<>();
List<? extends Number>  numList = intList;  // OK. List<? extends Integer> is a subtype of List<? extends Number>

类型擦除

添加了泛型以在编译时提供类型检查,并且在运行时无用,因此Java编译器使用类型擦除功能来删除字节码中的所有泛型类型检查代码,并在必要时插入类型转换。 类型擦除可确保不会为参数化类型创建新的类; 因此,泛型不会产生运行时开销。

例如,如果我们有如下通用类;

public class Test<T extends Comparable<T>> {private T data;private Test<T> next;public Test(T d, Test<T> n) {this.data = d;this.next = n;}public T getData() { return this.data; }
}

Java编译器用第一个绑定接口Comparable替换了绑定类型参数T,如下代码:

public class Test {private Comparable data;private Test next;public Node(Comparable d, Test n) {this.data = d;this.next = n;}public Comparable getData() { return data; }
}

多数民众赞成在Java中的泛型,泛型是一个非常大的话题,需要大量时间才能有效地理解和使用它。 本文旨在提供泛型的基本细节,以及如何使用泛型来扩展程序的类型安全性。

参考: Java泛型教程–示例类,接口,方法,通配符以及我们的JCG合作伙伴 Pankaj Kumar在Developer Recipes博客上的更多内容。

翻译自: https://www.javacodegeeks.com/2013/07/java-generics-tutorial-example-class-interface-methods-wildcards-and-much-more.html

java泛型方法 通配符

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu中mysql怎么退出命令_Ubuntu下MySQL简单操作

安装Ubuntu下安装常规软件都比较简单&#xff0c;直接使用apt-get即可。安装步骤如下&#xff1a;输入mysql命令系统会提示没有安装这个软件&#xff0c;如下图&#xff1a;根据系统提示&#xff0c;执行下面命令进行安装。$ sudo apt-get install mysql-client-core-5.6$ sudo…

虚拟现实技术利用计算机,虚拟现实技术在计算机专业教学中的应用思考

【摘要】虚拟现实技术在计算机教学中进行应用&#xff0c;其能够有效提高学生的学习兴趣&#xff0c;培养学生的探索能力和创新能力。本文对虚拟现实技术的概念和特点进行了阐述&#xff0c;并且分析了虚拟现实技术在计算机实践教学中的实践应用&#xff0c;从而有效提高计算机…

计算机二级web题目(2)--HTTP基础

1[单选题]HTTP协议是运行于&#xff08;C&#xff09;协议上的应用层协议。 A. FTP B. SMTP C.TCP D. UDP 解析&#xff1a;①传输控制协议TCP是传输层通信协议。 2[单选题] HTTP协议的消息有(B)两种类型。 A. 发送消息和接收消息 B. 请求消息和响应消息 C. 消息头和消息体 D. …

mpu 配置内存空间_PCIE的内存地址空间、I/O地址空间和配置地址空间

pci设备与其它接口的设备(如i2c设备)最大的不同是存在内存地址空间和配置地址空间首先区分一下IO空间和内存空间cpu会访问的设备一般有内存和外设寄存器&#xff0c;如下图所示。x86架构采用独立编址将内存操作与外设IO操作分开了才有了内存空间和IO空间的区分&#xff0c;x86平…

如何使用Java和XML Config在Spring Security中启用HTTP基本身份验证

在上一篇文章中&#xff0c;我向您展示了如何在Java应用程序中启用Spring安全性 &#xff0c;今天我们将讨论如何使用Spring Security 在Java Web应用程序中启用Basic HTTP身份验证 。 如果您使用的是Spring Security 3.1或更低版本&#xff0c;我将向您展示如何同时使用Java配…

网络通信协议是计算机网络的组成部分之一,通信互联网技术考点精讲之计算机网络系统的组成...

下面是由希赛小编整理的通信互联网技术考点精讲之计算机网络系统的组成&#xff0c;希望能帮助学友们。具体内容如下&#xff1a;计算机网络系统的组成计算机网络通常由3部分组成&#xff1a;资源子网、通信子网和通信协议&#xff1f;(1)资源子网&#xff1a;是网络中实现资源…

centos安装llvm_Linux CentOS上编译并安装Clang教程

如何在Linux CentOS上编译并安装Clang&#xff1f;下面小编为大家具体的介绍一下&#xff0c;解决你在安装Clang遇到的一系列问题。一、Minimal版CentOS安装Clang前的环境准备1&#xff0c;安装gcc&#xff1a;yum install gcc2&#xff0c;安装g&#xff1a;yum install gcc-c…

win10下JDK环境变量配置与IDEA开发工具清晰简洁步骤,迈出Java学习第一步

文章目录一、JDK下载二、win10下环境变量配置三、开发工具IDEA安装一、JDK下载 可以直接去官网下载&#xff0c;推荐下载JDK8.0版本 也可以这个网盘里面找一下下载&#xff1a;Windows下JDK8.0 提取码&#xff1a;0909 安装的时候建议jdk和jre都。 二、win10下环境变量配置 …

双非计算机专业考研西安交通大学,2020双非一战计算机专硕初试403经验贴

本帖最后由 Johnsonw 于 2020-7-3 10:59 编辑先自我介绍一下&#xff0c;我初试403分&#xff0c;专业课134分&#xff0c;本科是双非&#xff0c;无项目经历&#xff0c;无科研经历&#xff0c;一战西安交通大学&#xff0c;最终成功上岸。初试&#xff1a;参考书目西安交通大…

计算机二级web题目(3)--HTML基础

1 [单选题] HTML是一种标记语言。它是由&#xff08;C&#xff09;解释执行的。 A. 不需要解释 B. Windows C. 浏览器 D. 标记语言处理软件 2 [单选题] 在HTML文档中用于表示页面标题的标记对是(D)。 A. <head></head> B. <header></header> C. <Ca…

连不上机器判断机器状态_KUKA机器人为什么KPP故障联不上,断电重启hou报RDC连接连接不上...

1.RDC连不上出现的现象: 通过指示灯的判断是最简单快捷的,如果是坏了可以直接提示RDC的故障,如果灯不亮可直接判断是RDC坏了或者是线没连上.如果RDC卡连不上,指示是不亮的!那么KSP或KPP网络断,同样会引起RDC不能读取数据,这是问什么呢?表面上看在KCB总线中KSP与KPP是串行连接的…

分布式部署_业务模块化打造单体和分布式部署同步支持方案

我在2019年中国.NET开发者峰会上为大家分享了我们的微服务电商安全工程实践&#xff0c;那次会议分享的高清录播已经上传到我的腾讯课堂&#xff0c;大家可以通过底部的小程序打开直接观看(复习)。在大会上跟大家提到&#xff0c;我们当时只有4个人的创业团队。追求的是一个既可…

计算机二级web题目(4)--CSS基础

1 [单选题] CSS指的是下列&#xff08;B&#xff09;的缩写。 A. Computer style Sheets B. Cascading style Sheets C. Creative stye Sheets D. Colerful siyle Sheets 2 [单选魃] 在HTML文档中,应该在下列哪个部分引用外部样式表?&#xff08;D&#xff09; A. 文档的末尾 …

dozer bean_使用Dozer框架进行Bean操作

dozer bean介绍 如您所知&#xff0c;您可以在任何操作系统中将文件或文件夹从源位置复制到目标位置。 您是否考虑过复制基本上是POJO的java对象&#xff1f; 在很多情况下&#xff0c;您需要将源bean的内容复制到目标bean。 我不关心对象的拷贝构造函数&#xff0c;浅拷贝或深…

英语作文计算机主板,(完整版)电脑主板bios英文版的中英文对照翻译.pdf

电脑主板 BIOS 英文版的中英文对照翻译让你的电脑 BIOS 知识迅速提高滴。 Time/System Time时间 / 系统时间Date/System Date 日期/ 系统日期Level 2 Cache 二级缓存System Memory 系统内存Video Controller 视频控制器Panel Type 液晶屏型号Audio Controller 音频控制器Modem …

怎么修改提交git是的用户名_git 修改提交邮箱以及用户名-亲测

一.查看git配置$ git config --list 此命令会列出所有GIT当时能找到的配置...查看 列表项[email protected] 邮箱user.name123 用户名二.修改邮箱和用户名1.重新设置邮箱和用户名$ git config --global user.email"[email protected]&…

简而不漏,300字Java标识符命名规则规范,看一遍就可以记住,包名类名变量名常量名,让命名有迹可循

1.标识符命名规则 &#xff08;如果不遵循&#xff0c;编译不通过&#xff0c;需要严格遵守&#xff09; 由26个英文字母大小写&#xff0c;0-9&#xff0c;_&#xff0c;$组成不可以数字开头不可使用关键字和保留字&#xff0c;可以包含关键字和保留字严格区分大小写不能包含…

html文字依次显示,利用定时器和css3动画制作文字依次渐变显示的效果

如上图&#xff0c;这种效果看着是不是挺“柔”的附代码文字一次渐变出现body{background-color: #333333;padding: 20px;-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;}div,span{color: #ffffff;font-size: 30px;}.hidden{display: no…

面向Java程序员的20大Spring REST面试问题答案

大家好&#xff0c;过去两周来&#xff0c;我一直在与Spring教程共享一些REST&#xff0c;今天&#xff0c;我将向申请Web开发人员角色的Java开发人员共享一些常见的Spring和REST面试问题。 由于Spring Framework是用于开发Java Web应用程序和RESTful Web Services的最受欢迎的…

你还认识变量吗?Java基础学习不可略过的基本语法,简而不漏,变量的定义赋值和分类,系统认识Java中的变量有哪些?

文章目录变量的声明和赋值变量分类变量的声明和赋值 class VariableTest{public static void main(String[] args) {//变量的定义int myAge 21;//变量的使用System.out.println(myAge);//变量的声明int myNumber;//变量的赋值myNumber 9090;} }特别注意&#xff1a; ①定义变…