[Java 学习笔记] 泛型

[Java 学习笔记] 泛型,第1张

[Java 学习笔记] 泛型

目录

 泛型的向上转型

将静态方法的泛型类型和实例类型的泛型类型区分开

多泛型类

java可以创建泛型数组(待完善)

Java实现泛型的方法——擦拭法

由此,Java泛型的局限也体现出来

泛型继承(loading)

通配符(loading)

泛型与反射(loading)


总结自廖雪峰老师的Java教程: 

Java教程 - 廖雪峰的官方网站 (liaoxuefeng.com)https://www.liaoxuefeng.com/wiki/1252599548343744 


 泛型的向上转型

在Java标准库中,  ArrayList实现了List接口,它可以向上转型为List

public class ArrayList implements List {
    ...
}

List list = new ArrayList();

编译器看到泛型类型List就可以自动推断出后面的ArrayList的泛型类型必须是ArrayList,代码可以简写为:

// 可以省略后面的Number,编译器可以自动推断泛型类型:
List list = new ArrayList<>();

 

!注意:不能把ArrayList向上转型为ArrayList或List

假设ArrayList向上转型为ArrayList

// 创建ArrayList类型:
ArrayList integerList = new ArrayList();

// 添加一个Integer:
integerList.add(new Integer(123));

// “向上转型”为ArrayList:
ArrayList numberList = integerList;

// 添加一个Float,因为Float也是Number:
numberList.add(new Float(12.34));

// 从ArrayList获取索引为1的元素(即添加的Float):
Integer n = integerList.get(1); // ClassCastException!
  • 一个ArrayList转型为ArrayList类型后,这个ArrayList就可以接受Float类型,因为Float是Number的子类。
  • 而numberList 实际上和integerList 是同一个对象(ArrayList类型),不可能接受Float类型, 在获取Integer的时候将产生ClassCastException。

总结:

编译器为了避免这种错误,根本就不允许把ArrayList转型为ArrayList

注意泛型的继承关系:可以把ArrayList向上转型为List(T不能变),但不能把ArrayList向上转型为ArrayList(T不能变成父类)

▲另外须知: ArrayList和ArrayList两者完全没有继承关系。

 


将静态方法的泛型类型和实例类型的泛型类型区分开

注意,泛型类型不能用于静态方法

下面的代码编译错误

public class Pair {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { ... }
    public T getLast() { ... }

    // 对静态方法使用:
    public static Pair create(T first, T last) {
        return new Pair(first, last);
    }
}

 正确表示如下

public class Pair {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() { ... }
    public T getLast() { ... }

    // 静态泛型方法应该使用其他类型区分:
    public static  Pair create(K first, K last) {
        return new Pair(first, last);
    }
}


多泛型类
class Pair
{
    private T first;
    private K second;

    public Pair(T first, K second){
        this.first = first;
        this.second = second;
    }

    public T getFirst(){
        return this.first;
    }
    public K getSecond(){
        return this.second;
    }
}
public class pairx {
    public static void main(String[] args) {
        Pair p1 = new Pair<>("泥烟", 8080);
        System.out.println(p1.getFirst()+p1.getSecond());
    }
}



运行结果:

输出→ 泥烟8080 

另外java是可以创建泛型数组的(还未完全掌握,之后完善):

java可以创建泛型数组(待完善)

Java中创建泛型数组 - minghai - 博客园 (cnblogs.com)https://www.cnblogs.com/minghaiJ/p/11259318.html

Java实现泛型的方法——擦拭法

Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。

由此,Java泛型的局限也体现出来

局限一:不能是基本类型,例如int,因为实际类型是Object,Object类型无法持有基本类型:

Pair p = new Pair<>(1, 2); // compile error!

 局限二:无法取得带泛型的Class

有如下类

class Pair {
    private T first;
    private T last;
    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }
    public T getFirst() {
        return first;
    }
    public T getLast() {
        return last;
    }
}

    Pair p1 = new Pair<>("Hello", "world");
    Pair p2 = new Pair<>(123, 456);
    Class c1 = p1.getClass();
    Class c2 = p2.getClass();
    System.out.println(c1==c2); // true
    System.out.println(c1==Pair.class); // true

 

无论T的类型是什么,getClass()返回同一个Class实例,因为编译后它们全部都是Pair 

局限三:无法判断带泛型的类型,原因同上

Pair p = new Pair<>(123, 456);
// Compile error:
if (p instanceof Pair) {
    ...
}

并不存在Pair.class,而是只有唯一的Pair.class

局限四:不能直接实例化T类型 

public class Pair {
    private T first;
    private T last;
    public Pair() {
        // Compile error:
        first = new T();
        last = new T();
    }
}



擦拭后实际上变成了:

first = new Object();
last = new Object();

将其实例化的方法

 (待续...)

泛型继承(loading)

通配符(loading)

泛型与反射(loading)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/3974326.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-10-21
下一篇 2022-10-21

发表评论

登录后才能评论

评论列表(0条)