泛型------能够代表一切类型

为什么需要用泛型?

示例

以下是一个栈的实现代码

package FFF;

public class Test {
    public static void main(String[] args) {
        Stack stack=new Stack(5);
        stack.add(1);
        stack.add(2);
        stack.add(3);
        stack.add(4);
        System.out.println(stack.get());
        System.out.println(stack.get());
        System.out.println(stack.get());
        System.out.println(stack.get());
    }
}
package FFF;
/***
 * 定义一个栈
 * 数据先进后出
 */

public class Stack {
    //定义数组
    private int[] arr;
    private int i=-1;
    public Stack(int size){
        arr=new int[size];
    }
    public void add(int value){
        i++;
        arr[i]=value;
    }
    public int get(){
        return arr[i--];
    }
}

如果我们定义只能在栈当中存储一种数据类型,如果想要存储其他数据类型,需要对private int[] arr; 数组的类型进行修改

这样的话,每次存储不同数据类型的数组,就需要更改定义,这是十分麻烦的。

因此,我们需要用泛型定义数据,因为泛型能够代表一切类型

泛型类的定义

泛型类的定义语法

class 类名称 <泛型标识、泛型标识,...> {
    private 泛型标识 变量名;//可以有多个泛型标识,此时需要一次性传多个值
    ......
}
  • 常用的泛型标识 T、E、K、V

泛型类的定义案例

/**
 * 泛型类的定义
 * @param <T> 泛型标识-----类型形参
 *           T 创建对象的时候里面具体制定的数据类型
 */
public class Generic<T> {

    // T 是由外部使用类的时候来指定的。
    private T key;

    public Generic(T key) {
        this.key = key;
    }

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }

    @Override
    public String toString() {
        return "Generic{" +
                "key=" + key +
                '}';
    }
}

泛型类的使用语法

使用语法

类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();

java 1.7以后,后边的<>中具体的数据类型可以省略不写

类名<具体的数据类型> 对象名 = new 类名<>();

泛型类的使用案例:

public static void main(String[] args) {
    // 泛型类在创建对象的时候来指定操作的具体数据类型
    Generic<String> stringGeneric = new Generic<>("a");
    String key = stringGeneric.getKey();
    System.out.println("key:" + key);

    System.out.println("------------------------");
    Generic<Integer> integerGeneric = new Generic<>(100);
    Integer key1 = integerGeneric.getKey();
    System.out.println("key1:"+key1);
    // 总结:泛型的本质是参数化类型,也就是所操作的数据类型被指定为一个参数。

    System.out.println("----------注意点1:--------------");
    // 泛型类在创建对象的时候,没有指定泛型类,将按照Object类型来操作
    Generic generic = new Generic("ABC");
    Object key3 = generic.getKey();
    System.out.println("key3:"+key3);
    
    System.out.println("----------注意点2:--------------");
    // 泛型类不支持基本数据类型,原因就是我们在编译期间会将这个 T 编译成 Object
    // 基本数据类型无法转化为 object类型
    // Generic<int> intGeneric = new Generic<>(100);

    System.out.println("----------注意点3:--------------");
    // 同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型
    System.out.println(integerGeneric.getClass() == stringGeneric.getClass());
}

  我们可以将最开始的例子中数组类型定义为泛型

package FFF;
/***
 * 定义一个栈
 * 数据先进后出
 */

public class Stack <T>{
    //定义数组
    private T[] arr;
    private int i=-1;
    public Stack(int size){
        arr= (T[]) new Object[size];//Object是所有数据类型的父类,父类转化为子类需要进行强转    }
    public void add(T value){
        i++;
        arr[i]=value;qi
    }
    public T get(){
        return arr[i--];
    }
}
package FFF;

public class Test {
    public static void main(String[] args) {
        Stack<Integer> stack=new Stack(5);//泛型当中只能用到包装类
        stack.add(1);
        stack.add(2);
        stack.add(3);
        stack.add(4);
        System.out.println(stack.get());
        System.out.println(stack.get());
        System.out.println(stack.get());
        System.out.println(stack.get());
        Stack<String> stack1=new Stack(5);
        stack1.add("北京");
        stack1.add("保定");
        stack1.add("沧州");
        stack1.add("石家庄");
        System.out.println(stack1.get());
        System.out.println(stack1.get());
        System.out.println(stack1.get());
        System.out.println(stack1.get());
    }
}

总结:泛型类注意事项

