java[学习] 泛型

    xiaoxiao2021-03-25  169

    概念

    泛型,即概念参数化类型,将类型由原来的具体的类型参数化,类似方法中的变量参数,此时类型也定义成参数形式(可以称为类型形参),然后再使用调用时传入具体的类型。

    ##实例##

    先来看看Java自带的例子 List

    public class Fxing { public static void main(String args[]){ List<String> list = new ArrayList<String>(); list.add("qqyumidi"); list.add("corn"); for (int i = 0; i < list.size(); i++) { String name = list.get(i); // 2 show("name:" + name); } } private static void show(Object object){ System.out.println(object); } }

    上述列子中将lIst的泛型定义为String类型参数,也就是说,相应的List接口中肯定含有类型形参,且get()方法的返回结果也直接是此形参类型。具体看一下list源码

    public interface List<E> extends Collection<E> { int size(); ....... E get(int index); /** * Replaces the element at the specified position in this list with the * specified element (optional operation). */ E set(int index, E element); /** * Inserts the specified element at the specified position in this list * (optional operation). Shifts the element currently at that position * (if any) and any subsequent elements to the right (adds one to their * indices). */ void add(int index, E element); /** * Removes the element at the specified position in this list (optional * operation). Shifts any subsequent elements to the left (subtracts one * from their indices). Returns the element that was removed from the * list. */ E remove(int index); ..... }

    我们可以看到,在List接口中采用泛型化定义之后,中的E表示类型形参,可以接收具体的类型实参,并且此接口定义中,凡是出现E的地方均表示相同的接受自外部的类型实参。

    我又写了一个例子

    public class Fxing { public static void main(String args[]){ List list = new ArrayList(); list.add("qqyumidi"); list.add("corn"); list.add(100); for (int i = 0; i < list.size(); i++) { String name = "123"; if(list.get(i) instanceof String){ name = (String) list.get(i); // 2 }else if(list.get(i) instanceof Integer){ name = (list.get(i)).toString(); // 2 } show("name:" + name); } } private static void show(Object object){ System.out.println(object); } }

    从代码中,可以看出,如果没有定义类型参数,也可以传其他参数,但是在输出的时候就要判断是什么类型,这样就比较麻烦了。

    写了一个泛型类

    package com.yangyi.javaplan.fxing; /** * Created by GYH on 2017/3/6. */ public class Box<T> { private T data; public Box(T data) { this.data = data; } public T getData() { return data; } public void setData(T data) { this.data = data; } }

    调用

    import java.util.ArrayList; import java.util.List; /** * Created by GYH on 2017/3/6. */ public class Fxing { public static void main(String args[]){ Box<String> stringBox = new Box<String>("guoyuehua"); show(stringBox.getClass()); Box<Integer> integerBox = new Box<Integer>(12); show(integerBox.getClass()); } private static void show(Object object){ System.out.println(object); } }

    运行结果

    class com.yangyi.javaplan.fxing.Box class com.yangyi.javaplan.fxing.Box true

    从运行结果可以看出,虽然传入了不同的泛型实参类型,但是并没有真正意义上生成不同的类型,传入不同的类型实参,在内存上只有一个,即还是原来的最基本的类型,当然,逻辑上不同的泛型类型。

    原因:在Java中的泛型这一概念提出作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件是不包含任何泛型信息的,泛型信息不会进入到运行时阶段。

    那么泛型中父子关系的类型吗

    栗子

    public class Fxing { public static void main(String args[]){ Box<Number> numberBox = new Box<Number>(99); Box<Integer> integerBox = new Box<Integer>(12); showData(numberBox); showData(integerBox); } private static void showData(Box<Number> box){ show("name: "+ box.getData()); } private static void show(Object object){ System.out.println(object); } }

    栗子中Number 和 Integer是父子关系,但是编译时报错,…cannot be applied to …,错误,显然在逻辑上Box不能作为Box 的父类,如果非要用,是不是还要判断类型或者强制转换,这就和泛型提出的理论矛盾了,这个时候类型通配符就来了,类型通配符的使用:代替具体的类型实参(是实参、实参、实参 重要的事情说三遍)

    栗子

    public class Fxing { public static void main(String args[]){ Box<Number> numberBox = new Box<Number>(99); Box<Integer> integerBox = new Box<Integer>(12); showData(numberBox); showData(integerBox); } private static void showData(Box<?> box){ show("name: "+ box.getData()); } private static void show(Object object){ System.out.println(object); } }

    还有在使用的时候还要遇到,限制通配符的上限和下限,比如我要限制传的参数必须是Number的子类等等,那么就需要加上限制。

    public class Fxing { public static void main(String args[]){ Box<Number> numberBox = new Box<Number>(99); Box<Integer> integerBox = new Box<Integer>(12); showData(numberBox); showData(integerBox); } private static void showData(Box<? extends Number> box){ show("name: "+ box.getData()); } private static void show(Object object){ System.out.println(object); } }

    上面定义的是上限,那么下限定义是:Box<? super Number> 形式

    注意:并且还要注意的一点是,Java中没有所谓的泛型数组一说。

    转载请注明原文地址: https://ju.6miu.com/read-1256.html

    最新回复(0)