• Java泛型(7):无界通配符<?>


    无界通配符<?>很容易和原生类型混淆。

    以List为例:

    List表示持有任何Object类型的原生List,其实就等价于List<Object>

    List<?>表示某种具有特定类型的非原生List(同构集合),只是我们不知道它的具体类型是什么,所以我们就不允许往里set数据

    看下面例子:

     1 public class Wildcards {
     2 
     3     // 这里Holder等价于Holder<Object>,Holder<Object>没警告但下面的方法调用时除第一个都会报ERROR,Holder会有警告
     4     static void saveData(Holder holder, Object arg) {
     5         holder.set(arg); // [Warning] Type safety: The method set(Object) belongs to the raw type Holder. References to generic type Holder<T> should be parameterized
     6         Object obj = holder.get();
     7         System.out.println(obj.getClass().getSimpleName() + ": " + obj.toString());
     8     }
     9 
    10     // 因为不知道Holder<?>的具体类型是什么,所以我们就不允许往里set数据
    11     static void saveDataError(Holder<?> holder, Object arg) {
    12         // holder.set(arg); // [Compile Error] The method set(capture#1-of ?) in the type Holder<capture#1-of ?> is not applicable for the arguments (Object)
    13         // holder.set(new Wildcards()); // Same Compile Error
    14         Object obj = holder.get();
    15         System.out.println(obj.getClass().getSimpleName() + ": " + obj.toString());
    16     }
    17 
    18     public static void main(String[] args) {
    19         Holder h1 = new Holder<Long>();
    20         Holder<Long> h2 = new Holder<Long>();
    21         Holder<?> h3 = new Holder<Long>();
    22         Holder<? extends Long> h4 = new Holder<Long>();
    23 
    24         saveData(h1, 1L); // Long: 1
    25         saveData(h2, 2L); // Long: 2
    26         saveData(h3, 3L); // Long: 3
    27         saveData(h4, 4L); // Long: 4
    28 
    29         saveDataError(h1, 5L); // Long: 1
    30         saveDataError(h2, 6L); // Long: 2
    31         saveDataError(h3, 7L); // Long: 3
    32         saveDataError(h4, 8L); // Long: 4
    33     }
    34 }
    35 
    36 class Holder<T> {
    37     private T value;
    38     public Holder() { }
    39     public Holder(T val) { value = val; }
    40     public void set(T val) { value = val; }
    41     public T get() { return value; }
    42     @Override public boolean equals(Object obj) { return value.equals(obj); }
    43 }

    捕获转换技术

    如果向一个使用<?>的方法传递原生类型,那么对于编辑器来说,可能会推断出实际的类型参数,使得这个方法可以调用另一个使用确切类型的的方法。下面是一个例子:

     1 public class CaptureConversion {
     2 
     3     static <T> void getData(Holder<T> holder) {
     4         T t = holder.get();
     5         System.out.println(t.getClass().getSimpleName() + ": " + t);
     6     }
     7 
     8     static void chapterGet(Holder<?> holder) {
     9         getData(holder);
    10     }
    11 
    12     public static void main(String[] args) {
    13         Holder h1 = new Holder<Long>(1L);
    14         chapterGet(h1); // Long: 1
    15     }
    16 }
  • 相关阅读:
    Url中文传值乱码、编码转码问题总结
    简单介绍下我使用了一年多还不知道的Sql server 2005 组件知识
    一次管理项目小组网络的经历(使用RouterOS与Wireshark破解adsl上网密码,使用isa与Bandwidth Splitter来协调带宽)
    asp.net异步处理机制研究
    注释的力量
    AutoMapper简明教程(学习笔记)
    seajs学习笔记
    Hifi入门
    fxcop使用DataFlowRules规则集
    Visual Studio编译选项简介
  • 原文地址:https://www.cnblogs.com/storml/p/8005804.html
Copyright © 2020-2023  润新知