JAVA基础_泛型

什么是泛型

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉”类型”信息,是程序的运行效率不受影响,对于参数化的泛型类型,getClass()方法返回值和原始类型完全一样。由于编译生成的字节码会擦除泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,然后再调用add()方法即可

GenericDemo.java

public class GenericDemo {

    public static void main(String[] args) {

        // 未使用泛型,则可以添加任意Object类型的数据
        List noGrnerics = new ArrayList<>();
        noGrnerics.add(1);
        noGrnerics.add("hello");
        noGrnerics.add("1L");
        noGrnerics.add(new GenericDomain(1L,"Generic"));
        // 由于没有使用泛型,在取出数据时必须要知道某个位置上的某个数据的数据类型,并加以强制转换,否则要出错,除非用Object接收。
        Integer integer = (Integer) noGrnerics.get(0);
        System.out.println("integer = " + integer);
        // 由于不知道某个位置上的数据类型,用Object接收
        Object objIndex1 = noGrnerics.get(1);
        System.out.println("objIndex1 = " + objIndex1);
        Object objeIndex3 = noGrnerics.get(3);
        System.out.println("objeIndex3 = " + objeIndex3);
        // 虽然可以通过类对象来知道类属性,但是这样不是太麻烦了吗??
        System.out.println("objeIndex3.getClass() = " + objeIndex3.getClass());

        // 使用泛型
        List<String> strs = new ArrayList<>();
        strs.add("str1");
        strs.add("str2");
        strs.add("str3");
        // 因为指定了这个List中只能放置String类型的数据,当这里放置其他类型的数据时就会报错,因为不能装进去
        // 从某种角度上可以认为泛型解决了强制类型转换,使数据特征更明显,拥有一致性
//        strs.add(1);
        String str = strs.get(0);
        System.out.println("str = " + str);

    }

}

绕过编译时泛型,添加非泛型类型数据:GenericDemo2.java

public class GenericDemo2 {

