• Java 泛型


    Java 泛型技术产生的原因:

    package cn.mldn.utli;
    
    class Point {
        private Object x ;
        private Object y ;
        public void setX( Object x ) {
            this.x = x ;
        }
        public void setY( Object y ) {
            this.y = y ;
        }
        public Object getX() {
            return x ;
        }
        public Object getY() {
            return y ;
        }
    }
    
    public class TestDemo {
    
        public static void main(String[] args) {
            Point p = new Point() ;
            p.setX(10);
            p.setY(20);
            
            int x = (Integer) p.getX();
            int y = (Integer) p.getY();
            System.out.println(x + y) ;
        }
    }

     上述的程序中,利用Point类存储整型数据,利用Object对象进行存储,向下转型为int型

    public class TestDemo {
    
        public static void main(String[] args) {
            Point p = new Point() ;
            p.setX(10.1);
            p.setY(20.2);
            
            double x = (Double) p.getX();
            double y = (Double) p.getY();
            System.out.println(x + y) ;
        }
    }

     上述代码则是利用Point类存储小数,利用Object对象进行存储,向下转型为Double型

    public class TestDemo {
    
        public static void main(String[] args) {
            Point p = new Point() ;
            p.setX("上海");
            p.setY("南京");
            
            String x = (String) p.getX();
            String y = (String) p.getY();
            System.out.println(x + y) ;
        }
    }

      上述代码则是利用Point类存储String数据内容,利用Object对象进行存储,向下转型为String型

    ————————————————

    上述的三段代码,均利用Point类进行三种不同类型的多类型同对象的存储,而Point类中是利用Object进行存储的,于是可以在调用处通过向下转型的方式将Object转为int/double/String等类型数据(装箱/拆箱)。

    泛型技术:类在定义的时候可以只用一个标记,此标记表示类中属性或方法参数的类型标记,在使用的时候才动态的设置:

    package cn.mldn.utli;
    // 此时设置的T在Point定义上只表示一个标记,在使用的时候需要为其设置具体额类型
    class Point<T> {  // Type = T , 是一个类型
        private T x ; // x的属性类型不明,有Point在使用时动态使用
        private T y ;
        public void setX( T x ) {
            this.x = x ;
        }
        public void setY( T y ) {
            this.y = y ;
        }
        public T getX() {
            return x ;
        }
        public T getY() {
            return y ;
        }
    }

      在使用Point类的时候才取设置的内容,也就是设置了类中属性的类型;

    public class TestDemo {
    
        public static void main(String[] args) {
            Point<String> p = new Point<String>() ;
         // 利用的就是包装类的自动装箱功能 p.setX(
    "上海"); p.setY("南京"); // 由于泛型的特性,使用的时候动态的设置Point接收的类型为String类型,所以返回的也是String类型就不用在转型了 String x = p.getX(); String y = p.getY(); System.out.println(x + y) ; } }

      使用泛型之后,所有类中属性的类型都是动态设置的,而所有使用泛型标记的方法参数类型也都是会发生改变。由此避免了向下转型的安全问题隐患。

      如果是采用泛型,那么它能够接受的数据类型只能是基本数据类型的包装类表示,不可以引用类型!

    #  在使用泛型类或者接口的时候,没有设置泛型的具体类型,会报错。(如果在没有设置泛型的具体类型的时候,所有泛型使用Object描述泛型的数据类型)

    #  在JDK1.7后可以简化泛型:可以将实例化的泛型具体类型的定义省略

    ——————————

    泛型通配符:

    package cn.mldn.utli;
    
    class Message<T> {  
        private T msg ;
        public void setMsg(T msg) {
            this.msg = msg ;
        }
        public T getMsg() {
            return msg ;
        }
    }
    
    public class TestDemo {
    
        public static void main(String[] args) {
            Message<String> m = new Message<> ();
            m.setMsg("Hello World!");
            fun(m) ;  // 引用传递
        }
        public static void fun(Message<String> temp) {
            System.out.println(temp.getMsg()) ;
        }
    }

      上述代码为Message类设置的是一个String的泛型对象;

      如果我们需要一个可以接收任何类型的泛型数据,则可以使用 “?” 符号代替 "<>" 定义类型;如此以来则可以接收任何的泛型,但是不可以更改,只可以取出。

    public class TestDemo {
    
        public static void main(String[] args) {
            Message<String> m = new Message<> ();
            m.setMsg("Hello World!");
            fun(m) ;  // 引用传递
        }
        public static void fun(Message<?> temp) {
            System.out.println(temp.getMsg()) ;
        }
    }

      在 “?”的通配符上 还有两个子通配符:

        ~ ? extends 类:设置泛型上限,可以在泛型声明上和方法参数上使用;

            |-- ? extends  Number : 意味着可以设置Number或者子类的泛型

        ~ ? super 类: 设置泛型的下限,方法参数上使用;

            |-- ?super String : 意味只能设置String或者它的父类(Object)

    泛型接口:

     定义泛型接口

    interface Message<T> { //设置泛型接口
        public void print(T t) ;
    }

    在接口上定义其相应的子类,定义子类主要有两种形式:

    形式一:在子类上继续设置泛型

    package cn.mldn.utli;
    
    interface Message<T> { //设置泛型接口
        public void print(T t) ;
    }
    class MessageImpl<T> implements Message<T> {
        public void print(T t) {
            System.out.println(t) ;
        }
    }
    
    public class TestDemo {
    
        public static void main(String[] args) {
            Message<String> msg = new MessageImpl<String>() ; // 向上转型实例化
            msg.print("Hello World!");
        }    
    }

    形式二:在子类不设置泛型,而父接口明确定义一个泛型类型

    package cn.mldn.utli;
    
    interface Message<T> { //设置泛型接口
        public void print(T t) ;
    }
    class MessageImpl implements Message<String> {
    // 接口泛型的第二种定义方法,直接在实现接口的接口处明确一个泛型类型;由此实例化的时候不用设置泛型的具体类型
        public void print(String t) {
            System.out.println(t);        
        }
        
    }
    
    public class TestDemo {
    
        public static void main(String[] args) {
            Message msg = new MessageImpl() ; // 向上转型实例化
            msg.print("Hello World!");
        }    
    }

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

    泛型方法:

      泛型方法不一定定义在支持泛型的类中。

    泛型方法的定义:

    package cn.mldn.utli;
    
    public class TestDemo {
    
        public static void main(String[] args) {
            String str = fun("Hello,World!") ;
            System.out.println(str);
        }    
        // T 泛型类型由传入的参数类型决定
        public static <T> T fun(T t) {
            return t;
        }
    }

    ————————

    泛型总结:

      泛型特性解决的是向下转型所带来的安全隐患,其核心的组成就是在声明类或接口中不用设置具体的参数类型;

      ? 符号可以接收任意的泛型类型,但是只能够取出,不能够修改

    ~~~~

  • 相关阅读:
    Fragment生命周期详解
    VS常用快捷键
    转载:C#中的泛型
    Vue 引入代码代码编辑器monacoeditor并自定义语法提示
    Monaco Editor 参数配置详解
    关于uniapp生成证书数字签名(.keystore)文件
    C#上传到FTP Server
    Linux下静态编译glib
    简单谈谈haskell
    hi,大家
  • 原文地址:https://www.cnblogs.com/wangyuyang1016/p/10907191.html
Copyright © 2020-2023  润新知