博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java基础知识之泛型全接触
阅读量:6206 次
发布时间:2019-06-21

本文共 5148 字,大约阅读时间需要 17 分钟。

当我们在定义类,接口和方法时,可以接收一个类型作为参数,这就叫做泛型

函数可以传入普通的参数,也可以传入一个类型参数。不同之处是普通的参数就是值而已,但是类型参数却是个类型。

使用泛型的好处:

  • 强类型检查。在编译时就可以得到类型错误信息。
  • 避免显式强制转换。
  • 方便实现通用算法。

对类使用泛型

我们可以创建一个简单的Class Box。它提供存取一个类型为Object的对象。

12345678910
public class Box {
public Object getObject() {
return object; } public void setObject(Object object) {
this.object = object; } private Object object;

你可以传给它任何你想要的对象,比如对象String,Integer等,也可以传入自定义的一些对象。但是调用getObject方法返回的对象需要显式的强转为传入的类型,才能使用原来类型的一些方法。

我们可以使用泛型来构造这个对象。

1234567891011
public class Box
{
public T getObject() {
return object; } private T object; public void setObject(T object) {
this.object = object; }}

我们可以看到,所有的Object被替换成了T。T代表了某种类型,你在实例化Box对象时,必须要给其指定一种类型,String,Integer或者自定义的类,并且调用getObject方法并不需要进行强转就可以使用该类型的方法。

一般来说,类型参数名称越简单越好,并且需要是大写的。为了方便,我们约定了一些命名使用。

  • E Element
  • K key
  • N Number
  • T type
  • V value
  • S,U,V 第2,3,4个类型

我们可以这样实例化一个Box类。

1
Box
integerBox = new Box
();

同样,我们也支持在一个类中传入多个类型参数。例如下面的Pair对象

12345678910111213141516
public class Pair
{
private T key; private V value; public Pair(T key, V value) {
this.key = key; this.value = value; } public T getKey() {
return key; } public V getValue() {
return value; }

使用方法如下。

123
Pair
one = new Pair
(1, "one");Pair
hello = new Pair
("hello", "world");

对方法使用泛型

泛型可以作用与方法上,此时泛型参数只能在方法体中使用。而泛型作用于类时,则在整个类中可以使用。

在静态方法、非静态方法及构造函数都可以使用泛型。

1234567
public class Util {
public static
boolean compare(Pair
pair1, Pair
pair2) {
return pair1.getKey().equals(pair2.getKey()) && pair1.getValue().equals(pair2.getValue()); }}

下面是对该静态方法的使用。

12345
Pair one = new Pair("one", 1);        Pair two = new Pair("two", 2);        assertThat(Util.compare(one, two), is(false));// pass

对泛型进行限定

默认情况下如果直接使用的话,我们可以给其传任何值。有时候我们想值允许传入某个类及它的子类。这时候在声明泛型时可以使用extends关键字。

1234567891011
public class Box
{
public T getObject() {
return object; } private T object; public void setObject(T object) {
this.object = object; }}
123
Box box = new Box();        box.setObject(10);    //ok        box.setObject("hello");  //compile-time error

我们也可以给类型参数加多个限定。

1

加上限定类或接口以后,我们可以使用泛型参数变量调用该类或接口的方法。

通配符的使用

Java中的List就是一个实现了泛型的类,假如我们写了一个方法,获取List中元素的个数。只不过这个方法限定T类型为Number。

123456789
public static int getCount(List
list) {
int i = 0; for(Number n : list) {
i++; } return i; }

然后我们这样试图调用它。

123456789
List
list = new ArrayList
(){
{
add(1); add(2); add(3); } }; Util.getCount(list); //compile-time error

为什么会产生错误那?因为我们要求方法的参数是List,而我们实际传入的是List。虽然Integer是Number的子类,但是List却不是List的子类,他们其实是平等的关系。这点一定要注意。我们在方法定义时已经明确表示T的类型是Number了,所以只能接收List,而不能接收其它类型的参数。 这时候?通配符就起作用了。我们可以使用通配符重新定义这个方法。

12345678910111213
public class Util {
public static int getCount(List
list) {
int i = 0; for(Number n : list) {
i++; } return i; }}
123456789
List
list = new ArrayList
(){
{
add(1); add(2); add(3); } }; assertThat(Util.getCount(list), is(3)); // pass

既然能限定到一个类及其子类上,当然也能限定到一个类及其父类上。语法如下:

1

对泛型使用的总结

  • 类型参数不能是原始类型(int, char,double),只能传入这些类型的封转类(Integer,Char,Double)。

  • 不能直接创建类型参数的实例。

12
public static 
void append(List
list) {
E elem = new E(); // compile-time error list.add(elem); }

但有通过反射可以实现。

1
public static 
void append(List
list, Class
cls) throws Exception {
E elem = cls.newInstance(); // OK list.add(elem);}

你可以这样调用它:

12
List
ls = new ArrayList<>();append(ls, String.class);
  • 静态字段的类型不能为类型参数。
123
public class Box
{
private static T object; // compile-time error}
  • 不能创建类型参数变量的数组。
1
List
[] arrayOfLists = new List
[2]; // compile-time error
  • 不能重载一个方法,该方法的形参都来自于同一个类型参数对象。
123456
public class Example {
public void print(List
integers) {} public void print(List
doubles) {}}

参考文档:

转载地址:http://zvwja.baihongyu.com/

你可能感兴趣的文章
【eclipse转idea的第一天】配置idea
查看>>
error: Refusing toundefine while domain managed save image exists
查看>>
wordpress在新窗口打开留言者链接
查看>>
java开发过程中的命名规范
查看>>
mysql索引随记
查看>>
关于Pac-Man,你所要了解的 一切
查看>>
分布式配置管理平台Disconf
查看>>
pdf 字体和图片抽取
查看>>
Cisco Nexus 1000V
查看>>
我的友情链接
查看>>
[iOS Animation]-CALayer 性能优化实例
查看>>
CentOS多网卡重命名配置
查看>>
变态青蛙跳
查看>>
Git常用命令总结
查看>>
定时任务
查看>>
MyBatis之输入与输出(resultType、resultMap)映射
查看>>
剥开比原看代码09:通过dashboard创建密钥时,前端的数据是如何传到后端的?
查看>>
51、YUM安装配置LAMP、phpMyAdmin实战
查看>>
Yeslab现任明教教主ISE课程前七部分免费发布
查看>>
linux下恢复误删文件
查看>>