包装类, 泛型---java
目录
一. 包装类
1.1 基本数据类型和对应的包装类
包装类在之前我们就使用过, 使我们写代码更加的方便?
1.2 装箱和拆箱
装箱(装包): 把一个基本数据类型转变为包装类型
拆箱(拆包): 把一个包装类型转变为基本数据类型
int i = 10 ;Integer ii = i ; // 自动装箱Integer ii = Integer . valueOf ( i ); //显示装箱 ---类名.valueOf 说明该方法时用static修饰的Integer jj = new Integer(10) ;int j = jj ; // 自动拆箱int j = jj . intValue (); //显示拆箱
注:拆箱时, 我们可以将数据拆成我们想要的类型?
Integer jj = new Integer(10);
double d = jj.doubleValue();//拆成double类型
System.out.println(d);
//输出结果
10.0
?下面看一道面试题:
思考 : 为什么上述代码只是将100改成200, 输出的结果却不同呢?? ?
上述我们唯一做的动作就是装箱, 那么装箱时, 调用的方法是Integer.valueOf(), 按住Ctrl点进去查看valueOf的源码, 我们发现:
?我们传入的参数, 如果在一个low和high之间, 那么就返回一个数组某下标的值, 如果不在这个范围内, 那么就new一个对象, 此时即使传入一样的参数, 返回的值肯定是不同的.? 那么我们猜测, 200就不在low和high之间, 而100在low和high之间.?
那么我们点进去low和high的源码, 发现low = -128 , high = 127, 我们的猜测是正确的, 那么cache数组是怎么回事呢?
我们计算一下这个数组:
?二. 泛型
2.1什么是泛型
一般的类和方法,只能使用具体的类型 : 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。----- 来源《 Java 编程思想》对泛型的介绍。
2.2泛型的引入
代码示例:
?①?MyArray<T>? -----??类名后的 <T> 代表占位符,表示当前类是一个泛型类
了解: 【规范】类型形参一般使用一个大写字母表示,常用的名称有:E 表示 ElementK 表示 KeyV 表示 ValueN 表示 NumberT 表示 TypeS, U, V 等等 - 第二、第三、第四个类型
②T[] array = (T[])new Object[10] ----??创建泛型类数组
T[] array = (T[])new Object[10], 并不是一个最好的写法, 最好的写法是:
Object[] array = new Object[10];
不能new泛型类型的数组?T [] ts = new T [ 5 ]; // 是不对的
③ MyArray<Integer> myArray = new MyArray<>()? -----? ?创建泛型类对象,?类型后加入 <Integer> 指定当前类型?后面的<>中的内容可以省略
④??myArray.setVal(2,"bit")? -----? ?代码编译报错,此时因为在③处指定类当前的类型,此时编译器会在存放元素的时候帮助我们进行类型检查。
泛型, 是编译时期的机制, 在运行时, 没有泛型的概念
注:<>中的内容不能是基本数据类型, 只能是引用类型/包装类
想要存放String类型的数据:
?2.3 泛型类语法?
class 泛型类名称 < 类型形参列表 > {????????// 这里可以使用类型参数}class ClassName < T1 , T2 , ..., Tn > {}class 泛型类名称 < 类型形参列表 > extends 继承类 /* 这里可以使用类型参数 */ {????????// 这里可以使用类型参数}class ClassName < T1 , T2 , ..., Tn > extends ParentClass < T1 > {????????// 可以只使用部分类型参数}
?2.4 泛型类的使用
泛型类 < 类型实参 > 变量名 ; // 定义一个泛型类引用new 泛型类 < 类型实参 > ( 构造方法实参 ); // 实例化一个泛型类对象MyArray < Integer > list = new MyArray < Integer > ();//当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写MyArray < Integer > list = new MyArray <> (); // 可以推导出实例化需要的类型实参为 Integer
?2.5?裸类型(Raw Type)(了解)
裸类型是一个泛型类但没有带着类型实参,例如 MyArrayList 就是一个裸类型
MyArray list = new MyArray(); ?
?2.6 泛型是如何编译的?
2.7 泛型的上界
?在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
语法:
class 泛型类名称 < 类型形参 extends 类型边界 > {...}
例:
public class MyArray < E extends Number > {...}
表示: 只接受 Number 或 Number的子类型 作为 E 的类型实参?
MyArray < Integer > l1 ; // 正常,因为 Integer 是 Number 的子类型MyArray < String > l2 ; // 编译错误,因为 String 不是 Number 的子类型
了解:
1.? 没有指定类型边界 E,可以视为 E extends Object ?
2. 泛型没有下界
例: 写一个泛型类, 求一个数组中的最大值
?显然这样是错误的, 因为擦除机制将T替换成Object类, 而引用类型是不能直接比较大小的, 需要使用compareTo方法, 并实现Comparable接口,? 我们点进去Object的源码看发现:?
Object类并没有实现Comparable接口?
正确的写法应该是:
意味着, 传入的参数必须是继承了Comparable接口的类, 那么Integer我们点进去查看:
?Integer是继承了Comparable接口的.?
如果我们重新定义一个类当参数:
是不被允许的, 因为没有Person没有实现Comparable接口
正确写法:
2.8 泛型方法?
语法:
方法限定符 < 类型形参列表 > 返回值类型 方法名称 ( 形参列表 ) { ... }
上述代码可以写成 泛型方法:
?
当这个泛型方法是静态的时,??我们就不用实例化对象, 直接通过类来调用泛型方法?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!