类型、基础数据类型(内置数据类型):byte int short long float double boolean char 、
引用类型:所有的类(引用类型)都是直接间接继承Object类。
java是希望把所有的类型统一达成Object体系
包装类:标准库中创建了一组类,把内置类型的变量,包一下。
1.1:基本数据类型和对应的包装类
除了 Integer 和 Character, 其余基本类型的包装类都是⾸字⺟⼤写。
1.2:装箱和拆箱
虽然包装类,确实是类,在使用的时候,进行算术运算,还是需要转成内置类型,在进行运算。
包装类和内置类型转换。
内置类型-》包装类:装箱
包装类-》内置类型:拆箱
java复制代码
int i = 10;
// 装箱操作,新建⼀个 Integer 类型对象,将 i 的值放⼊对象的某个属性中
Integer ii = Integer.valueOf(i);
Integer ij = new Integer(i);
// 拆箱操作,将 Integer 对象中的值取出,放到⼀个基本数据类型中
int j = ii.intValue();
这个我们了解一下就可以了,现在的从ava8开始,已经可以自动拆箱装箱了。
1.3:自动拆箱和装箱
java复制代码
public class Test {
public static void main(String[] args) {
//内置类型,赋值给包装类
// Integer i = 10;
//包装类,赋值给内置类型、自动拆箱
// int n=i;
Integer i = 10;
Integer j = 20;
System.out.println(i+j);//这里的+就是针对两个Integer先转int在计算
对于包装类来说,拿过来直接用进行了,当内置类型来用。
但有的地方需要使用包装类,不能使用内置类型。
java复制代码
面试题:
下列代码输出什么,为什么?
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
//true
//false
package object.package1;
class MyArrayTemplate<T> {
//此时arr是T[]类型 T是啥类型? 还不知道,得在后面实例化的时候才知道
//由于T类型位置,不能直接new T[]
private T[] arr=(T[]) new Object[10];
public T get (int index){
return arr[index];
}
public void set (int index, T value){
arr[index]=value;
}
}
public class Test3 {
public static void main(String[] args) {
//针对MyArrayTemplate的进行实例化
//泛型参数类型T是Integer
//针对arr来说,就只能存储Integer类型
MyArrayTemplate<Integer> myArray = new MyArrayTemplate<Integer>();
myArray.set(0, 10);
System.out.println(myArray.get(0));
//针对MyArrayTemplate的进行实例化
//泛型参数类型T是String
MyArrayTemplate<String> myArray2 = new MyArrayTemplate<String>();
myArray2.set(0, "hello");
System.out.println(myArray2.get(0));
}
}
//10
//hello
针对泛型参数来说,只能指定引用类型,不能指定内置类型(int 就不可以。)
泛型这一套语法体系,底层还是靠Object这一些列的继承来完成的。
了解: 【规范】类型形参⼀般使⽤⼀个⼤写字⺟表⽰,常⽤的名称有:
E 表⽰ Element
K 表⽰ Key
V 表⽰ Value
N 表⽰ Number
T 表⽰ Type
S, U, V 等等 - 第⼆、第三、第四个类型
java复制代码
也可以省略实例化的一部分:(类型推导)
MyArrayTemplate<Integer> myArray = new MyArrayTemplate<Integer>();
转换为:
MyArrayTemplate<Integer> myArray = new MyArrayTemplate<>();
五:裸类型
5.1: 说明
裸类型是⼀个泛型类但没有带着类型实参,例如 MyArrayList 就是⼀个裸类型
MyArray list = new MyArray();
只是警告但不报错,
注意: 我们不要⾃⼰去使⽤裸类型,裸类型是为了兼容⽼版本的 API 保留的机制
下⾯的类型擦除部分,我们也会讲到编译器是如何使⽤裸类型的。
⼩结:
泛型是将数据类型参数化,进⾏传递
使⽤ <T> 表⽰当前类是⼀个泛型类。
泛型⽬前为⽌的优点:数据类型参数化,编译时⾃动进⾏类型检查和转换
六:泛型如何编译的
6.1 :擦除机制
那么,泛型到底是怎么编译的?
基本概念:
在编译时,Java 编译器会将泛型类型信息从代码中移除,这个过程就叫做类型擦除。
擦除后,泛型类型会被替换为其边界类型(通常是 Object)或者指定的类型。
擦除过程:
将泛型参数替换为其边界或 Object。
在必要的地⽅插⼊类型转换以保持类型安全。
⽣成桥接⽅法以保持多态性。
七 :泛型的上界
针对某个类泛型参数,能填啥,做出限制。
上界:约定了泛型参数的父类,然后有一个界限。
例如:泛型参数只能填数字不能填字符串
或者泛型参数只能填Animal,就是有限制。
7.1:语法
java复制代码
class 泛型类名称<类型形参 extends 类型边界> {
...
}
7.2:实例
java复制代码
public class Test4 <T extends Number> {
}
继承Number父类,它的子类只能是数字
Test4<Integer> l1; // 正常,因为 Integer 是 Number 的⼦类型
Test4<String> l2;//// 编译错误,因为 String 不是 Number 的⼦类型
这样就不可以使用,
eg:
public class Test4 <T extends Number> {
public static void main(String[] args) {
Test4<Integer> t1 = new Test4<Integer>();
Test4<Double> t2 = new Test4<Double>();
Test4<Float> t3 = new Test4<Float>();
Test4<Long> t4 = new Test4<Long>();
Test4<Short> t5 = new Test4<Short>();
Test4<Byte> t6 = new Test4<Byte>();
Test4<String> t7 = new Test4<String>();//String表示Number子类
也就是继承,然后类型匹配,不能匹配就不执行。
八:通配符(统统匹配)
java复制代码
public class Test5 <T>{
public static void main(String[] args) {
Test5<Integer> t1 = new Test5<Integer>();
//报红就不能实例化,因为泛型参数不匹配
t1= new Test5<String>();
//这个情况就是不挑食,无论泛型参数是什么,都可以通过t来实例化
//此处?就是通配符
Test5<?> t= new Test5<Integer>();
t= new Test5<String>();
在"?"的基础上⼜产⽣了两个⼦通配符:
? extends 类:设置通配符上限:
java复制代码
//指定了通配符的上界
//此时t1可以实例化Integer,String,Double等所有Number的子类
Test5<? extends Number> t1= new Test5<Integer>();
//错误写法,String类型不是Number的子类,所以编译报错
t1 = new Test5<String>();