小 P:” 是这样的,之前我们有个接口,是返回用户的各项评分,这个接口已经上线半年了,但客户要求我们不但要返回用户的各项评分,还要将描述一下分数的意义。“
小 P:” 原来接口是这样的 List<Integer> getScoresByUser(UserInfo uinfo),返回 60、1500、90 这样的得分,现在该接口要返回 60,活跃度中等【0~100】、1500、粉丝数、90,好评度【0-100】“。
小白:” 不是可以新加一个接口给对方吗?“
寻找解决方案
沟通完成后,小白拖着郁闷的身心,拉下新项目的代码,想着解决方案。先整理思路:
原先的接口原型:
public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); //todo ,get hot socore list.add(60); //todo get fans list.add(1500); //todo get evaluation list.add(90); System.out.println(Arrays.toString(list.toArray())); }
打印出结果:
[60, 1500, 90]
新接口想要打印出:
[60,活跃度中等【0~100】,1500,粉丝数,90,好评度【0-100】]
小白一直想吼出,老子不干了!
public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); list.add(2); list.add(3); try { //todo ,get hot socore list.add(60); list.getClass().getMethod("add", Object.class).invoke(list, "活跃度中等【0~100】"); //todo get fans list.add(1500); list.getClass().getMethod("add", Object.class).invoke(list, "粉丝数,排名 3689 位"); //todo get evaluation list.add(90); list.getClass().getMethod("add", Object.class).invoke(list, "用户评价,超越 92%的用户"); } catch (Exception e) { e.printStackTrace(); } System.out.println(Arrays.toString(list.toArray())); } // 输出 // [60,活跃度中等【0~100】,1500,粉丝数,90,好评度【0-100】]
原来因为种种原因,Java 不能实现真正的泛型,只能使用类型擦除来实现伪泛型。
类型擦除
当编译器对带有泛型的 Java 代码进行编译时,它会去执行类型检查和类型推断,然后生成普通的不带泛型的字节码,这种字节码可以被一般的 Java 虚拟机接收并执行,这种技术被称为擦除(erasure)。这样虽然不会有类型膨胀问题,但是也引起来许多新问题,所以,SUN 对这些问题做出了种种限制,避免我们发生各种错误。
编译器可以在对源程序(带有泛型的 Java 代码)进行编译时使用泛型类型信息保证类型安全,对大量如果没有泛型就不会去验证的类型安全约束进行验证,同时在生成的字节码当中,将这些类型信息清除掉。