Java 读书笔记 15泛型

本文深入探讨了泛型的概念及其在编程中的应用,包括泛型类、泛型方法、协变、通配符等,并通过实例说明了如何利用泛型提高代码的复用性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型

泛型的来源,首先我们知道类是存在聚合的,就是这个类有其他类的对象;那么问题来了,我今天用你,明天用别人;怎么办呢?

public class Automobile {      //普通模式有这么一个类
}
public class Holder1 {
    private  Automobile a;     //类间聚合;但是你必须编译的时候就定义啊;
    public  Holder1(Automobile a)   //完全不能改变的时候
    {
        this.a=a;
    }
    Automobile get()
    {
        return  a;
    }



    private  Object b;        //定义Object可以通过向下转型的方式储存其他对象,但是自然是麻烦的;
    public  Holder1(Object b)
    {
        this.b=b;
    }
    public  void  setB(Object b)
    {
        this.b = b;
    }
    public Object getB() {
        return b;
    }
}

然后泛型自然就出来;

public class Holder2<T> {      //定义一个Tpye,谁来换成谁,多好;
    private  T a;

    public Holder2(T a) {
        this.a = a;
    }

    public T getA() {
        return a;
    }

    public void setA(T a) {
        this.a = a;
    }
}

元组类库

  1. 就是通过泛型聚合多个类对象;使得一个对象可以携带多个对象,而且还是可以随便更改的对象;

泛型方法

  1. 不靠泛型类,方法泛型就行,就像下面
  2. static方法如果使用泛型必须成为泛型方法,简单的讲,因为static方法和类一起加载,那时就可以直接调用static方法了,而你的tpye是啥都不知道;而构造函数虽然也是隐藏的static,但我们就是通过人家获得的tpye的,soso。。
public class GenericMethods {
    public  <T> void  f(T x)
    {
        System.out.println(x.getClass().getName());
    }
    public  static  void  main(String [] arg)
    {
        GenericMethods genericMethods = new GenericMethods();
        genericMethods.f("");
        genericMethods.f(1);
        genericMethods.f(new HelloA());
    }
}

吐槽

编程思想这本书真的是,有太多和java思想无关的内容,而只是经验之谈,还有一些事设计模式,说的太杂;

泛型擦除

public class Foo<T> {
    T a;
    List<T> create (T t,int n)
    {
        List<T> result = new ArrayList<T>();
        for (int i = 0;i< n ;i++) {
            result.add(t);
        }
            return result;

    }
    public  String toString()
    {
        return  a.getClass().getName();
    }
    public static void  main(String []arg)
    {
        Foo<Holder1> holder1Foo= new Foo<>();
        Foo<String> foo = new Foo<>();
      List<String> list=  foo.create("hello",4);
        System.out.println(list);      //虽然擦除了类型,但是编译器还是知道你存的是什么,
        System.out.println(holder1Foo.getClass().getName()); //简单说,编译器帮我们又转型了;
        System.out.println(holder1Foo.toString()); //报错,因为它根本不知道是哪个类的
    }
}

协变

  1. 子类可以赋值给父类,就称为协变;
  2. 数组也可以协变,但是这货会存在陷阱一样的错误
class Fruit {}
class Apple extends Fruit {}
class Jonathan extends Apple {}
class Orange extends Fruit {}

public class CovariantArrays {
    public static void main(String[] args) {       
        Fruit[] fruit = new Apple[10];
        fruit[0] = new Apple(); // OK
        fruit[1] = new Jonathan(); // OK
        // Runtime type is Apple[], not Fruit[] or Orange[]:
        try {
            // Compiler allows you to add Fruit:
            fruit[0] = new Fruit(); // ArrayStoreException
        } catch(Exception e) { System.out.println(e); }
        try {
            // Compiler allows you to add Oranges:
            fruit[0] = new Orange(); // ArrayStoreException
        } catch(Exception e) { System.out.println(e); }
        }
} /* Output:
java.lang.ArrayStoreException: Fruit
java.lang.ArrayStoreException: Orange

然后就是泛型了,它不支持协变,父类和子类不能直接赋值;

通配符

public static void printList(List<?> list) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
    //一下操作不可以
    list.add(1);
    list.add("123");
}

原因在于:?就是表示类型完全无知,? extends E表示是E的某个子类型,但不知道具体子类型,如果允许写入,Java就无法确保类型安全性。假设我们允许写入,如果我们传入的参数是List,此时进行add操作,可以添加任何类型元素,就无法保证List的类型安全了。

超类型

public static void printList(List<? super String> list) {
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
    list.add("123");
    list.add("456");
}

这个很好理解,list的参数类型是String的上界,必然可以添加String类型的元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值