泛型

泛型又名参数化类型,是JDK5出现的新特性

 

★★★为什么需要泛型★★★

 

①可以对加入到集合的数据类型进行约束,以防加入的数据类型不合理

 

②遍历集合需要进行类型转换,当集合非常多元素时,这就会效率很慢,而如果使用泛型,由于泛型要求集合装的都是同样类型的元素,在进行增强for循环时,就直接把辅助对象定义为对应类型,而不需要是Object类,也就是说不用进行类型转换,提高了效率。

 

③用泛型可以保证,如果在编译时没有发出警告,那么运行时不会出现ClassCastExpection异常,而且代码也能更简洁,更健壮

 

 

 

★★★泛型语法★★★

 

泛型语法上作用是:可以在类声明的时候用一个标识符来表示一种数据类型,到底是哪种数据类型要在创建对象的时候才能确认,上一个例子看看

 

public class Test {
    public static void main(String[] args) {
       new A<String>("卡梅隆安东尼");
//可以指定

       new A("卡梅隆安东尼");
//也可以不指定,编译器会根据你赋予的值的类型来确定T,这里就会是String

        new A<String>(1);
//报错,因为指定只能放String

    
        new A();
 //无参构造器,泛型默认是Object

    }
}

class A<T>{
    //T在创建对象的时候确定,
    // 即在编译期间会确定这个T代表什么数据类型
    T a;

    public A(T a) {
        this.a = a;
        System.out.println(a.getClass());
    }

    public T a(T a){
        return a;
    }

    public A(){};
    
}    

 

 

 

①<>里面只能放引用类型,不能放基本数据类型,不过也只是确定的时候不能指定基本数据类型,如果是作为形参传递,会自动装箱成包装类

 

 

 第一条虽然传的整形参数会被自动装箱成包装类Integer

 

 

②一些特殊的写法

<?>:支持任意泛型类型

 

<?  extends  A>:支持A类以及A的子类,规定了泛型的上限

 

<?  super  A>:支持A类及A的父类,不限于直接父类,规定了泛型的下限

 

 

 

 

 

自定义泛型

 

语法:

class /interface   类名/接口名    <T,E,......>{

   成员

}

 

①这种含有自定义泛型的类或者接口,叫做自定义泛型类或者自定义泛型接口,类和接口(接口没有普通属性)的普通成员可以使用泛型(属性,方法),静态方法和静态属性中不能使用类的泛型,因为如果是用了类名来访问静态成员,你没办法去指定泛型是哪种类型

 

②使用泛型的数组,不能初始化,因为T还没确定

 

③泛型类的类型,是在创建对象的时候确定的,如果创建对象时没有指定类型,默认Object

 自定义泛型接口的泛型,在继承接口或者实现接口的时候确定,如果没有指定,默认Object

 

 

④指定了类型后的泛型类,不具有继承性(不是指泛型属性和泛型参数),除非用上面的特殊写法

 

public class Test {
    public static void main(String[] args) {
        Object o = new String();

        //这里可以把A<Object>当成一个新类型,A<Integer>也看成是一个新类型
        //并且这两个新类型<>里面没写继承关系,因此是不具备继承关系的,所以向上转型失败
        A<Object> a = new A<Integer>(1);//报错

//因为这里A<>会被编译器推断成A<Object>,所以ok //并且1被自动装箱为Integer,也就是Object的子类 //传进构造器,向上转型成Object A<Object> b = new A<>(1); } } class A<T> { public T c; public A(T c) { this.c = c; System.out.println(c.getClass().getSimpleName()); } }

 

 不具备继承性只是在    “类型<指定的类型>”    这种形式身上才存在的,因为这样相当于新类型,若想有继承关系必须要在<>里面说明,但是泛型属性和泛型参数只是通过泛型来确定自身的类型,没有形成新类型,所以该干嘛还是干嘛

 

 

 

自定义方法

语法:

修饰符   <T,R.....>   返回类型    方法名(形参列表){

}

 

①泛型方法可以定义在普通类中,也可以定义在泛型类中

 

②用了泛型的方法要等被调用时,类型才会被确定

 

public class Test {
    public static void main(String[] args) {
        A a = new A("1");

        a.a(1);
       
    }
}

class A <T>{
    public T c;

    public A(T c) {
        this.c = c;
    }

    
    public  void a(T b){
        System.out.println(b.getClass());
    } 
}

运行结果
class java.lang.Integer

 

可见,即便前边有确定了c的泛型T,也不关a方法的T的事,它们是独立开的,当调用a时才会确定T

 

 

③泛型紧跟其后的才是泛型方法,在参数列表的泛型只是说明方法使用了泛型

 

class A {
  
    //自定义泛型方法,这个泛型专属于这个方法
    public <T>  void a(T b){
        System.out.println(b.getClass());
    }

 //自定义泛型方法,这个泛型专属于这个方法
    public <T>  T a(T b){
        System.out.println(b.getClass());
    }

//方法使用了泛型 

public void b(T b){ System.out.println(b.getClass()); } }

 

④如果是无参泛型方法会怎样?

public class Test {
    public static void main(String[] args) {
        new Test().a();
    }

    public <T>  T a(){
        T b = (T)"1";
        System.out.println(b.getClass());
        return b;
    }
}

运行结果
class java.lang.String

可以看到,这种情况,会根据局部变量的赋值的类型来确定,也就是利用动态绑定来确定T

posted @ 2022-03-24 10:02  codemelo  阅读(52)  评论(0)    收藏  举报