JAVA泛型
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了JAVA泛型,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8905字,纯文字阅读大概需要13分钟。
内容图文
![JAVA泛型](/upload/InfoBanner/zyjiaocheng/674/21237cc3cee04de0ad671ca2623888e7.jpg)
JAVA中的基本类型,以及泛型的介绍、使用。
一、数据类型
数据类型:数据与操作是构成程序的两个要素,数据也是程序处理的对象。数据类型是对程序所处理的数据的抽象,数据类型决定了数据的含义、表示方式、存储格式和运算。
JAVA基本数据类型:不存在引用的概念,基本数据类型都是直接存储在内存中的内存栈上,数据本身的值就是存储在栈空间里面,因此使用时需赋具体值,且可用==判断是否相等。JAVA里面的八种基本数据类型都是这种存储模型。
JAVA八种基本数据类型:
??byte:JAVA中最小的数据类型,在内存中占8位,即1个字节。取值范围是-128 ~ 127,默认值0。
??short:短整型,在内存中占16位,即2个字节。取值范围-32768~32717,默认值0。
??int:整型,用于存储整数。在内存中占32位,即4个字节。取值范围-2147483648~2147483647,默认值0。
??long:长整型,在内存中占64位,即8个字节。取值范围-263~263-1,默认值0L。
??float:浮点型,在内存中占32位,即4个字节。用于存储带小数点的数字(与double的区别是float小数点后精度为7位),默认值为0。
??double:双精度浮点型,用于存储带有小数点的数字,在内存中占64位,即8个字节,默认值0。
??char:字符型,用于存储单个字符,占16位,即2个字节,取值范围0~65535(每个数值以ASCII码映射到字符),默认值为空。
??boolean:布尔类型,占1个字节,用于判断真或假(仅有两个值,即true、false),默认值false。
JAVA引用数据类型:变量值是指向内存空间的引用,所指向的内存中保存着变量所表示的一个值或一组值,和C语言的指针概念很相似。所以引用类型保存在栈上的是引用值,而数据真正的值则存放在引用所指向的堆内存空间。因此声明引用数据类型后,不可以直接使用,还需要实例化在堆内存中开辟内存空间。且引用数据类型使用时可以赋null,比较要用equals方法。JAVA中类、接口、数组都是引用数据类型。
JAVA四种引用类型:
??强引用(Strong Reference):JAVA中默认声明的就是强引用,只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null。
??软引用(Soft Reference):用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。因此这种特性常用于缓存技术,如网页缓存,图片缓存等。JAVA中用java.lang.ref.SoftReference类来表示软引用,只要发现强引用之后没被使用,那么在强引用对象转到软引用里面时,是会被回收的,反之会发生内存溢出。
??弱引用(WeakReference):引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。JAVA中用 java.lang.ref.WeakReference 来表示弱引用。
??虚引用(PhantomReference):是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,JAVA中用PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。
引用队列可以与软引用、弱引用以及虚引用一起配合使用,当垃圾回收器准备回收一个对象时,垃圾回收器检测到对象的可达性状态发生改变,就会把该对象对应的引用类型加入到引用队列(前提是创建该引用类型时有传入引用队列)。因此利用引用队列可以用来监听对象是否被垃圾回收器回收,同时进行额外的处理,如反向操作,数据清理,资源释放等。当某对象的引用类型出现在引用队列里,可以发现使用引用的get方法获取到对象为空,但是对象不代表已经被马上销毁,其表示对象可以被回收,但可能需要等待垃圾回收周期到来。
二、参数
1.实参和形参
实参:实际参数,在调用时传递给函数的参数,可以是常量、变量、表达式、函数等。 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。
??实参出现在主调函数中,进入被调函数后,实参变量不能使用。实参必须是已赋值才能传递给形参进行函数调用。
形参:形式参数,不是实际存在变量,所以又称虚拟变量。是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。调用函数时,实参将赋值给形参。
??形参出现在函数定义中,在整个函数体内都可以使用, 离开该函数则不能使用。所以形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。
2.参数传递
??值传递:将主调函数的实参值传递给被调函数的形参,其中形参单独分配内存,且持有和实参一样的值,所以形参改变不影响实参的值。即值传递是单向的。
??指针传递:形参和实参在内存中的地址是不同的,但是形参是指针类型且接收了实参的内存地址,那么可以通过内存地址访问和修改实参的值。
??引用传递:形参不在分配额外的内存空间,而是和实参占用一样的内存空间,此时形参相当于实参的一个别名,修改形参实际上也修改了实参。
3.其他参数(相对于Python)
??位置参数:函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。
??默认值参数:为某些参数设置默认值,这样这些参数在传递时就是可选的,默认值参数需要放置位置参数后面。
??命名参数:按照形参的名称传递参数,也称关键字参数。
??可变参数:指的是可变数量的参数。(Python中* param表多个参数收集到一个元组, * *param表多个参数收集到一个字典)
??强制命名参数:在可变参数后面添加的参数,必须在调用时强制命名。
三、泛型
泛型:即参数化类型,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(类型形参),然后在使用/调用时传入具体的类型(类型实参)。泛型的本质是为了参数化类型,即在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
1.泛型类、泛型接口、泛型方法
??泛型类:和普通类的区别就是泛型类名后有类型参数列表
??泛型接口:和泛型类一样,泛型接口在接口名后添加类型参数,接口声明类型后,接口方法就可以直接使用这个类型。实现类在实现泛型接口时需要指明具体的参数类型,不然默认类型是 Object,这就失去了泛型接口的意义。Comparator就是一个泛型接口,泛型接口定义基本的规则,然后作为引用传递给客户端,这样在运行时就能传入不同的策略实现类。
??泛型方法:指使用泛型的方法,如果它所在的类是个泛型类,那可以直接使用类声明的参数。否则需要自己在方法修饰符和返回值之间声明类型。
2.类型擦除
??在没有泛型前,要想实现一个通用的、可以处理不同类型的方法,就要使用 Object 作为属性和方法参数。而Object是所以对象的父类,当使用的时候,需要进行强制类型转换。所以容易出现类型转换异常。异常引入泛型,不仅仅消除强制类型转换,还保证了类型安全和潜在的性能收益。
??泛型和C++的模板类型,而C++ 中模板的实例化会为每一种类型都产生一套不同的代码,即所谓的代码膨胀。而JAVA虚拟机中并没有泛型类型对象,所以对象都是普通对象。主要因为泛型程序在编译的过程会执行类型检测和类型推断,然后生成普通的不带泛型的字节码被虚拟机接收并执行,整个过程就叫做类型擦除。
??类型擦除中,JAVA编译器将泛型代码中的类型完全删除、使其变成原始类型。接着JAVA编译器会在这些代码中加入类型转换,将原始类型转换成想要的类型。这些操作都是编译器后台进行,可以保证类型安全。
3.协变、逆变、不可变
??协变:如果 A 是 B 的父类,并且 A 的容器也是 B 的容器的父类,则称之为协变的。如JAVA中的数组就是协变的,Object[] objectArray=new Long[1]。
??逆变:如果 A 是 B 的父类,但是 A 的容器 是 B 的容器的子类,则称之为逆变。如List<? super Number> list = new ArrayList
4.通配符和泛型边界
??泛型中的extends:可以用来定义泛型、也可以用来实例化泛型。定义泛型时如
??泛型中的super:和extends不同,它只能和通配符一起用来实例化泛型,而不能用来定义泛型。相关的解释是说如果用super定义泛型,由于子类是不能持有父类引用的,相比于extends,后者类型擦除后可以统一转为父类对象,因此规定了上界。但是super类型擦除后只能确定的是可以转为Object,而不能强制转为其他父类,且泛型对象只持有Object类的方法,因此使用super定义泛型意义不大。而当super与通配符?一起使用来实例化泛型,如<? super E>表示泛型中的参数是不确定的,只知道是E或E的父类。
无限制通配符<?>:主要体现在要使用泛型,但是不确定或者不关心实际要操作的类型,因此用无限制通配符表示可以持有任何类型。例List<?>表示的是未知类型的列表。
??可以确定的是通配符?主要用于使用泛型类或者泛型方法,而不是用来声明泛型类、接口、方法的。通配符拿来使用定义好的泛型,其可以为传入的类型指定范围,从而进行一些特定的操作。比较容易混淆的如List、List<?>、List
上界通配符 <? extends E>:使用泛型时,表示不能放入任何类型对象,因为不能确定是哪个子类,但是可以取出E类型的对象。通常用于生产者用来取对象。另外其可以实现协变,即可以把E子类的容器赋给<? extends E>的容器。故可以读取E或E的任意子类型的容器对象。
下界通配符 <? super E>:使用泛型时,可以存放E以及E的所有子类,因为子类转父类是自动的,但是不能去取其他对象,因为不能确定到底是E的哪个父类,因此只能取出Object类型的对象。所以通常用于消费者存放对象,使得对象可以写入父类型的容器,且父类型的比较方法可以应用于子类对象。。同时利用<? super E>可以实现逆变,如把E父类的容器赋给<? super E>的容器。
内容总结
以上是互联网集市为您收集整理的JAVA泛型全部内容,希望文章能够帮你解决JAVA泛型所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。