Java—泛型

泛型

介绍

一种未知的数据类型,不知道用什么数据类型的时候,可用泛型
泛型也可以看作是一个变量,用来接收数据类型
    E e: Element 元素
    T t: Type 类型
当创建集合对象的时候,就会确定泛型的数据类型

不使用泛型

好处:
		默认类型是Object类,能够存储任意类型的数据
坏处:
		不安全,引发异常
ArrayList list = new ArrayList();
list.add("aaa");
list.add(111);
Iterator it = list.iterator();
while (it.hasNext()){
	Object next = it.next();
	System.out.println(next);
	// 引发异常,不能把Integer类型转为String类型
	String s=(String) next;
	System.out.println(s.length());

使用泛型

好处:
		避免类型转换的麻烦,存储什么类型,取出的就是什么类型
		把运行期异常,提升到了编译期
坏处:
		泛型是什么类型,只能存储什么类型的数据

泛型的类

定义:

格式:
修饰符 class 类名<泛型>{
	// 成员变量
	private 泛型 成员变量名;
    // 构造方法
    public 泛型 get...(){
    		return ...;
    }

	public void set... (泛型 ...){
			this... = ...;
	}
}
public class GenericClass<E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}

测试:

public static void main(String[] args) {
        // 不写泛型默认是Object
        GenericClass gc = new GenericClass();
        gc.setName("只能是字符串");
        Object name = gc.getName();

        // 使用泛型
        GenericClass<Integer> gc2 = new GenericClass<>();
        gc2.setName(123);
        Integer name1 = gc2.getName();
        System.out.println(name1);

        GenericClass<String> gc3 = new GenericClass<>();
        gc3.setName("da");
        String name2 = gc3.getName();
        System.out.println(name2);
    }

泛型的接口

定义:

格式:
    修饰符 interface 接口名 <I/*泛型,可使用任意字母*/> {
    		抽象方法…(I i);
    }
public interface GenericInterface<I> {
    public abstract void method(I i);
}

实现一

定义接口的实现类,实现接口,指定接口的泛型

public class GenericInterfaceImpl1 implements GenericInterface<String> {

    @Override
    public void method(String s) {
        System.out.println(s);
    }
}

实现二

接口是用什么泛型,实现类就是用什么泛型。

public class GenericInterfaceImpl2<I> implements GenericInterface<I>{

    @Override
    public void method(I i) {
        System.out.println(i);
    }
}

测试:

public static void main(String[] args) {
        GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
        gi1.method("字符串");

        GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
        gi2.method(123);

        GenericInterfaceImpl2<String> gi3 = new GenericInterfaceImpl2<>();
        gi3.method("avc");


    }

泛型的方法

定义含有泛型的方法: 定义在方法的修饰符和返回值类型之间

格式:
    修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
    }
public class GenericMethod {
    // 定义一个含有泛型的方法
    public <M> void method01(M m){
        System.out.println(m);
    }

    // 定义一个含有泛型的静态方法
    public static <S> void method02(S s){
        System.out.println(s);
    }
}

测试:

public static void main(String[] args) {
        GenericMethod gm = new GenericMethod();
        gm.method01("aaa");
        gm.method01(01);
        gm.method01(true);

        GenericMethod.method02("daa");
        GenericMethod.method02(11);
    }

通配符

泛型通配符:
	不知道是用什么类型来接受的时候,此时可以使用?,?表示未知通配符。
    此时只能接受数据,不能向该集合中存储数据
使用方法:
    不能创建对象使用
    只能作为方法的参数使用

例子:
定义一个方法,能够遍历所有类型的ArrayList集合这时候我们不知道ArrayList集合使用什么数据类型,可以使用泛型通配符?接受数据类型

public static void main(String[] args) {
        ArrayList<Integer> list01  = new ArrayList<>();
        list01.add(1);
        list01.add(2);

        ArrayList<String > list02 = new ArrayList<>();
        list02.add("a");
        list02.add("ab");

        printArray(list01);
        printArray(list02);
        // ArrayList<?> list02 = new ArrayList<>();
    }

public static void printArray(ArrayList<?> list){
        // 使用迭代器便利
        Iterator<?> it = list.iterator();
        while (it.hasNext()){
            Object o = it.next();
            System.out.println(o);
        }
    }

上下限定

泛型的上限限定: ? extends E    代表使用的泛型只能是E类型的子类/本身
泛型的下限限定: ? super E      代表使用的泛型只能是E类型的父类/本身

例子:

 public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        Collection<Number> list3 = new ArrayList<>();
        Collection<Object> list4 = new ArrayList<>();

        getElement1(list1);
//        getElement1(list2); // 报错
        getElement1(list3);
//        getElement1(list4); // 报错

//        getElement2(list1); // 报错
//        getElement2(list2); // 报错
        getElement2(list3);
        getElement2(list4);

    }
    // 子类或者本身也就是Integer和Number
    public static void getElement1(Collection<? extends Number> coll) {}
    // 父类或者本身也就是Object和Number
    public static void getElement2(Collection<? super Number> coll) {}
类与类之间的关系:
        Integer extends Number extends Object
        String extends Object
        
getElement1 参数列表使用的是 ?extends Number,需要遵循泛型的上先限定,
Number的子类有Integer,因此使用的泛型只能是其子类Integer和本身Number,
故list2,list4报错

getElement1 参数列表使用的是 ?super Number,需要遵循泛型的下线限定,
Number的父类有Object,因此使用的泛型只能是其父类Object和本身Number,
故list1,list2报错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rich_Z_b_f

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值