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的上下文提示、无需运行时反射和转换,效率更高、编写的代码语义清晰更容易理解
- java中的 泛型类、泛型方法、泛型接口
- Java中的泛型类,泛型方法,泛型接口
- java 泛型接口 泛型方法
- java泛型关于接口,类,方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型二:泛型类 泛型接口 泛型方法详解
- 【7】Java泛型:泛型类、泛型接口、泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类、泛型接口和泛型方法
- Java泛型:泛型类,泛型接口和泛型方法
- java中的泛型类和泛型方法
- bootstrap select2默认选中后台传过来的值
- Caffe源码解读:dropout_layer的正向传播和反向传播
- 使用RTMPdump(libRTMP)直播来自v4l2的摄像头数据
- mysql-sql-select
- equals,==,hashcode
- Java中的泛型类,泛型方法,泛型接口
- MDK debug时error 57:illegal address (0x08000000)解决办法
- (转载)Twain 学习纪录
- 深度学习基础
- [Language]Python跳转控制--条件与循环
- POJ1222_EXTENDED LIGHTS OUT_高斯消元法
- Python学习笔记(二)——特殊方法
- Ubuntu配置最新版nodejs环境
- Android-签名