
大家好!我是保护小周ღ,本期为大家带来的是 Java的泛型,会来大家初步了解什么是泛型,以及泛型的使用,感受一手泛型的思想,面向对象编程太爽了~
目录

泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化(传基本数据类型的包装类)以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。 —————搜狐百科
泛型是在JDK1.5引入的新的语法,泛型:从字面上来讲:“泛” 我觉得是很多的意思,“型”即是,相当于通用类型。从代码上讲,就是对类型实现了参数化。什么类型都可以传参;
class 泛型类名称 <类型参数列表> {
}
class genericName <T1,T2,T3,T4……>{
}
class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ {
// 这里可以使用类型参数
}
class ClassName<T1, T2, ...,Tn>extends ParentClass<T1> {
// 可以只使用部分类型参数
}
1. 类名后的<T > 代表占位符,表示当前类是一个泛型类,语言规范<大写字母>,一般使用有意义的字母,见名思意,T 代表 Type 用于描述单个类型 ,E代表 Element 用于描述将来会使用多个类型,其实任意 单词都可,但要注意代码规范即可。
2. 不能 new 泛型类型的数组,数组和泛型之间的一个重要区别是它们如何强制执行类型检查。具体来说,数组在运行时存储和检查类型信息。然而,泛型在编译时检查类型错误。如果使用泛型数组,运行的时候,直接转给某类型的数组,编译器认为是不安全的,且定义数组需要一个确定类型,而泛型,Java 不认为是一种确认类型,是不安全的。
泛型类的使用:
泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
MyArray<Integer> list = new MyArray<Integer>();
在Java 中,因为基本数据类型不是继承 Object 类,为了能在泛型代码中使用基本数据类型,且Java又是 完全面向对象的程序设计语言,所以每一个基本数据类型都有对应的包装类,包装类包含了基本数据类型,可以将基本数据类型转换成引用类型,那么一个类,里面就有许多方法,例如:包装类.value() ;就可以把某种数据类型转换成 包装类对应的基本数据类型(在符合规则的情况下),有了包装类,基本数据类型可以面向对象编程。
例:
以此类推,只要符合规则,各类型之间也可以使用包装类的方法进行转换,但是 boolean 类型是不可以转换的。

装箱/装包 :把基本数据类型转换成 引用类型(对应的包类型)

在进行自动“装箱”的时候,IDEA会自动调用一个 Integer.valueOf() 方法,来帮我们转换,
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

拆箱:把引用类型转化成基本数据类型

public int intValue() {
return value;
}
从代码上讲,泛型就是对类型实现了参数化。什么类型都可以传参;那为啥不直接使用 Objcet 来接收数据呢? 包装类也是继承了 Objcet 类的,我说:可以,但是不好用!
例题:
实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值。
用Objcet 类型来做这个题 看效果:
class UniversalArray {
private Object[] obj = new Object[3];//定义一个Object 类型的数组
public Object getObj(int pos) { //返回数组pos 下标的值
return obj[pos];
}
public void setObj(int pos, Object val) { //给pos下标的数组元素赋值为val
this.obj[pos] = val;
}
}
public class Test3 {
public static void main(String[] args) {
UniversalArray array = new UniversalArray();
array.setObj(0,10); //调用set构造方法赋值
array.setObj(1,"abc");
array.setObj(2,3.14);
// 我们返回 Object 类型的数据需要手动强转才可以使用,
int val1 = (int) array.getObj(0);
String val2 = (String) array.getObj(1);
double val3 = (double) array.getObj(2);
System.out.println(val1);
System.out.println(val2);
System.out.println(val3);
}
}

通过以上代码,我们确实使用Object 数组 做到了什么数据都可以存储,但是在获取数据的时候,必须要强制类型转换才可以使用,而且你还要知道 强转的类型才可以,在数据量特别大且复杂的时候,就把自己给绕晕了,不建议使用。
用泛型这种编程思量来做这个题 看效果:
首先我们想要的效果是,一个通用性数组,可以存储任意你指定类型的数据,但是最好一次只存一种类型的数据(使用时避免头晕),且不需要对拿到的数据进行强转即可使用。
class UniversalArray<E> { //泛型类
private Object[] obj = new Object[3];//定义一个Object 类型的数组
public E getObj(int pos) { //返回数组pos 下标的值
return (E) obj[pos]; //强换为指定类型的数据类型
}
public void setObj(int pos, E val) { //给pos下标的数组元素赋值为val
this.obj[pos] = val;
}
}
public class Test3 {
public static void main(String[] args) {
//实例化一个泛型类对象 array1
UniversalArray<Integer> array1 = new UniversalArray<Integer>();
// < > 中指定的的参数必须是引用类型,这里我们指定他为 Integer 类型
array1.setObj(0,10); //调用set构造方法对Object 数组赋值
array1.setObj(1,20);
array1.setObj(2,30);
//Object 类型被强转为 E 类类型,而 E 类型又被我们 指定为 Integer
int val1 = array1.getObj(0); //所以这里发生的是 隐形的拆箱操作,将Integer 引用类型转换成基本类型
int val2 = array1.getObj(1);
int val3 = array1.getObj(2);
System.out.println(val1);
System.out.println(val2);
System.out.println(val3);
//实例化一个泛型类对象 array2
UniversalArray<String> array2 = new UniversalArray<String>();
// < > 中指定的的参数必须是引用类型,这里我们指定他为 String 类型
array2.setObj(0,"1233"); //调用set构造方法对Object 数组赋值
array2.setObj(1,"abc");
array2.setObj(2,"helloWorld");
//Object 类型被强转为 E 类类型,而 E 类型又被我们 指定为 String 类型
String str1 = array2.getObj(0);
String str2 = array2.getObj(1);
String str3 = array2.getObj(2);
System.out.println(str1 + " " + str2 + " " + str3);
}
}