  • 泛型类,如果没有指定具体的数据类型,此时,操作类型是Object
  • 泛型的类型参数只能是类类型,不能是基本数据类型
  • 泛型类型在逻辑上可以看成是多个不同的类型,但实际上是相同类型

---------------------------------------------------------------------------------------------------------------------------------------------

小案例:年终抽奖器(可能会是奖金,也可能是奖品)

/**
 * 抽奖器
 * @param <T>
 */
public class ProductGetter<T> {

    //奖金或者奖品
     private T product;

     // 定义奖品、奖金池
     ArrayList<T> arrayList = new ArrayList<>();//创建了一个数组

     // 添加奖品到奖品池
     public void addProduct(T t){
         arrayList.add(t);
     }

     // 定义一个随机数,用来抽选奖品
    Random random = new Random();//Random生成一个随机数
     //抽奖
     public T getProduct(){
         product = arrayList.get(random.nextInt(arrayList.size()));
         return  product;
     }

}
public static void main(String[] args) {
   ProductGetter<String> stringProductGetter = new ProductGetter<>();
   String[] strPro = {"苹果手机","华为手机","扫地机器人","咖啡机"};
   //将奖品放入奖金池
   for (int i = 0;i< strPro.length;i++){
       stringProductGetter.addProduct(strPro[i]);
   }
    String product = stringProductGetter.getProduct();
    System.out.println("恭喜您抽中了:"+product);

    System.out.println("******************************");

    ProductGetter<Integer> IntegerProductGetter = new ProductGetter<>();
    Integer[] intPro = {100,1000,10000,20000};
    //将奖品放入奖金池
    for (int i = 0;i< intPro.length;i++){
        IntegerProductGetter.addProduct(intPro[i]);
    }
    Integer product1 = IntegerProductGetter.getProduct();
    System.out.println("恭喜您,获得了:"+product1+"元");

}

使用泛型类的优点

使用泛型可以避免频繁修改代码来适应不同的数据类型。例如在最初的栈的实现中,如果没有泛型,每次要存储不同类型的数据,都需要更改数组的类型定义,这会导致代码的冗余和维护的困难。而通过泛型,我们可以轻松地定义一个能够处理多种数据类型的栈,大大提高了代码的灵活性和可复用性。

从泛型类派生子类(2种情况)

子类也是泛型类,子类和父类的泛型类型要保持一致

class ChildGeneric<T> extends Generic<T>

子类不是泛型类,父类要明确泛型类的数据类型

class ChildGeneric extends Generic<String>

第一种情况:子类和父类的泛型类型要保持一致

定义父类

public class Parent<E> {

    private E value;

    public E getValue() {
        return value;
    }

    public void setValue(E value) {
        this.value = value;
    }
}

定义子类

/**
 * 泛型类派生子类,如果子类也是泛型类,子类的泛型标识要和父类一致。
 * @param <T>
 */
public class ChildFirst<T> extends Parent<T> {

    @Override
    public T getValue() {
        return super.getValue();
    }
}

 测试类

public static void main(String[] args) {
    ChildFirst<String> childFirst = new ChildFirst<>();
    childFirst.setValue("123");
    String value = childFirst.getValue();
    System.out.println(value);
}

第二种情况:子类没有使用 泛型

总结:子类不是泛型类,父类要明确泛型类的数据类型

泛型接口

泛型接口的语法定义

interface 接口名称 <泛型标识,泛型标识,...>{
    泛型标识 方法名();
    ......
}

泛型接口的使用(2种情况)

  • 实现类不是泛型类,接口要明确数据类型
  • 实现类也是泛型类,实现类和接口的泛型类型要一致

总结

  • 泛型的优势:提升代码的重用性和类型安全,避免在运行时出现类型错误。
  • 设计灵活的泛型类和接口,使得它们能够用于不同类型的数据,减少类型转换的需要。
  • 关注泛型的限制与注意事项,确保代码的可读性和可维护性。

欢迎大家点赞,评论,收藏和关注呦!!

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值