泛型
概念
泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型,也可以看作是一个变量,用来接收数据类型。(E e:Element元素,T t:Type类型)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V4O5ml7k-1620467634842)(E:\学习文档\JavaWeb\img\泛型\1619248400769.png)]
使用泛型的利与弊
好处:
- 避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
- 把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)
弊端:
泛型是什么类型,只能存储什么类型的数据
泛型的使用
在类中使用
package com.fanxing;
public class GenericClass <E>{
private E name;
public E getName(){
return this.name;
}
public void setName(E name) {
this.name = name;
}
}
package com.fanxing;
public class GenericClassTest {
public static void main(String[] args) {
GenericClass<Boolean> genericClass = new GenericClass();
genericClass.setName("aaa");//这里就是把运行期的错误放在编译期的完美体现,只能是Boolean类型
System.out.println(genericClass.getName());
}
}
//如果不写类型的时候,就是Object
在方法中使用
定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间
格式:修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
方法体
}
含有泛型的方法,在调用方法的时候确定泛型的数据类型。传递什么类型的参数,泛型就是什么类型。
package com.fanxing;
public class GenericClass {
public <E> E method(E type){
return type;
}
}
package com.fanxing;
public class GenericClassTest {
public static void main(String[] args) {
GenericClass genericClass = new GenericClass();
String str = genericClass.method("aaa");
System.out.println(str);
}
}
//在这里传入的是什么值,返回的就是什么值
含有泛型的接口
方式一:
含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型,
public interface Iterator<E>{}
Scanner类实现了Iterator接口,并指定接口的泛型为String,所有重写的next方法泛型默认就是String
public final class Scanner implements Iterator<String>{
@Override
public void method(String s){
System.out.println(s);
}
}
例:
package com.fanxing;
public interface GenericInterface<T> {
boolean add(T t);
T get(T type);
}
package com.fanxing;
public class GenericInterfaceImpl implements GenericInterface<String>{
@Override
public boolean add(String s) {
return false;
}
@Override
public String get(String type) {
return null;
}
}
方式二:
含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的方法
package com.fanxing;
public interface GenericInterface<T> {
boolean add(T t);
T get(T type);
}
package com.fanxing;
public class GenericInterfaceImpl<I> implements GenericInterface<I>{
@Override
public boolean add(I i) {
return false;
}
@Override
public I get(I type) {
return null;
}
}
泛型通配符
当使用泛型类型或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示,但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身的方法无法使用。
通配符基本使用
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符此时只能接受数据,不能往该集合中存储数据。
package com.fanxing;
import java.util.ArrayList;
public class GenericLable {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add("name"+i);
}
ArrayList<Integer> list1 = new ArrayList<>();
getElement(list);
}
public static void getElement(ArrayList<?> aryList){
for (String o : aryList) {//这里会报错因为如果使用了通配符,就只能使用Object类型,不能再使用其他类型了
System.out.println(o);
}
}
}
通配符的高级使用------受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。
泛型的上限
- 格式:类型名称<? extends 类>对象名称
- 意义:只能接收该类型及其子类
泛型的下限
- 格式:类型名称<? super 类> 对象名称
- 意义:只能接收该类型及其父类型
比如:现已知Object类,String类,Number类,Integer类,其中Number是Integer的父类
package com.fanxing;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
public class GenericLable{
public static void main(String[] args) {
ArrayList<Number> list1 = new ArrayList<>();
ArrayList<Object> list2 = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list1.add(i);
list2.add("i"+i);
}
getElement1(list1);
getElement2(list2);
}
public static void getElement1(Collection<? extends Number> coll){
//extends只能写Number类型或者Number类型的子类型
for (int i = 0; i < coll.size(); i++) {
System.out.println(coll);
}
}
public static void getElement2(Collection<? super Number> coll){
//super只能写Number类型或者Number类型的父类型
for (int i = 0; i < 10; i++) {
System.out.println(coll);
}
}
}
}
}
public static void getElement2(Collection<? super Number> coll){
//super只能写Number类型或者Number类型的父类型
for (int i = 0; i < 10; i++) {
System.out.println(coll);
}
}
}