    /**
     * 程序目标,向一个List<String>的泛型数组中添加Integer类型的数据
     *
     * @param args
     */
    public static void main(String[] args) {

        List<String> strs = new ArrayList<>();
        strs.add("str1");
        strs.add("str2");
        strs.add("str3");
        strs.add("str4");
        // 这里是添加不进去的,因为指定了泛型类型,且没有泛型擦除
        // strs.add(new Integer(1));
        System.out.println("Before add a Integer value : " + strs);

        // 通过泛型在运行时擦除的原理,利用反射向泛型中添加Integer数据
        Class<List<String>> clazz = (Class<List<String>>) strs.getClass();
        try {
            // 这里在利用反射获取add方法时,如果参数类型指定为String.class,
            // 则说明add方法为,java.util.ArrayList.add(java.lang.String)
            // 而我们传入了一个Integer类型的数据,则显然不能添加成功,会抛出 java.lang.NoSuchMethodException
            clazz.getDeclaredMethod("add", String.class).invoke(strs, new Integer(1));
            // 这里原因一样,java.util.ArrayList.add(java.lang.Integer) 但是用的int,
            // 请记住,java是强类型语言,这里不存在自动装箱和拆箱
            clazz.getDeclaredMethod("add", Integer.class).invoke(strs, 2);
            // 这里也是不正确的,因为Class<List<String>>指定了放String
            clazz.getDeclaredMethod("add", Integer.class).invoke(strs, new Integer(4));
            //同上
            clazz.getDeclaredMethod("add", int.class).invoke(strs, 5);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //正确做法
            try {
                clazz.getDeclaredMethod("add", Object.class).invoke(strs, 3);
                System.out.println("strs = " + strs);
                // 只有Object能行
                clazz.getDeclaredMethod("add", String.class).invoke(strs, "4");
                System.out.println("strs = " + strs);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
                    | NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("After add a Integer value : " + strs);
    }

}
时间: 2024-08-08 22:08:21

JAVA基础_泛型的相关文章

java基础之泛型用法

1.什么是泛型 泛型是java中保障类型安全的一种机制.它通过对变量类型的假设,实现变量类型的进行限制,从而在一定程度上保证程序编译时变量类型的安全.反之,如果没有泛型,这些假设则只存在于程序员的大脑中,这样会导致类型转换的异常在程序运行时才被发现. //不用泛型 List list1 = new ArrayList(); list1.add(1); Object o = list1.get(0); //返回Object类型对象 Integer i = (Integer) o; //需预先知道类

Java基础:泛型

Java的泛型是什么呢, 就是类型的参数化,这得类型包括方法参数和返回值,也就是原本该是确定类型的地方换成了变量,把类型的确定时间向后延迟了. 在之前,学过"重载"的概念,重载是什么呢,举例来说 public class Test{ // 处理整型数据 void receive(int i) { System.out.println("Received one int data"); System.out.println("i="+i); } /

Java基础巩固----泛型

注:参考书籍:Java语言程序设计.本篇文章为读书笔记,供大家参考学习使用   1.使用泛型的主要优点是能够在编译时而不是在运行时检查出错误,提高了代码的安全性和可读性,同时也提高了代码的复用性. 1.1如何理解泛型的使用提高了代码的安全性? 答:例如这样一段代码: ArrayList<Date> arrayList = new ArrayList<Date>(); arrayList.add(new Date()); arrayList.add("data")

java基础之泛型的继承

关于泛型的基本介绍和理解请参考以下几篇文章,或查询更多资料: 泛?型?与?泛?型?继?承 泛型(包括泛型抽象类的继承) 泛型的继承测试 本篇以简单的List<>方式来进行说明. ArrayList<Object>继承了List<Object>, ArrayList<String>没有继承List<Object> List<?>等价于List<? extends Object> 请参考以下代码: /** * author D

JAVA基础_自定义泛型

泛型的来源 在Java中,泛型借鉴了C++的模版函数,从而引入了泛型. C++泛型 int add(int x,int y){ return x + y; } float add(float x.float y){ return x + y; } double add(double x,double y){ return x + y; } // 泛型函数对上面的整数,浮点数的抽象和实现 template<class T> T add(T x,T y){ return x + y; } 自定义泛

Java基础:泛型详解

泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用.什么是泛型?为什么要使用泛型? 泛型,即“参数化类型”.一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参.那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参).泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型).也

Java基础_集合泛型

泛型 1.泛型概述 我们在集合中存储数据的时候,存储了String和Integer俩种类型的数据.而在遍历的时候,我们把它当做是String类型处理,做了转化,所以 会报错.但是呢?它在编译期间却没有告诉我们.所以我们觉得这一个设计的不好.所以集合也模仿着数组中在定义之前指明数据的类型,在 创建对象的时候明确元素的数据类型.这样就不会存在问题了.这一种技术被称为泛型. 2.泛型 是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊类型.参数化类型,把类型当作参数传递. 3.泛型定

Java基础教程——泛型

泛型 Generics:泛型,愿意指"无商标的". 泛型,可以理解为"宽泛的数据类型",就是将类型由原来的具体的类型泛化. 泛型在建立对象时不指定类中属性的具体类型,而是在声明及实例化对象时由外部指定.泛型可以提高数据安全性. List中应用了泛型,在编译期对数据类型进行严格 检查,如果类型不匹配,编译无法通过. 示例 : public interface List<E> extends Collection<E> E:Element T:T

黑马程序员——【Java基础】——泛型、Utilities工具类、其他对象API

一.泛型 (一)泛型概述 1.泛型:JDK1.5版本以后出现的新特性,用于解决安全问题,是一个类型安全机制. 2.泛型技术是给编译器使用的技术,用于编译时期,确保类型的安全. 3.泛型的擦除:运行时,会将泛型去掉,生成class文件中的是不带泛型的,这个称为“泛型的擦除”.擦除泛型的原因是为了兼容运行时的类加载器. 4.泛型的好处:(1)将运行时期出现的问题ClassCastException,转移到了编译时期.方便于程序员解决问题,让运行时期问题减少.安全.(2)避免了强制转换的麻烦. 5.泛