Java中的泛型类,泛型方法,泛型接口

来源:互联网 发布:mysql主键有什么用 编辑:程序博客网 时间:2024/06/08 18:20

泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展

1.泛型类,是在实例化类的时候指明泛型的具体类型;支持创建可以按类型进行参数化的类(泛型类:实例化类的时候指明类的类型;public class Test<T>{};Test<Object> t = new Test<Object>();)

2.泛型方法,是在调用方法的时候指明泛型的具体类型。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样(泛型方法:调用的方法持有泛型;public <T>T getObj(Class<T> O){};可以把泛型看做参数/占位符)

3.泛型接口

泛型作用(不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的):
1,(不用检查)类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

2,消除强制类型转换 所有的强制转换都是自动和隐式的。泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。

3,潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。

泛型在使用中还有一些规则和限制:
    1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
    2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
    3、泛型的类型参数可以有多个。
    4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
    5、泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(Java.lang.String);

 泛型是什么意思在这就不多说了,而Java中泛型类的定义也比较简单,例如:public class Test<T>{}。这样就定义了一个泛型类Test,在实例化该类时,必须指明泛型T的具体类型,例如:Test<Object> t = new Test<Object>();,指明泛型T的类型为Object。

       但是Java中的泛型方法就比较复杂了。

       定义泛型方法语法格式如下:



调用泛型方法语法格式如下:



说明一下,定义泛型方法时,必须在返回值前边加一个<T>,来声明这是一个泛型方法,持有一个泛型T,然后才可以用泛型T作为方法的返回值。

       Class<T>的作用就是指明泛型的具体类型,而Class<T>类型的变量c,可以用来创建泛型类的对象。

       为什么要用变量c来创建对象呢?既然是泛型方法,就代表着我们不知道具体的类型是什么,也不知道构造方法如何,因此没有办法去new一个对象,但可以利用变量c的newInstance方法去创建对象,也就是利用反射创建对象。

       泛型方法要求的参数是Class<T>类型,而Class.forName()方法的返回值也是Class<T>,因此可以用Class.forName()作为参数。其中,forName()方法中的参数是何种类型,返回的Class<T>就是何种类型。在本例中,forName()方法中传入的是User类的完整路径,因此返回的是Class<User>类型的对象,因此调用泛型方法时,变量c的类型就是Class<User>,因此泛型方法中的泛型T就被指明为User,因此变量obj的类型为User。

       当然,泛型方法不是仅仅可以有一个参数Class<T>,可以根据需要添加其他参数。

       为什么要使用泛型方法呢?因为泛型类要在实例化的时候就指明类型,如果想换一种类型,不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候指明类型,更加灵活。

 

