Java基础之泛型程序设计

简介: 类型变量使用大写形式,且比较短,在Java库中,使用变量E表示集合的元素类型,K和V分别表示表的关键字与值得类型。Object 表示”任意类型”

泛型程序设计


简要介绍

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 +
                '}';
    }


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


与Java泛型转换的事实

虚拟机中没有泛型,只有普通的类和方法。

所有的类型参数都用它们的限定类型替换

桥方法被合成来保持多态

为保持类型安全性,必要时插入强制类型转换。

约束与局限性

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

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


运行时类型查询只适用于原始类型

例如:

Pair<String> stringPair=new Pair<String>();
Pair<Employee> employeePair=new Pair<Employee>();
if(stringPair.getClass()==employeePair.getClass())


其比较结果是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);
}

现考虑以下调用:

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

为了调用这个方法,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. 通配符的使用

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);
}


这种情况会编译报错

//Test 2

Pair


下面是泛型的综合应用:

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);
}


/**

*

*/

class PairAlg {

/**

* @param pair

* @return

*/

public static boolean hasNulls(Pair


相关文章
|
5月前
|
安全 Java 编译器
揭秘JAVA深渊:那些让你头大的最晦涩知识点,从泛型迷思到并发陷阱,你敢挑战吗?
【8月更文挑战第22天】Java中的难点常隐藏在其高级特性中,如泛型与类型擦除、并发编程中的内存可见性及指令重排,以及反射与动态代理等。这些特性虽强大却也晦涩,要求开发者深入理解JVM运作机制及计算机底层细节。例如,泛型在编译时检查类型以增强安全性,但在运行时因类型擦除而丢失类型信息,可能导致类型安全问题。并发编程中,内存可见性和指令重排对同步机制提出更高要求,不当处理会导致数据不一致。反射与动态代理虽提供运行时行为定制能力,但也增加了复杂度和性能开销。掌握这些知识需深厚的技术底蕴和实践经验。
106 2
|
3月前
|
Java 测试技术 开发者
💡Java 零基础:彻底掌握 for 循环,打造高效程序设计
【10月更文挑战第15天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
132 63
|
3月前
|
Java API
[Java]泛型
本文详细介绍了Java泛型的相关概念和使用方法,包括类型判断、继承泛型类或实现泛型接口、泛型通配符、泛型方法、泛型上下边界、静态方法中使用泛型等内容。作者通过多个示例和测试代码,深入浅出地解释了泛型的原理和应用场景,帮助读者更好地理解和掌握Java泛型的使用技巧。文章还探讨了一些常见的疑惑和误区,如泛型擦除和基本数据类型数组的使用限制。最后,作者强调了泛型在实际开发中的重要性和应用价值。
66 0
[Java]泛型
|
3月前
|
存储 安全 Java
🌱Java零基础 - 泛型详解
【10月更文挑战第7天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
23 1
|
4月前
|
Java 编译器 容器
Java——包装类和泛型
包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。
49 9
Java——包装类和泛型
|
3月前
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
33 5
|
3月前
|
存储 Java 编译器
Java集合定义其泛型
Java集合定义其泛型
22 1
|
3月前
|
存储 Java 编译器
【用Java学习数据结构系列】初识泛型
【用Java学习数据结构系列】初识泛型
26 2
|
4月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
|
4月前
|
存储 安全 搜索推荐
Java中的泛型
【9月更文挑战第15天】在 Java 中,泛型是一种编译时类型检查机制,通过使用类型参数提升代码的安全性和重用性。其主要作用包括类型安全,避免运行时类型转换错误,以及代码重用,允许编写通用逻辑。泛型通过尖括号 `&lt;&gt;` 定义类型参数,并支持上界和下界限定,以及无界和有界通配符。使用泛型需注意类型擦除、无法创建泛型数组及基本数据类型的限制。泛型显著提高了代码的安全性和灵活性。