Java基础之泛型程序设计

举报
码农飞哥 发表于 2021/05/29 12:44:01 2021/05/29
【摘要】 泛型程序设计 简要介绍 类型变量使用大写形式,且比较短,在Java库中,使用变量E表示集合的元素类型,K和V分别表示表的关键字与值得类型。Object 表示”任意类型”程序清单使用了Pair类,静态的minmax方法遍历了数组并同时计算出最大值和最小值。它用一个Pair对象返回了两个结果。compareTo 方法只有 Comparable 接口有该方法,所以我们要将...

泛型程序设计

简要介绍

  1. 类型变量使用大写形式,且比较短,在Java库中,使用变量E表示集合的元素类型,K和V分别表示表的关键字与值得类型。Object 表示”任意类型”
  2. 程序清单使用了Pair类,静态的minmax方法遍历了数组并同时计算出最大值和最小值。它用一个Pair对象返回了两个结果。
  3. compareTo 方法只有 Comparable 接口有该方法,所以我们要将T限制为实现了Comparable接口的
    的类

类型擦除

无论何时定义一个泛型类型,都自动提供了一个相应的原始类型,原始类型的名字就是删去参数后的泛型类型名,擦除类型变量,并替换为限定类型(无限定的变量用Object)
例如:Pair 的原始类型如下所示:

public class Pair <Object>{ private Object name; private Object bonus; public Object getFirst() { return name; } public void setFirst(Object name) { this.name = name; } public Object getSecond() { return bonus; } public void setSecond(Object bonus) { this.bonus = bonus; } public Pair(){} public Pair(Object name, Object bonus) { this.name = name; this.bonus = bonus; } @Override public String toString() { return "Pair{" + "name=" + name + ", bonus=" + bonus + '}'; }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

类型擦除带来的方法参数不统一,编译器通过桥方法来处理。

与Java泛型转换的事实

  • 虚拟机中没有泛型,只有普通的类和方法。
  • 所有的类型参数都用它们的限定类型替换
  • 桥方法被合成来保持多态
  • 为保持类型安全性,必要时插入强制类型转换。

约束与局限性

  1. 不能用基本类型实例化类型参数

例如没有 Pair<double>,只有 Pair<Double>

  1. 运行时类型查询只适用于原始类型
    例如:
Pair<String> stringPair=new Pair<String>();
Pair<Employee> employeePair=new Pair<Employee>();
if(stringPair.getClass()==employeePair.getClass())

  
 
  • 1
  • 2
  • 3
  • 4

其比较结果是true,这是因为两次调用getClass都将返回 Pair.class

  1. 不能创建参数化类型的数组
    例如:
    Pair<String>[] table=new Pair<String>[10] //error

  2. Varargs 警告

public static <T> void addAll(Collection<T> coll,T ... ts){ for(t: ts) coll.add(t);
}

  
 
  • 1
  • 2
  • 3
  • 4

现考虑以下调用:


Collection<Pair<String>> table=...;
Pair<String> pair1=...;
Pair<String> pair2=...;
Pair<String> pair3=...;
addAll(table,pair1,pair2);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

为了调用这个方法,Java虚拟机必须建立一个Pair 数组。这就违反了前面的规则。
不过,对于这种情况,规则有所放松,你只会得到一个警告,而不是错误。

可以采取两种方法来抑制这个警告。一种方法是为包含addAll调用的方法增加注解@SuppressWarnings(“unchecked”)。或者在Java SE 7中,还
可以用@SafeVarargs直接标注addAll方法。

5 不能实例化类型变量
不能使用像new T(…),new T[…] 或T.class 这样的表达式中的类型变量,例如下面
Pair 构造器就是非法的:
public Pair(){name=new T();bonus=new T();}
类型擦除将T改变成了Object,而且,其本意肯定不希望调用new Object()。在Java SE 8之后,最好的解决办法是让调用者
提供一个构造器表达式。例如:
Pair<String> p=Pair.makePair(String::new)
6. 不能构造泛型数组
例如:
public static <T extends Comparable> T[] minmax(T[] a){T[] mm=new T[2];} //error
7. 泛型类的静态上下文中类型变量无效
不能再静态域或方法中引用类型变量。例如:
“`
public class Signleton {
private static T signleStance; //Error
public static T getSignleStance(){ //True
if(signleStance==null){
return signleStance;
}
}
}

8. 不能抛出或者捕获泛型类的实例

既不能抛出也不能捕获泛型类对象。实际上,甚至泛型类扩展Throwable都是不合法的。
例如:以下定义就不能正常编译:
`public class Problem<T> extends Exception{}`

9. 可以通过 `@SuppressWarnings('unchecked')` 来消除对受查异常的检查。
### 泛型类型的继承规则
1. 通配符的使用
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

public static void main(String[] args) {
Pair managerPair = new Pair<>();
printBuddies(managerPair);

}

public static void printBuddies(Pair<? extends  Employee> employeePair) { Employee name = employeePair.getFirst(); Employee bonus = employeePair.getSecond(); System.out.println("name:"+name+"bonus:"+bonus);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
这种情况会编译报错
  
 
  • 1

//Test 2
Pair

下面是泛型的综合应用:
  
 
  • 1

package com.jay.generic;

import com.jay.generic.employee.Employee;
import com.jay.generic.employee.Manager;

/**
* 泛型综合总结应用
* Created by xiang.wei on 2018/1/21
*
* @author xiang.wei
*/
public class PairTest3 {
public static void main(String[] args) {
Manager ceo = new Manager(“xiang”, 10000);
Manager cfo = new Manager(“li”, 8000);
Pair managerPair = new Pair<>(ceo, cfo);
printBuddies(managerPair);

 ceo.setBonus(2000); cfo.setBonus(1000); Manager[] managers = {ceo, cfo}; minmaxBonus(managers, managerPair); System.out.println("first:"+managerPair.getFirst().getName()+",second:"+managerPair.getSecond().getName()); maxminBonux(managers,managerPair); System.out.println("first:"+managerPair.getFirst().getName()+",second:"+managerPair.getSecond().getName());

}


public static void printBuddies(Pair<? extends Employee> pair) { Employee first = pair.getFirst(); Employee second = pair.getSecond(); System.out.println("first="+first.getName()+"------second="+second.getName());
}

public static void minmaxBonus(Manager[] managers, Pair<? super Manager> result) { if (managers.length == 0) { return; } Manager min = managers[0]; Manager max = managers[0]; for (int i = 0; i < managers.length; i++) { if (min.getBonus() > managers[i].getBonus()) { min = managers[i]; } if (max.getBonus() < managers[i].getBonus()) { max = managers[i]; } } result.setFirst(min); result.setSecond(max);
}

public static void maxminBonux(Manager[] managers, Pair<? super Manager> result) { if (managers.length == 0) { return; } minmaxBonus(managers, result); PairAlg.swapHelper(result);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

}

/**
*
*/
class PairAlg {
/**
* @param pair
* @return
*/
public static boolean hasNulls(Pair

文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。

原文链接:feige.blog.csdn.net/article/details/79130036

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。