前言
hello,大家好,我是阿旭啊。今天给大家带来数据结构第二篇:包装类&初识泛型。希望能给大家一些小帮助~
一.包装类
在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。
1.基本数据类型和对应的包装类
在类中必然会有属性和方法,这也大大的为我们数据的转换带来了便捷,也让我们的基本数据类型面向对象。除了Integer和Character,其余基本类型都是首字母大写。
2.装箱和拆箱(装包和拆包)
装箱(装包):把基本类型封装成包装类型
public static void main(String[] args) {
int a = 10;
Integer i = a;//自动装箱,此处自动调用valueOf方法
Integer ii = new Integer(a);//显示装箱
Integer iii = Integer.valueOf(a);//显示装箱
}
拆箱(拆包):把包装类型拆成基本类型。
public static void main(String[] args) {
Integer a = 10;
int i = a.intValue();//显示拆箱
float ii = a.floatValue();
double iii = a.doubleValue();
int iiii = a;//自动拆箱
}
【面试题】
下面程序的结果是什么?
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
}
//true
//false
解析:在valueOf底层代码中会发现Integer范围为**-128~127**。如果超出范围则会重新new一个Integer,此时两个超出范围的new就不是同一个变量了。
二.泛型
1.泛型的定义
泛型也是java当中的一种语法!!更为抽象,但是我们的要求也不高,能看懂就行。
通俗讲:泛型就是适用于许多许多的类型。从代码上来说就是类型实现了参数化。
类似于方法传递变量,但是泛型传递的是类型。
2.泛型的语法
代码如下(示例):
class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> { }
class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ {
// 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
// 可以只使用部分类型参数
}
【实战训练】
实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?
class A{
public Object[] objects= new Object[100];
public Object getPos(int pos){
return this.objects[pos];
}
public void setPos(int pos,Object a){
this.objects[pos] = a;
}
}
public class test1 {
public static void main(String[] args) {
A a = new A();
a.setPos(0, 1);
a.setPos(1, "abc");
int b = (int)a.getPos(0);
String c = (String)a.getPos(1);
System.out.println(b);
System.out.println(c);
}
}
//1
//abc
然而我们会发现当我们取出数据的时候需要强制转换,这样的话会比较麻烦,于是我么使用泛型类来答题。
class A <T>{//<T>表示占位符号
public T[] objects= (T[])new Object[100];
public T getPos(int pos){
return this.objects[pos];
}
public void setPos(int pos,T a){
this.objects[pos] = a;
}
}
public class test1 {
public static void main(String[] args) {
A<Integer> a1 = new A<>();
a1.setPos(0, 1);
a1.setPos(1, 10);
int b = a1.getPos(0);
int c = a1.getPos(1);
System.out.println(b);
System.out.println(c);
System.out.println("================");
A<String> a2 = new A<>();
a2.setPos(0, "abc");
a2.setPos(1,"bcd");
String d = a2.getPos(0);
String e = a2.getPos(1);
System.out.println(d);
System.out.println(e);
}
}
//1
//10
//================
//abc
//bcd
此时我们便使用同一个类定义了两个不同的不同类型的数组。与上面代码相比较,我们不用强制转换。
注意:
表示占位符,表示当前为一个泛型类,常用的有:
E 表示 Element K 表示 Key
V 表示 Value N 表示 Number
T 表示 Type
S, U, V 等等 - 第二、第三、第四个类型
3.泛型的意义
在编译的时候,帮我们进行类型的检查。
在编译的时候,帮我们进行类型的转换。
(运行的时候是没有泛型的概念的!!! )
4.泛型的编译
擦除机制:在编译过程中,把所有的T全部替换成Object的机制 。
5.泛型的上界
在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
语法:
class 泛型类名称<类型形参 extends 类型边界> { ...
}
注意:类型形参必须是类型边界的子类。
【实战训练】
class B<T extends Comparable<T>>{
public T findMax(T[] arr){
T max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (max.compareTo(arr[i]) < 0){
max = arr[i];
}
}
return max;
}
}
public class 使用泛型求最大值 {
public static void main(String[] args) {
B<Integer> b = new B();
Integer[] arr = {0, 1, 2 , 5 , 10};
Integer max = b.findMax(arr);
System.out.println(max);
System.out.println("===============");
B<String> c = new B<>();
String[] arr1 = {"asd", "asb", "cgs"};
String max1 = c.findMax(arr1);
System.out.println(max1);
}
}
下面是不使用泛型类,而是使用泛型静态方法来实现:
class B1{
public static <T extends Comparable<T>>T findMax(T[] arr){
T max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (max.compareTo(arr[i]) < 0){
max = arr[i];
}
}
return max;
}
}
public class 使用泛型求最大值 {
public static void main(String[] args) {
Integer[] a = {0, 12, 45, 450};
Integer max = B1.findMax(a);
System.out.println(max);
}
}
总结
okok,本篇文章就到此结束啦。这前两篇博客是学习数据结构的前置基础知识,从下一篇开始我们就正式开始我们数据结构的学习,希望大家能够多多点赞,多多评论,多多批评,大家下一篇再见~~~~