扒一拔:Java 中的泛型(一)

@

1 泛型

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

1.1 为什么需要泛型

泛型是JDK1.5才出来的, 在泛型没出来之前, 我们可以看看集合框架中的类都是怎么样的。

以下为JDK1.4.2的 HashMap

可以看到, 在该版本中, 参数和返回值(引用类型)的都是 Object 对象。 而在 Java 中, 所有的类都是 Object 子类, 实用时, 可能需要进行强制类型转换。 这种转换在编译阶段并不会提示有什么错误, 因此, 在使用时, 难免会出错。

而有了泛型之后, HashMap的中使用泛型来进行类型的检查

Java 8 HashMap

通过泛型, 我们可以传入相同的参数又能返回相同的参数, 由编译器为我们来进行这些检查。

这样可以减少很多无关代码的书写。

因此, 泛型可以使得类型参数化, 泛型有如下的好处

类型参数化, 实现代码的复用

强制类型检查, 保证了类型安全,可以在编译时就发现代码问题, 而不是到在运行时才发现错误

不需要进行强制转换。

1.2 类型参数命名规约

按照惯例,类型参数名称是单个大写字母。 通过规约, 我们可以容易区分出类型变量和普通类、接口。

E - 元素

T - 类型

N - 数字

K - 键

V - 值

S,U,V - 第2种类型, 第3种类型, 第4种类型

2 泛型的简单实用 2.1 最基本最常用

最早接触的泛型, 应该就是集合框架中的泛型了。

List<Integer> list = new ArrayList<Integer>(); list.add(100086); //OK list.add("Number"); //编译错误

在以上的例子中, 将 String 加入时, 会提示错误。 编译器不会编译通过, 从而保证了类型安全。

2.2 简单泛型类 2.2.1 非泛型类

先来定义一个简单的类

public class SimpleClass { private Object obj; public Object getObj() { return obj; } public void setObj(Object obj) { this.obj = obj; } }

这么写是没问题的。 但是在使用上可能出现如下的错误:

public static void main(String[] args) { SimpleClass simpleClass = new SimpleClass(); simpleClass.setObj("ABC");// 传入 String 类型 Integer a = (Integer) simpleClass.getObj(); // Integer 类型接受 }

以上写是不会报错的, 但是在运行时会出现报错

java.lang.ClassCastException

如果是一个人使用, 那确实有可能会避免类似的情况。 但是, 如果是多人使用, 则你不能保证别人的用法是对的。 其存在着隐患。

2.2.2 泛型类的定义

我们可以使用泛型来强制类型限定

public class GenericClass<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } } 2.2.3 泛型类的使用

在使用时, 在类的后面, 使用尖括号指明参数的类型就可以

@Test public void testGenericClass(){ GenericClass<String> genericClass = new GenericClass<>(); genericClass.setObj("AACC"); /* Integer str = genericClass.getObj();//*/ }

如果类型不符, 则编译器会帮我们发现错误, 导致编译不通过。

检查

2.3 简单泛型接口 2.3.1 定义

与类相似, 以 JDK 中的 Comparable 接口为例

package java.lang; import java.util.*; public interface Comparable<T> { public int compareTo(T o); } 2.3.2 实现

在实现时, 指定具体的参数类型即可。

public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... public int compareTo(String anotherString) { byte v1[] = value; byte v2[] = anotherString.value; if (coder() == anotherString.coder()) { return isLatin1() ? StringLatin1.compareTo(v1, v2) : StringUTF16.compareTo(v1, v2); } return isLatin1() ? StringLatin1.compareToUTF16(v1, v2) : StringUTF16.compareToLatin1(v1, v2); } ... } 2.4 简单泛型方法

泛型方法可以引入自己的参数类型, 如同声明泛型类一样, 但是其类型参数我的范围只是在声明的方法本身。 静态方法和非静态方法, 以及构造函数都可以使用泛型。

2.4.1 泛型方法声明

泛型方法的声明, 类型变量放在修饰符之后, 在返回值之前

public class EqualMethodClass { public static <T> boolean equals(T t1, T t2){ return t1.equals(t2); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxxdj.html