effective java 第32条 谨慎并用泛型和可变参数

1.可变参数的作用在于让客户端能够将可变数量的参数传给方法,但这是个技术露底:当调用一个可变参数方法时,会创建一个对象数组Object[]用来存放可变参数;这个数组应该是一个实现细节,他是可见的。因此,当可变参数有泛型或者参数化类型时,编译警告信息就会产混乱。

2.当一个参数化类型的变量指向一个不是该类型的对象时,会产生堆污染(heap pullution)。它导致编辑器的自动生成转换失败,破坏了泛型系统的基本保证。

3.java7中,增加了@SafeVarargs注解,它让带泛型vararg参数的方法的设计者能够自动禁止客户端的警告。本质上@SafeVarargs注解是通过方法的设计者做出承诺,声明这类型是安全的。所以不要随意使用@SafeVarargs对方法进行注解,除非它是真正安全的。

 

代码示例:

package effectivejava;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 谨慎并用泛型可变参数:
 * 1.可变参数的作用在于让客户端能够将可变数量的参数传给方法,但这是个技术露底:当调用一个可变参数方法时,会创建一个对象数组Object[]用来存放可变参数;这个数组应该是一个实现细节,他是可见的。因此,当可变参数有泛型或者参数化类型时,编译警告信息就会产混乱。2.当一个参数化类型的变量指向一个不是该类型的对象时,会产生堆污染(heap pullution)。它导致编辑器的自动生成转换失败,破坏了泛型系统的基本保证。
3.java7中,增加了@SafeVarargs注解,它让带泛型vararg参数的方法的设计者能够自动禁止客户端的警告。本质上@SafeVarargs注解是通过方法的设计者做出承诺,声明这类型是安全的。所以不要随意使用@SafeVarargs对方法进行注解,除非它是真正安全的。

public class VarargT {
    
    public static void main(String[] args) {
        // java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
        //允许另一个方法访问一个泛型可变参数数组是不安全的。
//        String[] arr = pickTwo("Good", "Fast", "Cheap");
        List<String> strList = new ArrayList<>();
        strList.add("work");
        dangerous(strList);
    }
    
    //unsafe
    //当调用一个可变参数方法时,会创建一个对象数组Object[]用来存放可变参数
    static <T> T[] toArray(T... args) {
        return args;
    }
    
    static <T> T[] pickTwo(T a , T b, T c) {
        switch (ThreadLocalRandom.current().nextInt(3)) {
        case 0:
            return toArray(a, b);
        case 1:
            return toArray(a, c);
        case 2:
            return toArray(c, b);
        }
        throw new AssertionError();
    }
    
    //当调用一个可变参数方法时,会创建一个对象数组Object[]用来存放可变参数
    static void dangerous(List<String>... stringLists) {
        List<Integer> intList = new ArrayList<>();
        intList.add(42);
        Object[] objects = stringLists;
        objects[0] = intList; // heap pullution:将List<Integer>放入List<String>
        String s = stringLists[0].get(0); // classCastException:java.lang.Integer cannot be cast to java.lang.String
        System.out.println(s);
    }
    
    

}
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值