public ResultDo<JxbkPasswordSetQueryBackPojo> invokePasswordSetQueryApi(JxbkPasswordSetQueryPojo jxbkPasswordSetQueryPojo) {        // 本地校验        ResultDo validDo = this.isAllFieldsValid(jxbkPasswordSetQueryPojo);        if (validDo.isError()) {            return validDo;        }        // 调用接口        Object resultObj = apiInvoke(jxbkPasswordSetQueryPojo, JxbkPasswordSetQueryBackPojo.class);        if (resultObj instanceof ResultDo) {            // 本地异常返回...            return (ResultDo) resultObj;        }        // 联机成功        JxbkPasswordSetQueryBackPojo jxbkPasswordSetQueryBackPojo = (JxbkPasswordSetQueryBackPojo) resultObj;        // 查询成功        ResultDo<JxbkPasswordSetQueryBackPojo> retDo = ResultDo.build();        retDo.setResult(jxbkPasswordSetQueryBackPojo);        return retDo;    }

工作中自己写的代码

private <T> Page<T> getList2Page(List<T> list, Pageable pageable) {        List<T> content = Lists.newArrayList();        int pageNum = pageable.getPageNumber();        int pageSize = pageable.getPageSize();        for (int i = pageNum * pageSize; i < (pageNum + 1) * pageSize; i++) {            if (i < list.size()) {                content.add(list.get(i));            }        }        Page<T> page = new PageImpl<T>(content, pageable, list.size());        return page;    }    private <T> List<T> getFtpList(Class<T> c, String[] result) throws Exception {        if (null == result) {            return new ArrayList<T>();        }        List<T> list = Lists.newArrayList();        for (int i = 0; i < result.length; i++) {            if (result[i].equals("null")) {                continue;            }            String[] resultSon = result[i].split("\\|");            T obj = c.newInstance();            Field[] fields = c.getDeclaredFields();            for (int j = 0; j < fields.length; j++) {                Field field = fields[j];                field.setAccessible(true);                String value = resultSon[j];                //获取 clazz 类型中的 propertyName 的属性描述器                PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(c, field.getName());                Method setMethod = pd.getWriteMethod();//从属性描述器中获取 set 方法                setMethod.invoke(obj, new Object[]{value});//调用 set 方法将传入的value值保存属性中去            }            list.add(obj);        }        return list;    }    private void copyPropertyByCustomAnno(Object target, Object src) {        try {            Field[] srcfields = src.getClass().getDeclaredFields();            for (int i = 0; i < srcfields.length; i++) {                Field field = srcfields[i];                if (field.isAnnotationPresent(ApiFieldAnnotation.class)) {                    field.setAccessible(true);                    String value = (field.get(src) == null || field.get(src).equals("")) ? "空(null)" : field.get(src).toString();//                    DecimalFormat df = new DecimalFormat("###,###.##");//                    if (field.getAnnotation(ApiFieldAnnotation.class).fieldClassType() == BigDecimal.class) {//                        long money = Long.valueOf(value) / 100;//                        value = df.format(money);//                    }                    //获取 clazz 类型中的 propertyName 的属性描述器                    PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(target.getClass(), field.getName());                    Method setMethod = pd.getWriteMethod();//从属性描述器中获取 set 方法                    setMethod.invoke(target, new Object[]{value});//调用 set 方法将传入的value值保存属性中去                }            }            Field[] srcSupfields = src.getClass().getSuperclass().getDeclaredFields();            for (int j = 0; j < srcSupfields.length; j++) {                Field field = srcSupfields[j];                if (field.isAnnotationPresent(ApiFieldAnnotation.class)) {                    field.setAccessible(true);                    String value = field.get(src) == null ? "空(null)" : field.get(src).toString();                    //获取 clazz 类型中的 propertyName 的属性描述器                    PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(target.getClass(), field.getName());                    Method setMethod = pd.getWriteMethod();//从属性描述器中获取 set 方法                    setMethod.invoke(target, new Object[]{value});//调用 set 方法将传入的value值保存属性中去                }            }        } catch (Exception e) {            log.error("获取渤海银行字段失败。", e);        }    }    /**     * 解析银行存管Pojo     */    private List<ReturnPojo> bhbkParseToReturnPojo(Object pojo) {        try {            List<ReturnPojo> params = Lists.newArrayList();            Field[] fields = pojo.getClass().getDeclaredFields();            Field[] fieldsSup = pojo.getClass().getSuperclass().getDeclaredFields();            Field[] fieldsAll = new Field[fields.length + fieldsSup.length];            for (int i = 0; i < fields.length; i++) {                fieldsAll[i] = fields[i];            }            for (int j = fields.length; j < fields.length + fieldsSup.length; j++) {                fieldsAll[j] = fieldsSup[j - fields.length];            }            params.addAll(bhbkParseToReturnPojo(fieldsAll, pojo));            return params;        } catch (Exception e) {            log.error("解析银行存管Pojo失败。", e);            return new ArrayList<ReturnPojo>();        }    }    private List<ReturnPojo> bhbkParseToReturnSonPojo(Object pojo) {        try {            List<ReturnPojo> params = Lists.newArrayList();            Field[] fields = pojo.getClass().getDeclaredFields();            params.addAll(bhbkParseToReturnPojo(fields, pojo));            return params;        } catch (Exception e) {            log.error("解析银行存管Pojo失败。", e);            return new ArrayList<ReturnPojo>();        }    }    private List<ReturnPojo> bhbkParseToReturnPojo(Field[] fields, Object pojo) {        try {            List<ReturnPojo> params = Lists.newArrayList();            for (Field field : fields) {                if (!field.isAnnotationPresent(ApiFieldAnnotation.class)//                    || "sign".equals(field.getName())                        ) {                    continue;                }                ApiFieldAnnotation annotation = field.getAnnotation(ApiFieldAnnotation.class);                field.setAccessible(true);                ReturnPojo returnPojo;                if (field.getAnnotation(ApiFieldAnnotation.class).fieldClassType() == BigDecimal.class) {                    returnPojo = new ReturnPojo(field.getName(), annotation.fieldDesc() + "(元)", annotation.notNull(), field.get(pojo));                } else {                    returnPojo = new ReturnPojo(field.getName(), annotation.fieldDesc(), annotation.notNull(), field.get(pojo));                }                params.add(returnPojo);            }            return params;        } catch (Exception e) {            log.error("解析银行存管Pojo失败。", e);            return new ArrayList<ReturnPojo>();        }    }    @Data    @AllArgsConstructor    private class ReturnPojo {        private String name;        private String nameZh;        private Boolean notNullFlag;        private Object defaultValue;    }
public class BhbkQueryChargeDetailBackPojo extends BhbkBasePojo {    @ApiFieldAnnotation(fieldClassType = String.class, fieldDesc = "大额充值账号", notNull = false, maxLength = 32)    private String chargeAccount;    @ApiFieldAnnotation(fieldClassType = String.class, fieldDesc = "大额充值账户户名", notNull = false, maxLength = 128)    private String accountName;    @ApiFieldAnnotation(fieldClassType = String.class, fieldDesc = "可用余额", notNull = false, maxLength = 16)    private String avlBal;    @ApiFieldAnnotation(fieldClassType = String.class, fieldDesc = "账户余额", notNull = false, maxLength = 16)    private String acctBal;    @ApiFieldAnnotation(fieldClassType = String.class, fieldDesc = "冻结余额", notNull = false, maxLength = 16)    private String frzBal;}


ps:泛型能否代替object?

泛型的作用是为了参数的统一,Object不仅仅是这个功能,它是整个面向对象编程思维的基础,泛型是更好的开发方案!

泛型比object更好,体现在:泛型可以在编译期间检查类型错误,获得ide的上下文提示、无需运行时反射和转换,效率更高、编写的代码语义清晰更容易理解



0 0
原创粉丝点击