包装类, 泛型---java

目录

一. 包装类

1.1 基本数据类型和对应的包装类

1.2 装箱和拆箱

 二. 泛型

2.1什么是泛型

2.2泛型的引入

 2.3 泛型类语法 

 2.4 泛型类的使用

 2.5 裸类型(Raw Type)(了解)

 2.6 泛型是如何编译的 

2.7 泛型的上界

2.8 泛型方法 


一. 包装类

Java 中,由于基本类型不是继承自 Object ,为了在泛型代码中可以支持基本类型, 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 编程思想》对泛型的介绍。
泛型是在 JDK1.5 引入的新的语法,通俗讲,泛型: 就是适用于许多许多类型 。从代码上讲,就是对类型实现了参数化。

2.2泛型的引入

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值.
思路:
1. 我们以前学过的数组,只能存放指定类型的元素,例如: int[] array = new int[10]; String[] strs = new String[10];
2. 所有类的父类,默认为 Object 类。数组是否可以创建为 Object?

代码示例:

问题:
以上代码实现后 发现
1. 任何类型数据都可以存放
2. 1 号下标本身就是字符串,但是确编译报错。getPos返回值是Object, 用String接收, 必须进行强制类型转换
虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。 此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。
那么我们对上述代码进行改写:

 ① MyArray<T>  -----  类名后的 <T> 代表占位符,表示当前类是一个泛型类

了解: 【规范】类型形参一般使用一个大写字母表示,常用的名称有:
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type
S, 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();  

小结:
1. 泛型是将数据类型参数化,进行传递
2. 使用 <T> 表示当前类是一个泛型类。
3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换

 2.6 泛型是如何编译的 

那么,泛型到底是怎么编译的?这个问题,也是曾经的一个面试问题。泛型本质是一个非常难的语法,要理解好他还是需要一定的时间打磨。
通过命令: javap -c 查看字节码文件,所有的 T 都是 Object
在编译的过程当中,将所有的 T替换为Object 这种机制,我们称为: 擦除机制
Java 的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。

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 泛型方法 

语法:

方法限定符 < 类型形参列表 > 返回值类型 方法名称 ( 形参列表 ) { ... }

上述代码可以写成 泛型方法:

当这个泛型方法是静态的时,  我们就不用实例化对象, 直接通过类来调用泛型方法 

  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值