1. 我们定义了一个 泛型类,泛型类中有一个Object 类型的数组,我们提供了get 和 set 方法可以对该数组进行操作。
2. 在测试类Test3 实例化了两个 泛型类的对象,array1 和 array2 但是我们对其 < >中指定的数据类型不一样,array1 指定为 Integer ,所以我们可以就可以将 array1 该对象的 Object 数组当成 Integer 类型的数组 进行操作,array2 指定为 String 类型, 所以我们就拥有了一个 String 类型数组。
3. 我们还可以定义 array3 、array4、 array5 ……许多对象,将他们指定为不同的数据类型,拥有通用类型的数组,实际上我们只定义了一个泛型类,这样是不是大大减少了代码的冗余。
4. 泛型的主要目的就是:指定当前的当前容器,要持有某个类型的对象,就像是传参,你希望他是什么类型,就传入什么类型参数。
泛型:在存储数据的时候,相当于预定了将来的数据类型,实际上还是Object 类型,在获取元素的时候,自动的帮我们进行类型转换。泛型实际上是编译时期的一种设计思想(把类型作为参数传递),在运行的时候,就没有这个概念了。

泛型只能接受类,所有的基本数据类型必须使用包装类 。
泛型的上界是什么意思呢,在定义泛型类时,有时需要对传入的类型变量做一定的约束,或者是继承一些功能,可以通过类型边界来约束。
class 泛型类名称<类型形参 extends 类型边界> {
......
}
举个例子:


以上代码更能体现泛型是在编译时期对类型进行检查的机制。
也可以通过继承一些功能
class Alg <E extends Comparable<E>>{ //泛型的上界
public E findMax(E[] array) {
E max = array[0];
for (int i = 0; i < array.length; i++) {
if(max.compareTo(array[i]) < 0) {
max = array[i];
}
}
return max;
}
}
“E” 类型是可以把他(理解)是通用类型,他跟 Object 是不一样的,Object 是具体的,而泛型与之相比是抽象的概念,所以以 “E” 定义的变量没有具体的类型,也没有继承对应包装类的各种方法,所以在这种情况下,要想使用具体类型的方法,我们就使得“E” 这个“类型”继承一个Comparable 接口或者是其他接口,这样 “E”类型的 变量,方法等就可以实现 Comparable 接口里的方法。
方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) {
}
有泛型的类,那自然有泛型的方法,接下来博主给大家演示一手泛型方法有多厉害。
public class Test4 {
//交换数据
private static <E> void swop(E[] arr, int i, int j) {
E tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static <E extends Comparable<E>> void sort (E[] array) {
//冒泡
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length - i - 1; j++) {
if( array[j].compareTo(array[j+1]) > 0) {
swop(array, j, j+1);
}
}
}
}
public static void main(String[] args) {
//整型数组
Integer[] arr = {10,2,1,3,4,5};
Test4.<Integer>sort(arr);
System.out.println(Arrays.toString(arr));
Double[] doubArr = {3.14, 2.2, 5.1, 1.11,3.1};
Test4.sort(doubArr);
System.out.println(Arrays.toString(doubArr));
Character[] charArr = {'b','d','c','a','e'};
Test4.sort(charArr);
System.out.println(Arrays.toString(charArr));
}
}

根据以上代码:我们就可以体验到泛型的运用场景,不管是泛型的类,还是泛型的方法,通用性都非常强。

至此,初识Java 的泛型的内容博主已经分享完了,希望对大家有所帮助,如有不妥之处欢迎批评指正。

