Java基础:泛型

泛型简介

泛型规范在 JDK 1.5 版本中被添加,使用泛型机制编写的代码比起随意使用 Object 变量然后再进行强制类型转换的代码具有更高的安全性和可读性,同时也更为简洁。

泛型的好处

  • 泛型将将运行时期的问题ClassCastException转到了编译时期。
  • 避免了强制转换的麻烦。
  • 泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

什么时候使用泛型

当操作的引用数据类型不确定的时候,就使用泛型,将要操作的引用数据类型传入即可。其实<>就是一个用于接收具体引用数据类型的参数范围。

泛型演示

泛型在 ArrayListIterator 中的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.ArrayList;
import java.util.Iterator;
public class GenrticDemo {
public static void main(String[] args){
//明确传入的具体引用数据类型
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("haha");
arrayList.add("xixi");
arrayList.add("hello");

////明确传入的具体引用数据类型
Iterator<String> it = arrayList.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
}
}

自定义泛型

泛型类

1
2
3
4
5
6
7
8
9
10
public class Utils<T> {

public void print (T t) {
System.out.println(t);
}

public void show (T t) {
System.out.println(t);
}
}

如此即可定义一个泛型类,这样 Utils 的所有方法就可以操作创建 Utils 类时指定的数据类型了。

泛型方法

1
2
3
4
5
6
7
8
9
10
11
public class Utils {

public<T> void print (T t) {
System.out.println(t);
}

public<T> void show (T t) {
System.out.println(t);
}

}

泛型类有一个弊端,就是当该类中有不同的方法,来接收不同的参数时,就不行了,因为它之接收创建类时指定的数据类型

所以就有了泛型方法,这样方法 print 与 show 方法就可以分别接收不同类型的数据类型了,而不必受类的泛型的限制

泛型类与泛型方法混合使用

1
2
3
4
5
6
7
8
9
10
public class Utils<T> {

public void print (T t) {
System.out.println(t);
}

public<E> void show (E e) {
System.out.println(e);
}
}

这样就是混合使用了, print 会使用类的泛型 T ,而 show 方法则会使用自身的泛型 E,两者互不冲突。

泛型静态方法

1
2
3
4
5
6
7
8
9
10
public class Utils<T> {

public void print (T t) {
System.out.println(t);
}

public static<E> void show (E e) {
System.out.println(e);
}
}

由于静态的特性,所以静态方法不可以访问类上定义的泛型,如果静态方法操作的数据类型不确定,那么就将泛型定义上方法上。

泛型接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface Inter<T> {
void show(T t);
}

class InterImpl implements Inter<String> {
public void show (String str) {
System.out.println(str);
}
}

public class GenericDemo {
public static void main(String[] args) {
InterImpl inter = new InterImpl();
inter.show("haha");
}
}

当接口的实现类也不确定要使用的数据类型时,也可以让接口用泛型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface Inter<T> {
void show(T t);
}

class InterImpl<T> implements Inter<T> {
public void show (T t) {
System.out.println(t);
}
}

public class GenericDemo {
public static void main(String[] args) {
InterImpl<String> inter = new InterImpl<String>();
inter.show("haha");

InterImpl<Integer> inter2 = new InterImpl<Integer>();
inter2.show(5);
}
}

泛型限定

占位符

1
2
3
4
5
6
7
public static void printColl(ArrayList<?> al) {
Iterator<?> it = al.iterator();

while (it.hashNext()) {
Systen.out.println(it.next());
}
}

上方代码展示了一个占位符的应用场景,占位符有一个缺陷就是无法操作这个元素,例如使用 时还可以 T t = it.next() ,而使用了占位符 ? 的话就不能 ? t = it.next()

上下限

1
2
3
4
5
6
7
public static void printColl(ArrayList<? extends Person> al) {
Iterator<?> it = al.iterator();

while (it.hashNext()) {
Systen.out.println(it.next());
}
}

这是一个上限的例子,表示 只能接收 Person 与 Person 的子类

下限则是指其父类,格式是:<? super Person>

坚持原创技术分享,您的支持将鼓励我继续创作!