大O符号(Big O notation):是用于描述函数渐进行为的数学符号
推导大O阶方法
效果:去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数
结果形式:
概念:对一个算法在运行过程中临时占用存储空间大小的量度,在实际上算的是变量的个数
计算方式:求出变量的个数后,用大O渐进表示法表示
在Java中,由于基本数据类型不是继承与Object的,为了在泛型代码中可以支持基本类型,Java中每一个基本数据类型都有一个对应的包装类
对于基本类型来说,包装类中的属性和方法,可以让数据的转换等使用方法更加方便
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
除了 Integer 和 Character ,其余基本类型的包装类都是首字母大写
public static void main1(String[] args) {
int a = 10;
int b = 20;
//自动装箱
Integer i = a;//与Integer i = Integer.valueOf(a);是一样的,JVM会帮着调用一个valueOf方法
Integer iiii = (Integer) b;
显示装箱
int c = 30;
int d = 40;
Integer iii = Integer.valueOf(c);//使用类调用的,说明是被static修饰的
Integer ii = new Integer(d);
}
❤️Integer.valueOf方法介绍
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
public static void main2(String[] args) {
Integer a = 10;
//自动拆箱
int ii = a;
int iii = (int)a;
//显示拆箱
int i = a.intValue(); //用对象调用,说明这是一个类中的方法
float f = a.floatValue();
}
<>里面一定是个引用类型
语法(1)------------>定义一个泛型类
class 泛型类名称<类型形参列表>{
//这里可以使用类型参数
}
语法(2)------------>定义一个继承某个类的泛型类
class 泛型类名称<类型形参列表> extends 继承类(这里可以使用类型参数){
//可以只使用部分类型参数
}
语法(3)------------>定义一个泛型类引用
泛型类<类型实参>变量名;
语法(4)------------>实例化一个泛型类对象
new 泛型类<类型实参>(构造方法实参);
语法(5)------------>裸类型
概念:是一个泛型类但是没有带着类型实参,意味着什么都能放,那取出来还要强转
注意:不要主动去使用裸类型,因为这是为了兼容老版本保留的机制
class MyArray4<T>{ //定义一个泛型类,T这边的效果就是传什么就是什么,T表示的是这是一个占位符,表示当前类是一个泛型类
public Object[] objects = new Object[10]; //最好的写法
//public T[] objects2 = new T[5]; 错误,数组在new的时候,后面一定要跟一个具体的类型
public T[] objects3 = (T[])new Object[5]; //这种可以,但是不好
public Object getPos(int pos){
return objects3[pos];
}
}
public class Test {
public static void main(String[] args) {
MyArray<Integer> myArray = new MyArray<>(); //语法3+语法4,Integer表示指定传的是int类型的
MyArray<Integer> myArray1 = new MyArray<Integer>(); //裸类型
//效果和上一行是一样的,实例化对象那边的<>中的包装类型是可以省略的,因为可以根据上下文推导出实例化所需要的类型实参
//数组在new的时候,后面一定要跟一个具体的类型,因为T这种占位符在运行的时候是不知道是什么的
//T[] ts = new T[5];
}
}
class MyArray1<T>{
public Object[] objects = new Object[10];
public T getPos(int pos){
return (T)objects[pos];
}
public void setPos(int pos, T val){
objects[pos] = val;
}
}
public class Test{
public static void main(String[] args){
MyArray1<Integer> myArray1 = new MyArray1<>();
myArray1.setPos(0, 20);
System.out.println(myArray1.getPos(0));
MyArray1<String> myArray2 = new MyArray1<>();
myArray2.setPos(0, "aaa");
System.out.println(myArray2.getPos(0));
}
}
泛型的编译中需要遵循一个擦除机制
擦除机制就是在编译的过程当中把所有的T替换成Object这种机制,所以在运行的时候是没有T的,即没有泛型的概念
❤️为什么不能实例化泛型数组
错误示例
class MyArray<T>{
public T[]array = (T[])new Object[10];
public T getPos(int pos){
return this.array[pos];
}
public void setVal(int pos, T val){
this.arrar[pos] = val;
}
public T[] getArray(){
return array;
}
}
public class Main{
public static void main(String[]args){
MyArrar<Integer> myArray1 = new MyArray<Integer>();
Integer[] intgers = myArray1.getArray(); //不知道该用什么接收
}
}
会报错,返回的Object数组里面,可能存放的是任何的数据类型,运行的时间直接传给Integer等类型的数组,会被编译器认为不安全
那怕是强转都不行,因为Object类型表示这里面什么类型都可以放,即可能有char、String等类型,全部都转为Integer会不安全
正确解法
class MyArray1<T>{
public Object[] objects = new Object[10];
public T getPos(int pos){
return (T)objects[pos];
}
public void setPos(int pos, T val){
objects[pos] = val;
}
public Object[] getArray(){
return objects;
}
}
public class Test{
public static void main(String[] args){
MyArray1<Integer> myArray1 = new MyArray1<>();
myArray1.setPos(0, 20);
System.out.println(myArray1.getPos(0));
MyArray1<String> myArray2 = new MyArray1<>();
myArray2.setPos(0, "aaa");
System.out.println(myArray2.getPos(0));
}
}
概念:在定义泛型类时,对传入的类型变量通过类型边界作一定的约束
语法:
class 泛型类名称<类型形参 extends 类型边界>{
}
示例
class MyArray< E extends Number>{
}
E要么是Number的子类,要么就是Number
代码示例 ------------------> 写一个泛型类,求数组中的最大值
<>里面的一定是个引用类型,而引用类型是不可以通过大于和小于进行比较的,因为T在编译的时候会变成Object类,Object类是所有类的父类,本身并没有关联Comparable接口,所以这个泛型类要关联Comparable接口
class Alg<T extends Comparable<T>>{ //擦除为一个实现了这个接口的类型
public T findMax(T[] array) {
T max = array[0];
for (int i = 1; i < array.length; i++) {
//引用类型不可以通过 大于和小于进行比较
if(max.compareTo(array[i]) < 0 ) {
max = array[i];
}
}
return max;
}
}
public class Test{
public static void main(String[] args){
Alg<Integer> alg = new Alg<>();
Integer[] array = {1, 5, 2, 7, 19, 4};
Integer max = alg.<Integer>findMax(array); //可以通过array类判断传的是什么类型的数据
System.out.println(max);
}
}
//这是用静态泛型方法去写
class Alg2 {
public static<T extends Comparable<T>> T findMax(T[] array) {
T max = array[0];
for (int i = 1; i < array.length; i++) {
if(max.compareTo(array[i]) < 0 ) {
max = array[i];
}
}
return max;
}
}
public class Test2 {
public static void main(String[] args) {
Integer[] array = {1,5,2,7,19,4};
Integer max = Alg2.<Integer>findMax(array);//可以通过array类判断传的是什么类型的数据
System.out.println(max);
}
}
泛型方法
语法:
方法限定符<类型形参列表> 返回值类型 方法名称(形参列表){
}