泛型


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

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

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

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

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

★★★泛型语法★★★

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

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

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

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

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

    }
}

class A{
    //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还没确定

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

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

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

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

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

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

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

自定义方法

语法:

修饰符      返回类型    方法名(形参列表){

}

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

②当泛型方法被调用时,类型才会被确定

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

        a.a(1);
       
    }
}

class A {
    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的事,它们是独立开的

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

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

    //方法使用了泛型
    public void b(T b){
        System.out.println(b.getClass());
    }
}