@(工作笔记)

generic-record

Alt text

[TOC]


泛型(Generics)

  • 泛型是JDK1.5中一个最重要的特征。通过引入泛型,我们将获得编译时类型的安全和运行时更小地抛出ClassCastExceptions的可能。
  • 在JDK1.5中,你可以声明一个集合将接收/返回的对象的类型

泛型之前

  • 类别定义时的逻辑完全一样,只是里面成员变量的类型不同
  • 如果需要多个相似的类,需要定义多个文件,不同的只是变量的类别,而逻辑是完全一样的

所谓泛型:就是变量类型的参数化。


类中使用

class Person<T, K, A, V> {

  private String   username;
  private T        friend;
  private K        country;
  private A[]      address;
  private Object[] versions;

  static {}

  {}

  public void getSimpleAddress() {
    // 没有办法消除警告,只能强转
    address = (A[]) new Objects[10];
  }

  public V getSimpleVersions(int index) {
    // 没有办法消除警告,只能强转,ArrayList也是这么实现的,参考get方法
    return (V) versions[index];
  }

  Person() {}

  public Person(String username, T friend) {
    this.username = username;
    this.friend   = friend;
  }

  @Override
  public String toString() {
    return new StringJoiner(", ", Person.class.getSimpleName() + "[", "]")
        .add("username='" + username + "'")
        .add("friend=" + friend)
        .add("country=" + country)
        .add("address=" + Arrays.toString(address))
        .toString();
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public T getFriend() {
    return friend;
  }

  public void setFriend(T friend) {
    this.friend = friend;
  }

  public K getCountry() {
    return country;
  }

  public void setCountry(K country) {
    this.country = country;
  }

  public A[] getAddress() {
    return address;
  }

  public void setAddress(A[] address) {
    this.address = address;
  }
}

限制泛型可用类型

  • 在定义泛型类别时,预设可以使用任何的类型来实例化泛型类型中的类型,但是如果想要限制使用泛型类别时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口·
  • 当没有指定泛型继承的类型或接口时,默认使用T extends Object,所以默认情况下任何类型都可以作为参数传入
class Human {

}

class Person<F extends Human> {

  private F friend;

  public F getFriend() {
    return friend;
  }

  public void setFriend(F friend) {
    this.friend = friend;
  }
}
  • 使用<?>或是<? extends SomeClass>的声明方式,意味着你只能通过该名称来取得所参考实例的信息,或者是移除某些信息,但不能增加它的信息,因为只知道当中放置的事SomeClass的子类,但不确定是什么类的实例,编译器不让你加入信息,理由是,如果可以键入信息的话,那么你就得记得取回的实例是什么类型,然后转换为原来的类型方可进行操作,这就失去了使用泛型的意义。

java 泛型中 T 和 问号(通配符)的区别

https://blog.csdn.net/jianghuxiaojin/article/details/51457773

通配符(?)

当在赋值的时候,上面一节说赋值的都是为具体类型,当赋值的类型不确定的时候,我们用通配符(?)代替了:

List<?> unknownList;
List<? extends Number> unknownNumberList;
List<? super Integer> unknownBaseLineIntgerList;

在Java集合框架中,对于参数值是未知类型的容器类,只能读取其中元素,不能向其中添加元素, 因为,其类型是未知,所以编译器无法识别添加元素的类型和容器的类型是否兼容,唯一的例外是NULL

Java 泛型 <? super T> 中 super 怎么 理解?与 extends 有何不同?

https://www.zhihu.com/question/20400700

  • <? extends T>:是指 “上界通配符(Upper Bounds Wildcards)”
  • <? super T>:是指 “下界通配符(Lower Bounds Wildcards)”
  • Plate<? extends Fruit>
    

    翻译成人话就是:一个能放水果以及一切是水果派生类的盘子。再直白点就是:啥水果都能放的盘子。这和我们人类的逻辑就比较接近了。Plate<? extends Fruit>和Plate最大的区别就是:Plate<? extends Fruit>是Plate以及Plate的基类。直接的好处就是,我们可以用“苹果盘子”给“水果盘子”赋值了.

    在这个体系中,上界通配符 “Plate<? extends Fruit>” 覆盖下图中蓝色的区域。

    preview

    什么是下界?

    相对应的,“下界通配符(Lower Bounds Wildcards)**”**:

    Plate<? super Fruit>
    

    表达的就是相反的概念:一个能放水果以及一切是水果基类的盘子Plate<? super Fruit>是Plate的基类,但不是Plate的基类。对应刚才那个例子,Plate<? super Fruit>覆盖下图中红色的区域。

    preview

    下界<? super T>不影响往里存,但往外取只能放在Object对象里

    使用下界<? super Fruit>会使从盘子里取东西的get( )方法部分失效,只能存放到Object对象里。set( )方法正常。

    Plate<? super Fruit> p=new Plate<Fruit>(new Fruit());
    
    //存入元素正常
    p.set(new Fruit());
    p.set(new Apple());
    
    //读取出来的东西只能存放在Object类里。
    Apple newFruit3=p.get();    //Error
    Fruit newFruit1=p.get();    //Error
    Object newFruit2=p.get();
    

    因为下界规定了元素的最小粒度的下限,实际上是放松了容器元素的类型控制。既然元素是Fruit的基类,那往里存粒度比Fruit小的都可以。但往外读取元素就费劲了,只有所有类的基类Object对象才能装下。但这样的话,元素的类型信息就全部丢失。


    定义含有泛型的方法

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

    • 格式

      修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)) {

      ​ 方法体

      }

    • 含有泛型的方法,在调用方法的时候确定泛型的数据类型,传递什么类型参数,泛型就是什么类型

     public static <T> void foo(T t) {
        dlog(t.getClass(), new Info("t.getClass()"));
     }
    
    // public static <T> 是声明该方法是泛型函数
    

    results matching ""

      No results matching ""