本期收录于博主的专栏——JavaSE,适用于编程初学者,感兴趣的朋友们可以订阅,查看其它“JavaSE基础知识”。
感谢每一个观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*
文章存在借鉴,如有侵权请联系修改删除!
前面一篇关于智能合约翻译文讲到了,是一种计算机程序,既然是程序,那就可以使用程序语言去编写智能合约了。而若想玩区块链上的项目,大部分区块链项目都是开源的,能看得懂智能合约代码,或找出其中的漏洞,那么,学习Solidity这门高级的智能合约语言是有必要的,当然,这都得在公链``````以太坊上,毕竟国内的联盟链有些是不兼容Solidity。Solidity是一种面向对象的高级语言,用于实现智能合约。智能合约是管理以太坊状态下的账户行为的程序。Solidity是运行在以太坊(Ethereum)虚拟机(EVM)上,其语法受到了c++、python、javascript影响。Solidity是静态类型
Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法,Linux…感兴趣就关注我吧!你定不会失望。目录1.ls显示当前目录下的文件内内容2.pwd-显示用户当前所在的目录3.cd-改变工作目录。将当前工作目录改变到指定的目录下1.cd-回到上一次待的工作空间2.cd..返回上一层目录1.相对路径:cd../aurora2.绝对路径:cd/home/aurora/lesson1/aurora3.cd~进入用户家目录4.cd/进入root目录4.mkdir-新建目录5.rmdir/rm-删除1.rmdir删除空文件夹2.rm删除1.rm-f2.rm-i3.rm-r1.ls显示当前目
在下面的链接(MDN站点)上它说“字符串泛型是非标准的,已弃用并且将来可能会被删除。请注意,如果不使用下面提供的填充程序,您不能跨浏览器依赖它们。“他们所指的方法是否是他们在该声明下方提供的垫片中列出的方法?这是我见过的唯一提到短语“字符串泛型”的地方,所以让我很困惑。对于数组泛型也有同样的问题,因为该站点也提到了类似的情况。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#String_generic_methodshttps://developer.mozi
我需要根据变量在Typescript泛型类中的类型设置默认值,如下所示classMyClass{myvariable:T//HereIwanttosetthevalueofthisvariable//withthedefaultvalueofthetypepassedin'T'}例如,如果T是数字,那么变量myvariable的默认值应该是“0”,同样对于字符串,它应该是空字符串等等。 最佳答案 您不能这样做,因为T的实际类型只会在运行时才知道。你可以做什么:abstractclassMyClass{myvariable:T;con
我正在尝试编写一个函数,通过将任意TypedArray作为输入来扩展/缩小TypedArray,并返回一个具有不同大小的新的相同类型的TypedArray,并将原始元素复制到其中。例如,当您通过时,newUint32Array([1,2,3])新尺寸5,它将返回newUint32Array([1,2,3,0,0]).exportconstresize=(source:ArrayLike,newSize:number,):ArrayLike=>{if(!source.length){returnnewsource.constructor(newSize);}newSize=typeofn
gtest是Google开发的一个开源单元测试框架,代码提供丰富的注释和实例,参考实际用例可以很快上手基本单元测试,丰富的代码注释能够让有兴趣的开发者深入了解gtest的代码结构并做部分针对性的二次开发。gtest主要针对c/c++提供了针对函数接口和类方法丰富测试方法,针对单元测试特有的数据或者代码反复编写的这种特性做了集成和优化,满足当前绝大部分对于单元测试的需求。其有如下特点:自动收集测试用例,无需开发者再次组织提供强大的断言集,支持包括布尔、整型、浮点型、字符串等。提供断言方法自定义扩展提供死亡测试功能使用参数化自动生成多个相似的测试用例可以将公共的用例初始化和清理工作放入测试夹具中,
这个问题在这里已经有了答案:HowdoIconvertanexistingcallbackAPItopromises?(24个答案)关闭7年前。我如何用promise包装一个可以在内部具有同步/非同步功能的函数?我已经调用了下面的函数action[fn](req,res);在函数fn(在下面的例子中)运行可以有内部(我对每个函数使用动态调用)同步或像下面的例子那样异步,Howitsrecommendedtowrapitinpromise.Howtohandleerrorsifany...我使用nodeJS应用程序run:function(req,res,filePath){varwri
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭4年前。Improvethisquestion我正在为我的JS库寻找文档生成器。我找到JSDuck最全面和最强大的。但我没有看到使用其语法为泛型类和函数定义类型变量的方法。快速浏览流行的JS文档生成器让我觉得它们都没有这样做的能力。这是我正在寻找的伪示例:/***@classMyArray*Myperfectarrayclass.*@typevarT*/MyArray=function().../***@cl
一鸿蒙简介HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。在传统的单设备系统能力基础上,HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念,能够支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备,提供全场景(移动办公、运动健康、社交通信、媒体娱乐等)业务能力。HarmonyOS提供了支持多种开发语言的API,供开发者进行应用开发。支持的开发语言包括Java、XML(ExtensibleMarkupLanguage)、C/C++、JS(JavaScript)、CSS(CascadingStyleSheets)和HML(HarmonyOSMarkupLan
我以前从未用静态类型语言编写过。我主要使用Javascript进行开发,最近我有兴趣了解更多有关FB的Flowtype的信息。我发现文档写得很好,而且我理解了其中的大部分内容。但是我不太明白generics的概念.我试过用谷歌搜索一些例子/解释,但没有成功。谁能解释一下什么是泛型,它们主要用于什么,并可能提供一个例子? 最佳答案 假设我想编写一个只存储单个值的类。显然这是人为的;我保持简单。实际上这可能是一些集合,比如Array,可以存储多个值。假设我需要包装一个number:classWrap{value:number;const