java泛型——从源头杜绝类型转换异常—基本使用姿势浅析
来源:互联网 发布:ipad比下软件 编辑:程序博客网 时间:2024/05/18 11:25
java泛型——从源头杜绝类型转换异常—基本使用姿势浅析
前言
泛型利用类型参数让代码具有更好的可读性,并且在编译期就对类型进行规范约束,从而从源头解决类型问题
Ps:Java从1.5之后支持泛型
List<String> sList=new ArrayList<>();//最常见的例子 sList.add("str"); sList.add(1); //编译错误
实现原理
类型擦除
//简单的验证下类型擦除ArrayList<String> aString=new ArrayList<String>(); ArrayList<Integer> aInteger=new ArrayList<Integer>(); System.out.println(aString.getClass()==aInteger.getClass()); //发现结果为true。
在编译期间,所有的泛型信息都会被擦除,List和List类型,在编译后都会变成List类型(原始类型)。Java中的泛型基本上都是在编译器这个层次来实现的,这也是Java的泛型被称为“伪泛型”的原因。
那 什么是“原始类型”呢?
原始类型就是泛型类型擦除了泛型信息后,在字节码中真正的类型。无论何时定义一个泛型类型,相应的原始类型都会被自动提供。原始类型的名字就是删去类型参数后的泛型类型的类名。擦除类型变量,并替换为*限定类型(T为无限定的*类型变量,用Object替换)。
//泛型类型 ,泛型为超类Objectclass Bean<T> {private T value; }//原始类型 class Bean {private Object value; }
//泛型类型 , 泛型为数值类型,支持byte,double,float,int,long,shortclass Bean<T extends Number> {private T value; }//原始类型 class Bean {private Number value; }
数值类型,点击查看官方解释
泛型使用注意事项
1.不可以在静态变量,静态方法中直接使用
public class Test<T> { public static T key; //编译错误,静态存在的时候对象还没有实例化,不知道泛型是什么 public static T show(T one){ //编译错误 return null; } public static <T>T show(T one){//这是正确的,此处使用的泛型T是方法自身的T return null; } }
2.泛型不能是基本数据类型
比如:没有List,只有List。因为当类型擦除后,List的原始类中的类型变量(T)替换为Object,但Object类型不能存储double值。
基本数据类型:int、short、float、double、long、boolean、byte、char
对应包装类:Integer、Short、Float、Double、Long、Boolean、Byte、Character
String 是引用数据类型
3.泛型类型引用传递
ArrayList<String> aList1=new ArrayList<Object>();//编译错误,要求一致不支持转型,违背设计原则ArrayList<Object> aList1=new ArrayList<String>();//编译错误
其实这个问题基本不会存在,因为(在java6以上)后面可以直接使用new ArrayList<>(),IDE会直接默认写好
List<String> rawList = new ArrayList();Java 5的javac编译器会产生类型未检查的警告 注意: test.java使用了未检查或称为不安全的操作;这种警告可以使用@SuppressWarnings("unchecked")注解来屏蔽。
4.运行时类型查询
ArrayList<String> arrayList=new ArrayList<>();if( arrayList instanceof ArrayList<String>) //运行报错 //因为类型擦除之后,ArrayList<String>只剩下原始类型,泛型信息String不存在了。 //解决方案if( arrayList instanceof ArrayList<?>)//正确,?为通配符,也即非限定符。
5.限定通配符和非限定通配符
List<? extends T>可以接受任何继承自T的类型的ListList<? super T>可以接受任何T的父类构成的List //例子 List<? extends Number>可以接受List<Integer>或List<Float>//Byte,Double,Long,Short 几种数值类型
泛型使用场景
1.集合框架/数组
ArrayList<Object> aList1=new ArrayList<>();
// 接收可变参数 返回泛型数组public static <T> T[] fun1(T...arg){ return arg ; }//调用方法Integer i[] = fun1(1,2,3,4,5,6)
2.泛型类 ——对象的引用传递
//进行引用传递的时候泛型必须匹配才可以传递,否则无法传递。class Info<T>{ private T var ; // 定义泛型变量 public void setVar(T var){ this.var = var ; } }
3.泛型接口
泛型接口很类似泛型类:访问权限 +interface +接口名称 + <泛型标示>{}
// 泛型接口 定义抽象方法,抽象方法的返回值就是泛型类型interface Info<T> { public T getVar(); }//实现类__方式1 getter/setter方法略class InfoImpl implements Info<String> { private String mVar; public InfoImpl(String var) {this.mVar=var;}}//实现类__方式2 getter/setter方法略class InfoImpl2<T> implements Info<T> { private T mVar; public InfoImpl2(T var) {this.mVar=var; }}//测试类public class Test { public static void main(String arsg[]) { Info i = new InfoImpl("hello world"); // 通过子类实例化对象 System.out.println("方式一内容:" + i.getVar()); Info<String> j = new InfoImpl<String>("soyoungboy"); System.out.println("方式二内容:" + j.getVar()); }}
4.泛型方法(可用在2,3 中也可用在其他位置)
//来个简单案例。泛型方法(对象设置特定属性) public static <T extends Number> T setValue(T x){ return x; }
//T, E or K,V等被广泛认可的类型占位符public V put(K key, V value) { return cache.put(key, value); }
5.泛型嵌套 —— 泛型类的深入使用
//一个普通的泛型类,接收两个泛型变量,省略setter方法class Info<T, V> { private T var; private V value; public Info(T var, V value) { this.var =var; this.value =value; } public T getVar() {return var;} public V getValue() { return value;}}//一个嵌套了泛型类的泛型类user, 可能存在一个mannager类也嵌套info泛型类class User<S> { public S info; public User(S info) {this.info=info;} public S getInfo() {return info;}}//测试类public class test { public static void main(String args[]) { User<Info<String, Integer>> d = null; Info<String, Integer> i = null; i = new Info<String, Integer>("feisher", 29); d = new User<Info<String, Integer>>(i); System.out.println("姓名:" + d.getInfo().getVar()); System.out.println("年龄:" + d.getInfo().getValue()); }}
阅读全文
1 0
- java泛型——从源头杜绝类型转换异常—基本使用姿势浅析
- java反射1——反射源头
- 从源头掌控质量——北京源品汇科技有限公司
- 给linux添加系统调用——从源头说起
- 异常详细信息: System.InvalidCastException: 对象不能从 DBNull 转换为其他类型——的解决方法
- Java复习笔记(四)——Java基本类型的类型转换
- java基本类型转换
- JAVA基本类型转换
- java基本类型转换
- Java 基本类型转换
- java基本类型转换
- java基础讲义(2)——基本类型的类型转换
- Java学习记录(4)——基本类型的类型转换
- Java基本类型与类型转换(2)——位操作: byte & 0xff
- C/C++ — 浅析C++的强制类型转换
- 小白Java笔记——基本类型的类型转换和表达式类型的自动提升
- JAVA初入门——基本类型,类,构造函数,异常处理,IO,集合问题归纳
- Hibernate调试——定位查询源头
- IIS崩溃(死循环)
- 常用Linux命令、文件操作解压缩相关、Linux命令大全、测试查询
- Location Privacy readings
- ECMAscript6快速入门-Class
- 连接到 Azure (Resource Manager) 上的 SQL Server 虚拟机
- java泛型——从源头杜绝类型转换异常—基本使用姿势浅析
- java.lang.VerifyError: Expecting a stackmap frame at branch target 16 类似java异常
- docker 代理设置
- pip不能安装Tensorflow问题
- Linux下tomcat开机自动启动
- mongodb之副本集搭建
- 强化学习用于发掘GAN在NLP领域的潜力
- 阿里云专家为你解读安全管家服务
- 话说Svn与Git的区别