zoukankan      html  css  js  c++  java
  • 泛型

      泛型是java1.5之后才引入的,为什么要引入泛型:

      1 为了使类型参数化

      2 提高类型的安全性并简化类型转换的过程,在泛型处理过程中,类型的转换都是自动和隐士的,泛型让类型检查从运行期提前到编译器,出错能预先提示。

    在没有泛型的情况:

    class TestObj{
        private Object obj = null;
        public TestObj(Object obj) {
            this.obj = obj;
        }
        public void speak() {
            System.out.println(this.obj.getClass());
        }
        public Object getObj() {
            return obj;
        }
    }
    
    
            Integer i1 = new Integer(10);
            TestObj to = new TestObj(i1);
            
            to.speak();
            Integer i2 =(Integer)to.getObj();
            System.out.println(i2);
        

    在这里Integer i2 =(Integer)to.getObj(); 类型转换是不安全的。如果不能确认object类型是integer 那么就会出错。

    在看看泛型:

    class GenObj <T>{
        private T obj;
        public GenObj(T obj){
            this.obj = obj;
        }
        public void speak() {
            System.out.println(obj.getClass());
        }
        public T getObj() {
            return (T)obj;
        }
    }
    
            Integer i1 = new Integer(10);
            //GenObj go = new GenObj(i1);
            GenObj<String> go = new GenObj<String>("123");
            go.speak();
            
        

    如果用GenObj go = new GenObj(i1); 来实例化引入泛型的对象会出现警告:

    提示说要对通用类型的引用参数化,这里参数化就是<>里的,这句话就是开头说的为了使类型参数化;

    引入的泛型之后就不用使用显示的强制类型转换了。

            Integer i1 = new Integer(10);
            //GenObj go = new GenObj(i1);
            GenObj<String> go = new GenObj<String>("123");
            go.speak();
            String st1 = go.getObj();
            System.out.println(st1);
        

    如果类型错误,编译器会报错。
    泛型参数T 必须是引用类型,不能基本数据类型(int long char等等);

    多个参数的泛型:

    class MutilGen<K,V>{
        private K k1;
        private V v1;
        public MutilGen(K k1,V v1) {
            this.k1 = k1;
            this.v1 = v1;
        }
        public K getK1() {
            return k1;
        }
        public V getV1() {
            return v1;
        }
        public void speak() {
            System.out.println(this.k1.getClass()+":"+this.k1.toString());
            System.out.println(this.v1.getClass()+":"+this.v1.toString());
        }
    }
            MutilGen<String, Integer> mg = new MutilGen<String, Integer>("你好", 1);
            mg.speak();

    执行结果是:
    class java.lang.String:你好
    class java.lang.Integer:1

    多参数用逗号隔开。

    泛型的类型边界

    为什么要有类型边界呢,看下面这个程序。

    public class SumTest<M> {
    
        M[] tsMs;
        double sum=0;
        public SumTest(M[] tsMs) {
            this.tsMs = tsMs;
        }
        public double Sum() {
            for(int i=0;i<tsMs.length;i++) {
                sum +=tsMs[i].doubleValue();        }
            return sum;
       }
    }

    这里tsMs[i].doubleValue();会报错,为什么呢,因为定义的泛型参数M 编译器并不知道是什么类型,所以这里用doubleValue()肯定是不行的。如果我们确认传入的参数一些数据类型,也就是说这些参数是在一个范围的,有点像c语言的枚举类型,将泛型参数的边界确定下来,看修改之后的程序:

    public class SumTest<M extends Number> {
    
        M[] tsMs;
        double sum=0;
        public SumTest(M[] tsMs) {
            this.tsMs = tsMs;
        }
        public double Sum() {
            for(int i=0;i<tsMs.length;i++) {
                sum +=tsMs[i].doubleValue();
            }
            return sum;
        }
        
        public static void main(String[] args) {
            Integer[] intArr = new Integer[3];
            ArrayList<Integer> intList = new ArrayList<Integer>();
            intList.add(100);
            intList.add(10);
            intList.add(200);
            intArr = intList.toArray(new Integer[0]);
            SumTest<Integer> st = new SumTest<Integer>(intArr);
            System.out.println(st.Sum());
        }
    }

    结果是310.0
    因为数据类型 Byge Double Long Integer Short的父类是Number,所以用externds 来确定泛型M的边界,我感觉非常类似与c语言里的枚举类型,举个例子:

    typedef enum{
        Monday = 0,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    }Week;
    
    void ShowDay(Week day){
        switch(day){
            case 0:printf("Monday
    ");break;            
            case 1:printf("Monday
    ");break;
            case 2:printf("Tuesday
    ");break;
            case 3:printf("Wednesday
    ");break;
            case 4:printf("Thursday
    ");break;
            case 5:printf("Saturday
    ");break;
            case 6:printf("Sunday
    ");break;
            default:break;
        }
    }
    ShowDay(Monday);


    通配符:

        M[] tsMs;
        double sum=0;
        public SumTest(M[] tsMs) {
            this.tsMs = tsMs;
        }
        public double Sum() {
            for(int i=0;i<tsMs.length;i++) {
                sum +=tsMs[i].doubleValue();
            }
            return sum;
        }
        public boolean SumEqual(SumTest<M> st) {
            if(this.Sum() == st.Sum()) {
                return true;
            }else {
                return false;
            }    
        }
        public static void main(String[] args) {
            Integer[] intArr = {1,2,3};
            Integer[] intArr1 = {1,2,3};
            Double[] dblArr = {1.0,2.0,3.0};
            SumTest<Integer> st = new SumTest<Integer>(intArr);
            SumTest<Integer> st1 = new SumTest<Integer>(intArr1);
            SumTest<Double> st2 = new SumTest<Double>(dblArr);
            System.out.println(st.SumEqual(st1));
            System.out.println(st.SumEqual(st2));//这里会报错  
    }

    这里加入一个public boolean SumEqual(SumTest<M> st) 方法,传入的是参数是SumTest,如果按照这样定义会出现参数不匹配,这里很好理解,因为st1传入的是Integer,而st2是Double类型,那么怎么解决这个问题呢。将泛型参数<M>改成通配符<?>即可。

        public boolean SumEqual(SumTest<?> st) {
            if(this.Sum() == st.Sum()) {
                return true;
            }else {
                return false;
            }    
        }

    结果是:
    true
    false

    这个只不过是自己的流水账,偶尔有一些心得,错误的地方概不负责
  • 相关阅读:
    ADB高级应用
    struts2 结合extjs实现的一个登录实例
    css3中关于伪类的使用
    漫谈并发编程(三):共享受限资源
    awk依照多个分隔符进行切割
    3星|《财经天下周刊》2017年21期:海外购几乎是亚马逊中国的最后一根救命稻草
    3星|《迷失的盛宴:中国保险产业1978-2014》:序言比正文精彩
    3星|《超级运营术》:互联网社区运营老手经验谈
    3星|《百年流水线》:流水线与工业、社会、艺术的交互史
    5星|戴蒙德《为什么有的国家富裕,有的国家贫穷》:为什么有的国家能发展出好制度
  • 原文地址:https://www.cnblogs.com/ashitaka/p/5273043.html
Copyright © 2011-2022 走看看