java的泛型

泛型:

  表示数据类型(这种数据类型是引用类型)的一种类型。如int a = 1;变量a为1。类比得 E = String,E表示泛型,他可以表示所有的数据类型,这里这个泛型表示String类型

  1. 泛型又称参数化类型,解决数据类型的安全性问题

  2. 在类声明或实例化时指定好需要的类型即可(即传入实参)

  3. 泛型的作用:可以在类声明时通过一个标识表示类中的某个属性类型,或某个方法的返回值类型,或参数类型

public class Generic{
    public static void main(String[] args){
        //注意:E的具体类型是在编译期间确定的,这里泛型E的类型表示Srting类型
        Person<String> person = new Person<String>("zhangsan");
    }
}

class Person<E>{
    E s; //某个属性类型
    public Person(E s){//参数类型
        this.s = s;
    }
    public E f(){//某个方法的返回值类型
        return s;
    }    
    void show(){
        System.out.println(s.getclass());//这个看E的实际类型(运行类型)
    }
}

泛型的声明:

  class 类名<E,K,M>{}和interface 接口名<T,V>{}

    E,K,M,T,V表示泛型,只能表示引用类型,任意字母都行。一般在一个对象实例化就能指定泛型表示的具体类型了

    在指定泛型的具体类型后,可以传入该类型或该类型的子类型

泛型的使用形式:

  Person<String> person = new Person<String>("zhangsan");

  也可以为:Person<String> person = new Person<>("zhangsan");后面的<>中的类型会自动推导,推荐使用第二种

 

自定义泛型类:

  class 类名<E,K,M>{}

  1. 普通成员(属性、方法)可以用泛型修饰

  2. 使用泛型的数组不能初始化。因为数组在new时,不能确定T的类型,就无法确定要分配多大的空间

  3. 静态方法中不能使用泛型。因为静态方法和类相关,在类加载时,对象还没有创建,所以如果静态方法或静态属性使用了泛型,JVM就无法完成初始化。

  4. 泛型类的类型是在创建对象时确定的。因为创建对象时,需要指定确定类型

  5. 如果在创建对象时,没有指定类型,默认是Object

public class Customgeneric{//其他外部类
    public static void main(String[] args){
        //注意:E的具体类型是在编译期间确定的,这里泛型E的类型表示Srting类型
        Person<String> person = new Person<String>("zhangsan");
        Person person = new Person("zhangsan"); //相当于Person<Object> person = new Person<>("zhangsan");
    }
}

class Person<E>{
    E s; //某个属性类型
    E[] arr;//E[] arr = new E[]; 使用泛型的数组不能初始化
    //static E a;
    //public static E m(E str){} 静态方法中不能使用泛型
    
    public Person(E s){//参数类型
        this.s = s;
    }
    public E f(){//某个方法的返回值类型
        return s;
    }    
    void show(){
        System.out.println(s.getclass());//这个看E的实际类型(运行类型)
    }
}

自定义泛型接口:

  interface 接口名<T,V>{}

  1. 静态成员也不能使用泛型(接口中的属性默认有public static final

  2. 泛型接口的类型,在继承接口(即在extend后面要指定确定的类型)或实现接口(在implement后面指定具体的类型)时确定

  3. 没有指定类型,默认是Object

 

泛型方法:

  访问修饰符 <T,R> 返回值 方法名(参数列表){

  }

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

  2. 当调用泛型方法时,就要确定泛型的类型

  3. 如public void eat(E e){}这种,访问修饰符后没有<T,R>,那么eat就不是个泛型方法,只是使用了泛型

 

public class CustomMethodgeneric{
    public static void main(String[] args){
        Car car = new Car();
        car.fly("保时捷",100);//当调用方法时,传入参数,编译器会确定具体的类型
    }
}

class car{//普通类
    public void run(){//普通方法
        
    }
    //<T,R>是泛型,是提供给fly方法使用的
    public <T,R> void fly(T t,R r){//泛型方法在普通类中
        
    }
}
class fish<T,R>{//泛型类
    public void run(){
        
    }
    public<U, M> void eat(U u,M m){//泛型方法在定义在泛型类中
        
    }
}
class Fish<T,R>{
    public void run(){
        
    }public<U,M> void eat(U u,M m){//泛型方法
        
    }
    //hi不是泛型方法,hi使用了类声明的泛型
    public void hi(T t){
        
    }
    //泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型
    public<K> void hello(R r, K k){
        
    }
}

 泛型和通配符:

  约束泛型的范围

  1. 通配符 <?> :表示支持任意的泛型类型

  2. 通配符 <? extends A>:表示支持A类以及A类的子类,限制泛型的范围在A以下

  3. 通配符 <?super A>:表示支持A类以及A类的父类(不限于直接父类),限制泛型的范围在A以上

posted @ 2023-06-05 14:37  踏浪而来的人  阅读(34)  评论(0编辑  收藏  举报