详谈Java中的泛型概念

相关文章

1.泛型的概念

Java5才有了泛型,在泛型被加入之前。Java中的对象集合,往往是需要转换为Object对象,取出对象也是要再次进行强制类型转换,这样的操作带来了ClassCastException风险。
泛型的加入,使得集合在编译阶段就可以推断出集合中元素类型,减少了代码臃肿和异常风险。

java5 允许程序在创建集合时指定集合元素的类型,如List指定类型为String,它只可以保存String对象,这被称为“参数化类型(parameterized type)”,又称“泛型(Generic)。”

//java7 的菱形语法("<>"标识)可以省略构造器中泛型对象类型
List<String> names = new ArrayList<>();
names.add("小王1");
names.add("小王2");
names.add("小王3");

2.泛型的3种常见使用–泛型类、泛型接口和泛型方法

定义类、接口或方法时使用类型形参(泛型),在声明变量、创建对象、调用方法时候会动态指定这个泛型。

2.1 泛型类

public class Apple<T> {
    //使用T类型定义实例变量
    private T info;
    public Apple(){}
    //使用T类型来定义构造器
    public Apple(T info){
        this.info = info;
    }

    public T getInfo() {
        return info;
    }

    public void setInfo(T info) {
        this.info = info;
    }
    
}

//使用
Apple<String> name = new Apple<>("苹果");
Apple<Double> price = new Apple<>(5.0);

泛型类与普通类的区别就是在方法名后使用<T>进行了声明泛型形参,接下来可以在类中将T作为类型使用(如上面直接定义变量info)。

2.2 泛型接口

//泛型形参E
public interface loadResult<E>{
    //E 作为参数类型
    void returnResult(E result);
    
}

public interface addResult<E>{
    //E 作为类型使用
    E add();
}

泛型接口跟泛型类声明基本一样,使用的范围也是相同。

2.3 泛型方法

List<String>不是List<Object>子类,如果想要将每一个String类型的数组元素放到一个集合中,集合的数据类型只能是String:

     String[] fruitArray = new String[]{"apple","banana","peach"};
     List<String> fruitList = new ArrayList<>();
     array2Collection(fruitArray,fruitList);
     Log.d(TAG,">>>>>> fruitList = " + fruitList);

	//代码省略...
    private void array2Collection(String[] array, List<Object> list) {
        for (String str : array) {
            list.add(str);
        }
    }

上面的代码在编译环境下会报如下异常信息:
在这里插入图片描述

如果后期需要放置Integer类型,就需要再次新建Integer的集合,这样的方法功能十分有限。为了解决这个问题,Java设计了泛型方法。泛型方法对比普通方法多了泛型形参声明,所有的泛型形参声明放在修饰符和方法返回值中间。

修饰符 <T,S> 返回值类型 方法名(形参列表){
    //方法体

}
private static <T> void add(T t) {
   Log.d(TAG, ">>>>>>" + t + "-100");
}

使用泛型方法来完成将数组数据元素放到集合中


//定义一个泛型方法,T泛型形参仅可以在该方法中使用
private <T> void array2Collection(T[] array, List<T> list) {
    for (T str : array) {
            list.add(str);
    }
}

//泛型方法使用
String[] fruitArray = new String[]{"apple", "banana", "peach"};
List<String> fruitList = new ArrayList<>();
Integer[] integers = new Integer[]{0, 1, 2, 3};
Float[] floats = new Float[]{1.0f, 2.0f, 3.2f};
List<Number> numberList = new ArrayList<>();
array2Collection(integers, numberList);
Log.d(TAG, ">>>>>> Integer[] numberList = " + numberList);
array2Collection(floats, numberList);
Log.d(TAG, ">>>>>> Float[] numberList = " + numberList);
array2Collection(fruitArray, fruitList);
Log.d(TAG, ">>>>>> List<String> fruitList = " + fruitList);

//输出结果:
D: >>>>>> Integer[] numberList = [0, 1, 2, 3]
D: >>>>>> Float[] numberList = [0, 1, 2, 3, 1.0, 2.0, 3.2]
D: >>>>>> List<String> fruitList = [apple, banana, peach]

3.类型通配符

接下来了解下类型通配符的规则。Java集合不支持型变,即List<String>并不是List<Object>的子类。为了表示泛型父类,可以考虑使用类型通配符作为参数。
类型通配符使用符号"?"表示。常见如集合List<?>、Map<?>等场景。

    
//定义方法
    private void test2(List<?> c) {
        for (int i = 0; i < c.size(); i++) {
            Log.d(TAG, ">>>>>>>> result = " + c.get(i));
        }
    }
        //使用类型通配符
        List<String> list = new ArrayList<>();
        list.add("String_0");
        list.add("String_1");
        test2(list);

        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        test2(list1);

	//输出结果:
	D: >>>>>>>> result = String_0
	D: >>>>>>>> result = String_1
	D: >>>>>>>> result = 1
	D: >>>>>>>> result = 2

使用类型通配符的List代表它是各种泛型List的父类,不能向List<?>中添加元素。集合代表的是一组对象,不允许把对象放进未知类型的集合中。

3.1 类型通配符的上/下限

List<?>表示的是所有父类,为了限制其范围Java提供了被限制的泛型通配符。其表示如下:

//代表集合中的元素都是Fruit子类
List<? extends Fruit>

既然有上限自然有下限,通配符下限表示方式为:

List<? super Apple>

4.泛型形参的上限

有了对通配符上限的了解,泛型形参上限的概念也很好理解了。如下代码示例:定义类Orange,限制传递的泛型必须是Number子类或本身

    /**
     * 泛型形参上限
     * @param <T>
     */
    public class Orange<T extends Number>{
        T temp;

        public Orange() {
        }
    }

		//使用Orange类
        Orange<Integer> orange = new Orange<>();
        Orange<Double> orange1 = new Orange<>();
        Orange<String> orange2 = new Orange<String>();//①编译报错

上面代码示例①处编译报Type parameter xxx is not within its bound。:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值