zoukankan      html  css  js  c++  java
  • [Java 学习笔记] 泛型

    目录

     泛型的向上转型

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

    多泛型类

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

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

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

    泛型继承(loading)

    通配符(loading)

    泛型与反射(loading)


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

    Java教程 - 廖雪峰的官方网站 (liaoxuefeng.com)icon-default.png?t=L9C2https://www.liaoxuefeng.com/wiki/1252599548343744 


     泛型的向上转型

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

    public class ArrayList<T> implements List<T> {
        ...
    }
    
    List<String> list = new ArrayList<String>();
    

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

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

    !注意:不能把ArrayList<Integer>向上转型为ArrayList<Number>List<Number>

    假设ArrayList<Integer>向上转型为ArrayList<Number>

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

    总结:

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

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

    另外须知: ArrayList<Integer>和ArrayList<Number>两者完全没有继承关系


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

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

    下面的代码编译错误

    public class Pair<T> {
        private T first;
        private T last;
        public Pair(T first, T last) {
            this.first = first;
            this.last = last;
        }
        public T getFirst() { ... }
        public T getLast() { ... }
    
        // 对静态方法使用<T>:
        public static Pair<T> create(T first, T last) {
            return new Pair<T>(first, last);
        }
    }

     正确表示如下

    public class Pair<T> {
        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 <K> Pair<K> create(K first, K last) {
            return new Pair<K>(first, last);
        }
    }


    多泛型类

    
    class Pair<T,K>
    {
        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<String, Integer> p1 = new Pair<>("泥烟", 8080);
            System.out.println(p1.getFirst()+p1.getSecond());
        }
    }
    
    
    
    

    运行结果:

    输出→ 泥烟8080 

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

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

    Java中创建泛型数组 - minghai - 博客园 (cnblogs.com)icon-default.png?t=L9C2https://www.cnblogs.com/minghaiJ/p/11259318.html

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

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

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

    局限一<T>不能是基本类型,例如int,因为实际类型是ObjectObject类型无法持有基本类型

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

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

    有如下类

    class Pair<T> {
        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<String> p1 = new Pair<>("Hello", "world");
        Pair<Integer> 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<Object> 

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

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

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

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

    public class Pair<T> {
        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)

  • 相关阅读:
    预搜索,不匹配;反向预搜索,不匹配
    反向引用 /1, /2...
    贪婪与非贪婪模式
    其他一些代表抽象意义的特殊符号
    修饰匹配次数的特殊符号
    自定义能够匹配 ' 多种字符' 的表达式
    能够与 ' 多种字符' 匹配的表达式
    6)添加带有颜色的那个画板
    5)添加快捷键
    4)记住我的图形
  • 原文地址:https://www.cnblogs.com/Knight02/p/15799065.html
Copyright © 2011-2022 走看看