泛型的注意事项

注意一:时间复杂度从小到大排列

O( 1 ) < O( log n ) < O( n ) < O( n log n ) < O( n^2 )

注意:

接口与接口之间的关系: extends

接口与类之间的关系: implements

注意二:泛型

泛型:泛型就是将类型进行参数化,将类型作为参数进行传递。

找一个数组可以存放所有数据类型的数据,那么这个数组的类型必然是Object 类型的数组,

  • 因为Object 是所有类的父类,并且它可以接受所有的数据类型包括:类,接口,数组。
  • 引用数据类型大部分都是类或接口,String类等,他们的父类是Object类
  • 基本数据类型,有拆箱和装箱的概念

在这里插入图片描述

public static void main(String[] args) {
        Object[] array = {1,2,3,"hello"};
        String[] array2 = (String[]) array; //现在不报错但是运行的时候报错 
        
    }
//只要是Object类型的数组,就不让强转成其他类型。但是单个类是可以转的。
package demo;

class Arrayer{

    Object[] array = new Object[10];  //数组中每个元素都是Object类型

    public void setArray(int pos, Object value){
        array[pos] = value;
    }

    public Object getArray(int pos){
        return array[pos];
    }
}

public class Test2 {
    public static void main(String[] args) {
       Arrayer arrayer = new Arrayer();
       arrayer.setArray(5,"hello");
       arrayer.setArray(4,20);

       //String str = arrayer.getArray(5); //error
        //getArray()方法返回的是Object 不会自动转化成String类型,要手动强转
        //注意区别这句话  : 只要是Object类型的数组,就不让强转成其他类型。但是单个类是可以转的。
        String str = (String) arrayer.getArray(5);//right
        System.out.println(str);
        System.out.println(arrayer.getArray(1));
    }
}


// hello  null

这样我们会发现一个问题,向Object类型的数组中 传数据是比较方便的,但是取的时候是非常困难的,我们取的时候要找个变量来接收,

但是数组中元素的类型是Object类型,所以每次都要根据接受变量的类型进行强制类型转换,这样做是非常不智能的。低效的。

改进:(使用泛型)

package demo;

class Arrayer2<T>{  // T  类型形参列表 表示的是传递的类型 可以指定多个类型     < > 占位符 表示当前类是泛型类
    
    T[] array = (T[]) new Object[10]; //注意这个地方有问题

    public void setArray(int pos, T value){
        array[pos] = value;
    }

    public T getArray(int pos){
        return array[pos];
    }
}

public class Test3 {
    public static void main(String[] args) {
        Arrayer2<Integer> arrayer = new Arrayer2<Integer>();
        Arrayer2<String> arrayer2 = new Arrayer2<String>();

        arrayer.setArray(0,12);
        arrayer2.setArray(0,"nihao");
        arrayer2.setArray(1,"hhh");

        System.out.println(arrayer.getArray(0));
        System.out.println(arrayer2.getArray(0));
        System.out.println(arrayer2.getArray(1));
    }
}
/*
12
nihao
hhh
*/

我们之前传递的是变量的值,现在我们传递的是变量的类型了。

泛型存在的两个最大的意义:

  • 1:在存放元素的时候会进行类型的检查
  • 2:在取出元素的时候会进行类型的转换,不用自己再强转了。
  • 这两步都是在编译的时候完成的,因为在程序运行的时候,没有泛型这个概念。泛型主要是程序编译时的一种机制 --》擦除机制。

注意:< 里面一定是类类型 ,不可以是基本数据类型 > < int > //error

在这里插入图片描述

在这里插入图片描述

java泛型机制是在编译时期实现的,编译器生成的字节码在运行期间并不包括泛型的类型信息

注意三:Object类型的数组是不可以强转成其他类型的会报错

package demo;

import java.util.Arrays;

class Arrayer2<T>{
    //T[] array1 = new T[10];    error
    T[] array = (T[]) new Object[10];                            //注意这个地方有问题

    public void setArray(int pos, T value){
        array[pos] = value;
    }

    public T getArray(int pos){
        return array[pos];
    }

    public T[] getArray(){
        return array;                                            //注意这是返回一个Object类型的数组
    }
}

public class Test3 {
    public static void main(String[] args) {
        Arrayer2<Integer> arrayer = new Arrayer2<Integer>();
        Arrayer2<String> arrayer2 = new Arrayer2<String>();

        arrayer.setArray(0,12);
        arrayer2.setArray(0,"nihao");
        arrayer2.setArray(1,"hhh");
        
        Integer[] ret = arrayer.getArray();                //Object类型的数组是不可以强转成其他类型的会报错
        
//ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;at demo.Test3.main(Test3.java:31)
    }
}

 //T[] array1 = new T[10];           error
    T[] array = (T[]) new Object[10]; //注意这个地方有问题
//你所实例化的一个数组不是具体类型的
import java.lang.reflect.Array;

