• Java——泛型的作用


    什么是向下转型和向上转型。

    面向对象的转型只会发生在具有继承关系的父子类中(接口也是继承的一种)
    向上转型:其核心目的在于参数的统一上,根本不需要强制类型转换。
    向下转型:是为了操作子类定义的特殊功能,需要强制类型转换,可是现在存在的问题是:向下转型其实是一种非常不安全的操作,以为编译的时候,程序不会报错,而在运行的时候会报错,这就是传说中的—迷之报错。
    不过呢,在JDK1.5之后,新增加了泛型的技术,这就将上述向下转型的问题消灭在了萌芽之中。
    泛型的核心意义在于:类在进行定义的时候可以使用一个标记,此标记就表示类中属性或者方法以及参数的类型,标记在使用的时候,才会去动态的设置类型。
    源代码如下:

    package com.demo;
    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) {
            //1.设置数据
            Point p = new Point() ;
            p.setX(10);
            p.setY(20);
            //2.取出数据
            int x = (Integer) p.getX();
            int y = (Integer) p.getY();
            System.out.println("x地置"+ x +",y地置"+ y);
       }
    }

    坐标代码满足字符串的:

    package com.demo;
    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) {
            //1.设置数据
            Point p = new Point() ;
            p.setX("东经:100°");
            p.setY("北纬:20°");
            //2.取出数据
            String x = (String) p.getX();
            String y = (String) p.getY();
            System.out.println("x地置"+ x +",y地置"+ y);
       }
    }

    再来看看:泛型的基本表现形式:

    package com.demo;
    //此时设置的T在Point类定义上,只表示一个标记,在使用的时候需要为其设置具体的类型
    class Point<T> {  //定义坐标,这个"<>"里面的东西随意,Type = T,是表示一种类型
        private T x ;  //此属性的类型不确定,由Point类使用时动态决定
        private T y ;  //此属性的类型不确定,由Point类使用时动态决定
        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类的时候才设置标记的内容,也就是设置了类中的属性的类型。
    //下面用String试试:
    public class TestDemo {
        public static void main(String[] args) {
            //1.设置数据
            Point<String> p = new Point<>() ;  //JDK1.7之后实例化的泛型可以省略。
            //加入设置的数据类型是错误的,那么在编译的时候就会自动的排查了
            p.setX("东经:10°");
            p.setY("北纬:20°");
            //2.取出数据,由于我们接收的类型就是String,所以不需要向下强制转换
            String x =  p.getX();
            String y =  p.getY();
            System.out.println("x地置"+ x +",y地置"+ y);
       }
    }
    //输出之后发现,所有类中属性的类型,都是动态设置的,而所有使用泛型标记的方法参数类型也都发生改变,这样
    //就相当于避免了向下转型的问题,从而解决了转换的安全问题

    泛型的通配符:

    package com.demo;
    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<Integer> m1 = new Message<Integer>();
            Message<String> m2 = new Message<String>();
    
            m1.setMsg(10);
            m2.setMsg("Hello World");
            fun(m1) ;//引用传递
            fun(m2) ;
        }
        public static void fun(Message temp){
            System.out.println(temp.getMsg());
        }
    }
    
    /*以上代码为Message类设置的是一个String型的泛型类型,但是如果说
    现在设置的类型变了,那么fun()方法里面接收的"Message<String>"那么就不能够使用了,并且
    fun()方法不能够针对不同的泛型进行重载,因为方法的重载认的只是参数的类型,与泛型无关
    解决方法1.不设置泛型参数的泛型

    在接口上必须定义其相应的子类,如果要定义子类有以下两种方式:

    1.在子类上不设置泛型,但是在父类接口上要明确定义一个泛型。代码如下:

    package com.demo;
    
    interface IMessage<T>{//设置泛型接口
        public void print(T t) ;
    }
    //子类也继续使用泛型,并且父接口使用和子类同样的泛型标记
    class MessageImpl implements IMessage<String> {
    
        @Override
        public void print(String t) {
            // TODO Auto-generated method stub
            System.out.println(t);
        }
    
    }
    public class TestDemo {
        public static void main(String[] args) {
            IMessage<String> msg = new MessageImpl();
            msg.print("Hello World!") ;
        }
    }

    2.在子类上继承实例化泛型

    package com.demo;
    
    interface IMessage<T>{//设置泛型接口
        public void print(T t) ;
    }
    //子类也继续使用泛型,并且父接口使用和子类同样的泛型标记
    class MessageImpl<T> implements IMessage<T> {
        public void print(T t){
            System.out.println(t);
        }
    
    }
    public class TestDemo {
        public static void main(String[] args) {
            IMessage<String> msg = new MessageImpl<String>();
            msg.print("Hello World!") ;
        }
    }

    总结:泛型主要针对向下转型时所带来的安全隐患,其核心组成是在声明类或接口时,不设置参数或属性的类型。

  • 相关阅读:
    GetClassLoader和GetCallerClass的使用
    Maven的生命周期和插件
    对象池原理简要描述
    Git x SVN rebase事故
    Git 二进制文件冲突解决
    Git x SVN 当前工作流程
    Laya 项目解耦
    Laya 利用JS进行反射
    Laya Tween 和 遮罩
    Laya Tween循环
  • 原文地址:https://www.cnblogs.com/xingchong/p/12721961.html
Copyright © 2020-2023  润新知