泛型 订阅
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。 展开全文
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。
信息
适用范围
计算机
类    别
程序设计语言的一种特性
中文名
泛型
外文名
genericity
泛型定义分类
泛型的定义主要有以下两种:1.在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象。(这是当今较常见的定义)2.在程序编码中一些包含参数的类。其参数可以代表类或对象等等。(人们大多把这称作模板)不论使用哪个定义,泛型的参数在真正使用泛型时都必须作出指明。一些强类型编程语言支持泛型,其主要目的是加强类型安全及减少类转换的次数,但一些支持泛型的编程语言只能达到部分目的。
收起全文
精华内容
参与话题
问答
  • 泛型

    2020-11-16 08:47:28
    泛型是指类型参数化。意思是允许在定义类、接口、方法中使用类型形参,当使用时(创建对象时)指定具体类型,所有使用该泛型参数的地方都被统一化,保证类型一致。如果未指定具体类型,默认是Object类型。集合体系中...

    泛型是指类型参数化。意思是允许在定义类、接口、方法中使用类型形参,当使用时(创建对象时)指定具体类型,所有使用该泛型参数的地方都被统一化,保证类型一致。如果未指定具体类型,默认是Object类型。集合体系中的所有类都增加了泛型,泛型也主要用在集合

    泛型:可以在类或方法中预知的使用未知的类型
    用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
    泛型在定义的时候不具体,使用的时候才变得具体。在使用的时候(创建对象时)确定泛型的具体数据类型。
    注:一般在创建对象时,将未知的类型确定具体的类型。当没有指定具体的类型时,默认类型为Object类型。

    泛型的定义
    泛型类:public class Demo {} ,T表示未知类型。
    泛型接口:public interface ImplDemo<T,V>{} ,和定义类一样(接口就是一个特殊类)。
    泛型方法:public void demo1(T name){System.out.println(name);} , public T demo2(T t){ return t;}

    泛型的好处:
    1.编译时确定类型,保证类型安全,避免类型转换异常
    2.避免了强制类型转换
    3.代码利于重用,增加通用性

    泛型的限制和规则
    · 泛型的类型参数只能是引用类型,不能使用值类型。
    · 泛型的类型参数可以有多个。
    · 泛型类不是真正存在的类,不能使用instanceof运算符。
    · 泛型类的类型参数不能用在静态申明。
    · 如果定义了泛型,不指定具体类型,泛型默认指定为Ojbect类型。
    · 泛型使用?作为类型通配符,表示未知类型,可以匹配任何类型。因为是未知,所以无法添加元素。
    · 类型通配符上限:<? extends T>,?代表是T类型本身或者是T的子类型。常用于泛型方法,避免类型转换。
    · 类型通配符下限。<? super T>,?代表T类型本身或者是T的父类型。
    · 除了通配符可以实现限制,类、接口和方法中定义的泛型参数也能限制上限和下限。

    以String类型举例:

    public class Student {
    private T sex;
    public T getSex() {
    return sex;
    }
    public void setSex(T sex) {
    this.sex = sex;
    }
    }

    将泛型作为参数和返回值类型使用:

    public class Test01 {
    public static void main(String[] args) {
    show(3.1);
    System.out.println(getT(“abc”));
    }
    // T 我不知道是什么类型 , 使用泛型做为参数
    public static void show(T t){
    System.out.println(t.getClass());
    }
    public static T getT(T t){
    return t;
    }
    }

    泛型在定义的时候不具体,在使用的时候才变得具体,在使用的时候确定泛型的具体类型。
    使用泛型:即什么时候确定泛型
    在创建对象的时候确定泛型

    含有泛型的方法:
    定义格式:

    修饰符 <代表泛型的变量> 返回值类型 方法名(参数) { }

    展开全文
  • 泛型

    千次阅读 2020-01-06 09:17:48
    一、泛型 1、泛型的优点 保证类型安全,使运行期错误提前到编译器 消除强制类型转换(如果没有泛型,认为是一个Object,在转换时,非常容易出现ClassCastException) 二、泛型定义 1、泛型在类上 实例看...

    一、泛型

    1、泛型的优点

         jdk5加入,保证类型安全,使运行期错误提前到编译器

         消除强制类型转换(如果没有泛型,认为是一个Object,在转换时,非常容易出现ClassCastException)

        代码更灵活,可以复用

    2、泛型的原理

          虚拟机不支持泛型,所以java实现的是一种伪泛型机制,也就是说java在运行生成字节,码编译器擦除了所有的泛型信息,这样java在不需要产生新的类型到字节码,所有的泛型类型最终都是一种原始类型,在java运行时根本不存在泛型信息。

     

    二、泛型定义

    1、泛型在类上

         实例看集合类

    public interface List<E> extends Collection<E> {
        boolean add(E e);
    }

    总结:

    • 在我们new 对象的时候才传入泛型的类型
    • 类的泛型是在运行期确定的,可以作用于整个类中
    • 静态方法不可以访问定义在类上的泛型

    2、泛型在方法上

    (1)泛型定义在成员方法上

    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
          if (a.length < size)
                // Make a new array of a's runtime type, but my contents:
                return (T[]) Arrays.copyOf(elementData, size, a.getClass());
          System.arraycopy(elementData, 0, a, 0, size);
          if (a.length > size)
             a[size] = null;
          return a;
    }

    (2)泛型定义在静态方法上(注意泛型的位置)

    publicc  <T> static void  action(T t){
    
    }

    总结:

    • 泛型定义在方法上,在我们使用这个方法时确定泛型类型,因此作用范围就是这个方法,
    • 静态方法不可以访问类定义的泛型,因为类定义的泛型是初始化对象时确定,静态方法随类,不随类的对象

    3、泛型定义在接口上

    public interface Iterator<E> {
       
        boolean hasNext();
    
        E next();
    }
    

    4、通配符

    (1)非限定通配符?(等价于? extends  Object)(一般用在方法上)

    public static void  print(ArrayList<?>  list){
       Iterator<?> it=list.iterator();
       while(it.hasNext()){
         //it.next();
       }
    }

    (2)限定通配符(?extends  T,? super  T)

    public class GenericBean<T> {
    
        private T data;
    
        public void  setData(T t){
            this.data=t;
        }
        
        public T getData(){
            return data;
        }
    }
    
    //Orange,Apple,Fruit关系
    Orange  extends  Apple  extends  Fruit

       泛型限定有两种:

    • ? extends  E 可以接受E类型或者E的子类型,上限
    • set数据会编译错误,可以安全的获取数据,
    • get数据返回值类型是E本省
    GenericBean<?  extends  Apple>  bean=new GenericBean<>();
    bean.setData(new Apple());        //编译错误
    bean.setData(new Orange());       //编译错误
    bean.setData(new Fruit());        //编译错误
    
    Apple data = bean.getData();
    • ? super E  可以接收E类型或者E的父类型,下限
    • set数据只能是本身和子类(因为子类可以安全转型为本身),不能是超类(超类不能安全转型)
    • get数据返回的是Object
    GenericBean<? super  Apple>  bean=new GenericBean<>();
    bean.setData(new Apple());
    bean.setData(new Orange());
    bean.setData(new Fruit());            //报错

     

    三、 泛型    继承与子类型

    1、

    面试题:可以把List<String>  传递给一个接受List<Object> 参数的方法吗?       不能

                   可以把List<String>  传递给一个接受Collecton<Object>参数的方法吗?    不能             

     

    四、泛型擦除

    1、检查泛型类型,获取目标类型

    2、 擦除类型变量,并替换为限定类型

    •    如果泛型类型的类型变量没有限定,用Object作为原始类型
    •    如果有限定(T  extends  XClass) 则用XClass作为原始类型
    •    如果有多个限定(T  extends  XClass1&XClass2)则使用第一个边界XClass2作为原始类

    3、在必要时插入类型转换以保持类型安全

    4、生成桥方法以在扩展时保持多态性(当编译一个扩展参数化类的类,或一个实现了参数化接口的接口时,编译器有可能因此要创建一个合成方法,名为桥方法)

      说明:

    •   泛型擦除实例:
    List<Integer> list=new ArrayList<>();
    list.add(1);     //字节码运行,实际调用的是List.add(Object e),1先装箱成Integer
    
    Integer x=list.get(0);
    //字节码运行,实际调用的是Object obj=list.get(index);然后把Object强转成Integer,再进行拆箱操作
    Integer y=(Integer)list.get(0);
    int x=y.intValue();
    
    • 生成桥方法实例:
    public  class  Plat<T>{
                                 ---泛型擦除变成--->     void   set(Object  t);
        void set(T t);
    }
    
    
    
    public class AndroidPlat<T extends  Compare>  implement  Plat<T>{
    
    
        void  set(T t);          ------泛型擦除----->     void  set(Compare t);
        因为AndroidPlat实现了Plat接口得复写其方法,
        所以生成桥方法 set(Object t),但是实际调用的是参数为Compare类型的set方法,
        会把Object类型强转成Compare类型                                                      
    } 

    最后在类常量池保存了泛型信息,因此反射时可以正确获取泛型的类型

     

    五、泛型的局限性

    •  泛型不能是基础类型,如果使用只能是基础类型的包装类    

             因为泛型擦除,最后泛型的原始类型是Object,Object不能存放基础类型。

    • 泛型不支持instanceOf关键字
    ArrayList<String> list=new ArrayList<>();
    list instanceOf  ArrayList<String>     报错 

       泛型擦除后类型丢失,是不能判断的。 

    •  泛型获取的class都是原生类型,无论传入的泛型是什么类型
    ArrayList<String> list=new ArrayList<>();
    ArrayList<Boolean> listBollean=new ArrayList<>();
    Log.d("aaaa",""+(list.getClass()==listBollean.getClass()));   //true
    
    •   泛型数组可以 定义,但是不能初始化,会报错,编译不过
    GenericBean<String>[] array=null;
    array=new GenericBean<String>[10];

        如果A  extends  B,那么A[]的父类是B[],这是数组的协变,当泛型擦除后,数组无法协变,因此无法使用泛型数组。

    //数组协变
    Fruit[] fruit=new Fruit[10];
    Apple[] apples=new Apple[10];
    fruit=apples;
    fruit[0]=new Apple();
    fruit[1]=new Orange();   //可以编译,运行错误
    • 泛型类不能派生自Exception/Throwable

     

    展开全文
  • JAVA泛型

    千次阅读 2019-09-19 21:15:47
    JAVA泛型1 概念2 泛型方法( )3 泛型类 4 类型通配符 ?5 类型擦除 1 概念 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定...

    1 概念

    泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。比如我们要写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,我们就可以使用 Java 泛型。

    2 泛型方法( )

    你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

    // 泛型方法 printArray
    public static <E> void printArray(E[] inputArray) {
    	for (E element : inputArray) {
    		System.out.printf("%s ", element);
    	}
    }
    
    1. <? extends T>表示该通配符所代表的类型是 T 类型的子类。
    2. <? super T>表示该通配符所代表的类型是 T 类型的父类。

    3 泛型类

    泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。

    public class Box<T> {
    	private T t;
    	public void add(T t) {
    		this.t = t;
    	}
    	public T get() {
    		return t;
    	}
    }
    

    4 类型通配符 ?

    类 型 通 配 符 一 般 是 使 用 ? 代 替 具 体 的 类 型 参 数 。 例 如 List<?> 在 逻 辑 上 是 List,List 等所有 List<具体类型实参>的父类。

    5 类型擦除

    Java 中的泛型基本上都是在编译器这个层次来实现的。在生成的 Java 字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个过程就称为类型擦除。如在代码中定义的 List和 List等类型,在编译之后都会变成 List。JVM 看到的只是 List,而由泛型附加的类型信息对 JVM 来说是不可见的。类型擦除的基本过程也比较简单,首先是找到用来替换类型参数的具体类。这个具体类一般是 Object。如果指定了类型参数的上界的话,则使用这个上界。把代码中的类型参数都替换成具体的类。

    注:以上内容来源网络收集和归纳,如有错误请不吝赐教。

    展开全文

空空如也

1 2 3 4 5 ... 20
收藏数 94,982
精华内容 37,992
关键字:

泛型