public class Test4<T> {
    T[] array;
    public Test4(Class<T> clazz,int capicity){
        array = (T[])Array.newInstance(clazz,capicity);
    }
}

public class Test {
    public static void main(String[] args) {
        Test4<Integer> test4 = new Test4<Integer>(Integer.class ,10);
    }
}

//这样写是正确的,涉及到反射的知识,作为了解

//这样你所实例化的一个数组是具体类型的

注意四:泛型上界

在这里插入图片描述

在这里插入图片描述

你会发现只接受 Number 的子类型作为 E 的类型实参,别的都超出Number的边界了。

package demo1;

public class Alg<T extends Comparable<T>> { //特殊:泛型上界  T类型必须是实现了Comparable接口的
    //寻找数组中的最大值
    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;
    }


}


class Person implements Comparable<Person> {
    private int age;
    private String name;

    public Person(int age, String name){
        this.name = name;
        this.age = age;
    }
    //重写compareT方法 ,你想比较啥就写啥
    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }
   //重写toString方法
    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}


class Test{
    public static void main(String[] args) {

        Integer[] array = {1,2,3,4,5,6};
        Alg<Integer> alg = new Alg<>();
        System.out.println(alg.findMax(array));
        
        
        Person[] person = {
                new Person(10,"xiaobai"),
                new Person(20,"xiaohong"),
                new Person(5,"xiaohuang"),
                new Person(30,"dabai")
        };

        Alg<Person> alg1 = new Alg<Person>();
        Person ret = alg1.findMax(person);
        System.out.println(ret);

    }
}


//6
//Person{age=30, name='dabai'}

注意五:泛型方法

(1):泛型静态方法

package demo2;

public class Alg {
    public static<T extends Comparable<T>> T findmax(T[] array){
        T max = null;
        for(int i = 0; i < array.length - 1; i++){
            if(array[i].compareTo(array[i+1]) < 0){
                max = array[i + 1];
            }
        }
        return max;
    }
}

class Test{
    public static void main(String[] args) {
        Integer[] array = {1,2,3,4,5,6,7,8,9,10};
        Integer ret = Alg.findmax(array);
        //Integer ret = Alg.<Integer>findmax(array);    
        //这两种写法都是可以的,只不过第一种省去的类型参数是通过传参array来判断的.
        System.out.println(ret);
    }
}
// 10

(2):泛型方法:

package demo2;

import java.util.Arrays;

public class Alg2 {
    public <T extends Comparable<T>> void func(T[] array){
        for (int i = 0; i < array.length - 1; i++) {
            if(array[i].compareTo(array[i+1]) < 0){ //会调用相应对象的compareTo方法
                T temp = array[i];
                array[i] = array[i+1];
                array[i+1] = temp;
            }
        }//泛型方法,对任意类型的数组进行排序
    }

}

class Person implements Comparable<Person> {
    private String name;

    public Person(String name){
        this.name = name;
    }

    @Override
    public int compareTo(Person o) {
        return this.name.length() - o.name.length();//重写了compareTo方法,以这个方式进行比较
    }

    @Override
    public String toString() {      //重写了toString方法,Arrays.toString(person)直接调用相应对象当中的toString方法
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}//Person类


class Test1{
    public static void main(String[] args) {
        Person[] person = {
                new Person("xiaohong"),
                new Person("xiaohuang"),
                new Person("xiaohua")
        };
        Alg2 alg2 = new Alg2();
        alg2.func(person);
        System.out.println(Arrays.toString(person));

    }
}

//[Person{name='xiaohuang'}, Person{name='xiaohong'}, Person{name='xiaohua'}]

泛型静态方法不用new对象直接调用。

注意六:通配符

package demo4;

public class Messager<T> {
    private T ret;

    public void setRet(T ret){
        this.ret = ret;
    }
    public T getRet(){
        return  this.ret;
    }
}

class test{
    public static void main(String[] args) {
        Messager<Integer> messager = new Messager<>();
        messager.setRet(10);
        func(messager);
        
        Messager<String> messager2 = new Messager<>();
        messager2.setRet("xiaobai");
        func(messager2);
        
    }
    public static void func(Messager<?> messager){
        //可以接收所有的泛型类型,但是又不能够让用户随意修改。这种情况就需要使用通配符"?"来处理
        System.out.println(messager.getRet());
        //messager.setRet("hhh")   error   不可以往里面放,因为也不知到放什么类型
    }
}
public static void func(Messager<Integer> messager){
        System.out.println(messager.getRet());
}

public static void func(Messager<String> messager){
        System.out.println(messager.getRet());
}
//这两段代码是一样的,擦除完之后如下
public static void func(Messager<Object> messager){
        System.out.println(messager.getRet());
}

public static void func(Messager<Object> messager){
        System.out.println(messager.getRet());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HackerTerry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值