泛型的使用

链接: 原文链接

一.泛型的定义

泛型,即“参数化类型”。就是将类型由原来的具体类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(类型形参),然后再使用/调用时传入具体的类型

常用的泛型变量
Element(E):元素,多用于java框架集合

Key(K) :关键字

Number(N) : 数字

Type(T) : 类型

Value(V) : 值

如果没有泛型会怎么样?

如果要实现不同类型的加法,每种类型都需要重载一个add方法

package com.company;

public class GenericityTest {

    public static int add(int a ,int b){
        return a+b;
    }

    public  static  float add(float a,float b){
        return a+b;
    }
    
	 public static void main(String[] args) {
        GenericityTest.add(1, 2);
        GenericityTest.add(1f, 2f);
	
	 }
}

如果我们利用泛型,只需要定义一个方法

package com.company;

public class GenericityTest {

    public static <T extends Number> int add(T a, T b) {
        System.out.println(a + "+" + b + "=" + (a.intValue() + b.intValue()));
        return a.intValue() + b.intValue();
    }

    public static void main(String[] args) {
        GenericityTest.add(1, 2);
        GenericityTest.add(1f, 2f);
    }
}

所以泛型的意义在于
1.适用于多种数据类型执行相同的代码
2.泛型中的类型在使用时指定,不需要强制转换类型(类型安全,编译器会检查类型)

二.泛型的使用

1.泛型类的使用

package com.company;

public class GenericityTest<T> {

    public T data;

    public void setData(T data){
        this.data=data;
    }

    public T getData(){
        return data;
    }

    public static void main(String[] args) {

        GenericityTest genericityTest=new GenericityTest();
        genericityTest.setData(1245.1323f);
        System.out.println(genericityTest.getData());

    }
}

2.泛型接口的使用

package com.company;

public interface GenericityInter <T>{
    public T getData();
}

3.泛型方法的使用

如果没有使用泛型类,定义泛型方法时,需要加<T>定义该方法所拥有的泛型标识符

package com.company;

public class GenericityTest{

    public  <T> T setData(T data){

        return data;
    }

    public static void main(String[] args) {

        GenericityTest genericityTest=new GenericityTest();
        System.out.println(genericityTest.setData("abc"));

    }
}

4.限定泛型类型变量

对方法的限定: public T setData(T data){}

package com.company;

public class GenericityTest{

    public  <T extends Number> T setData(T data){

        return data;
    }

    public static void main(String[] args) {

        GenericityTest genericityTest=new GenericityTest();
        System.out.println(genericityTest.setData("abc"));//如果传入String类型,则报错
        System.out.println(genericityTest.setData(123));

    }
}

对类的限定:public class GenericityTest{}

package com.company;

public class GenericityTest<T extends Number>{

    public T name;


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

    public T getName(){
        return name;
    }

    public static void main(String[] args) {

        GenericityTest genericityTest=new GenericityTest();
        genericityTest.setName(1212);
        genericityTest.setName("abc");//如果传入字符串则报错
        System.out.println(genericityTest.getName());

    }
}

5.通配符类型

? - 表示不确定的java类型

1.<? extends Parent> 指定了泛型类型的上届
2.<? super Child> 指定了泛型类型的下届
3. <?> 指定了没有限制的泛型类型

/**
 * Author:Jay On 2019/5/10 19:51
 * <p>
 * Description: 泛型通配符测试类
 */
public class GenericByWildcard {
    private static void print(GenericClass<Fruit> fruitGenericClass) {
        System.out.println(fruitGenericClass.getData().getColor());
    }

    private static void use() {
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        print(fruitGenericClass);
        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        //类型不匹配,可以使用<? extends Parent> 来解决
//        print(orangeGenericClass);
    }

    /**
     * <? extends Parent> 指定了泛型类型的上届
     */
    private static void printExtends(GenericClass<? extends Fruit> genericClass) {
        System.out.println(genericClass.getData().getColor());
    }

    public static void useExtend() {
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printExtends(fruitGenericClass);
        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        printExtends(orangeGenericClass);

        GenericClass<Food> foodGenericClass = new GenericClass<>();
        //Food是Fruit的父类,超过了泛型上届范围,类型不匹配
//        printExtends(foodGenericClass);

        //表示GenericClass的类型参数的上届是Fruit
        GenericClass<? extends Fruit> extendFruitGenericClass = new GenericClass<>();
        Apple apple = new Apple();
        Fruit fruit = new Fruit();
        /*
         * 道理很简单,? extends X  表示类型的上界,类型参数是X的子类,那么可以肯定的说,
         * get方法返回的一定是个X(不管是X或者X的子类)编译器是可以确定知道的。
         * 但是set方法只知道传入的是个X,至于具体是X的那个子类,不知道。
         * 总结:主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。
         */
//        extendFruitGenericClass.setData(apple);
//        extendFruitGenericClass.setData(fruit);

        fruit = extendFruitGenericClass.getData();

    }

    /**
     * <? super Child> 指定了泛型类型的下届
     */
    public static void printSuper(GenericClass<? super Apple> genericClass) {
        System.out.println(genericClass.getData());
    }

    public static void useSuper() {
        GenericClass<Food> foodGenericClass = new GenericClass<>();
        printSuper(foodGenericClass);

        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printSuper(fruitGenericClass);

        GenericClass<Apple> appleGenericClass = new GenericClass<>();
        printSuper(appleGenericClass);

        GenericClass<HongFuShiApple> hongFuShiAppleGenericClass = new GenericClass<>();
        // HongFuShiApple 是Apple的子类,达不到泛型下届,类型不匹配
//        printSuper(hongFuShiAppleGenericClass);

        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        // Orange和Apple是兄弟关系,没有继承关系,类型不匹配
//        printSuper(orangeGenericClass);

        //表示GenericClass的类型参数的下界是Apple
        GenericClass<? super Apple> supperAppleGenericClass = new GenericClass<>();
        supperAppleGenericClass.setData(new Apple());
        supperAppleGenericClass.setData(new HongFuShiApple());
        /*
         * ? super  X  表示类型的下界,类型参数是X的超类(包括X本身),
         * 那么可以肯定的说,get方法返回的一定是个X的超类,那么到底是哪个超类?不知道,
         * 但是可以肯定的说,Object一定是它的超类,所以get方法返回Object。
         * 编译器是可以确定知道的。对于set方法来说,编译器不知道它需要的确切类型,但是X和X的子类可以安全的转型为X。
         * 总结:主要用于安全地写入数据,可以写入X及其子类型。
         */
//        supperAppleGenericClass.setData(new Fruit());

        //get方法只会返回一个Object类型的值。
        Object data = supperAppleGenericClass.getData();
    }

    /**
     * <?> 指定了没有限定的通配符
     */
    public static void printNonLimit(GenericClass<?> genericClass) {
        System.out.println(genericClass.getData());
    }

    public static void useNonLimit() {
        GenericClass<Food> foodGenericClass = new GenericClass<>();
        printNonLimit(foodGenericClass);
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printNonLimit(fruitGenericClass);
        GenericClass<Apple> appleGenericClass = new GenericClass<>();
        printNonLimit(appleGenericClass);

        GenericClass<?> genericClass = new GenericClass<>();
        //setData 方法不能被调用, 甚至不能用 Object 调用;
//        genericClass.setData(foodGenericClass);
//        genericClass.setData(new Object());
        //返回值只能赋给 Object
        Object object = genericClass.getData();

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值