java编程思想第4版第15章通配符笔记及练习

// Exploring the meaning of wildcards.

public class Wildcards {
   // Raw argument:
  static void rawArgs(Holder holder, Object arg) {
     holder.set(arg); // Warning:
    //   Unchecked call to set(T) as a
    //   member of the raw type Holder
     holder.set(new Wildcards()); // Same warning

    // Can't do this; don't have any 'T':
    // T t = holder.get();

    // OK, but type information has been lost:
    Object obj = holder.get();
  }	
  // Similar to rawArgs(), but errors instead of warnings:
  static void unboundedArg(Holder<?> holder, Object arg) {
    // holder.set(arg); // Error:
    //   set(capture of ?) in Holder<capture of ?>
    //   cannot be applied to (Object)
    // holder.set(new Wildcards()); // Same error

    // Can't do this; don't have any 'T':
    // T t = holder.get();

    // OK, but type information has been lost:
    Object obj = holder.get();
  }	
  static <T> T exact1(Holder<T> holder) {
    T t = holder.get();
    return t;
  }
  static <T> T exact2(Holder<T> holder, T arg) {
    holder.set(arg);
    T t = holder.get();
    return t;
  }
  static <T> T wildSubtype(Holder<? extends T> holder, T arg) {
    // holder.set(arg); // Error:
    //   set(capture of ? extends T) in
    //   Holder<capture of ? extends T>
    //   cannot be applied to (T)
    T t = holder.get();
    return t;
  }	
  static <T> void wildSupertype(Holder<? super T> holder, T arg) {
    holder.set(arg);
    // T t = holder.get();  // Error:
    //   Incompatible types: found Object, required T

    // OK, but type information has been lost:
    Object obj = holder.get();
  }
  public static void main(String[] args) {
    Holder raw = new Holder<Long>();
    // Or:
    raw = new Holder();
    Holder<Long> qualified = new Holder<Long>();
    Holder<?> unbounded = new Holder<Long>();
    Holder<? extends Long> bounded = new Holder<Long>();
    Long lng = 1L;

    rawArgs(raw, lng);
    rawArgs(qualified, lng);
    rawArgs(unbounded, lng);
    rawArgs(bounded, lng);
	
    unboundedArg(raw, lng);
    unboundedArg(qualified, lng);
    unboundedArg(unbounded, lng);
    unboundedArg(bounded, lng);

    Object r1 = exact1(raw); // Warnings:
    //   Unchecked conversion from Holder to Holder<T>
    //   Unchecked method invocation: exact1(Holder<T>)
    //   is applied to (Holder)
    Long r2 = exact1(qualified);
    Object r3 = exact1(unbounded); // Must return Object
    Long r4 = exact1(bounded);

    //Long r5 = exact2(raw, lng); // Warnings:
    //   Unchecked conversion from Holder to Holder<Long>
    //   Unchecked method invocation: exact2(Holder<T>,T)
    //   is applied to (Holder,Long)
    Long r6 = exact2(qualified, lng);
    // Long r7 = exact2(unbounded, lng); // Error:
    //   exact2(Holder<T>,T) cannot be applied to
    //   (Holder<capture of ?>,Long)
    //Long r8 = exact2(bounded, lng); // Error:
    //   exact2(Holder<T>,T) cannot be applied
    //   to (Holder<capture of ? extends Long>,Long)
	
    //Long r9 = wildSubtype(raw, lng); // Warnings:
    //   Unchecked conversion from Holder
    //   to Holder<? extends Long>
    //   Unchecked method invocation:
    //   wildSubtype(Holder<? extends T>,T) is
    //   applied to (Holder,Long)
    Long r10 = wildSubtype(qualified, lng);
    // OK, but can only return Object:
    //Object r11 = wildSubtype(unbounded, lng);
    Long r12 = wildSubtype(bounded, lng);
	
    // wildSupertype(raw, lng); // Warnings:
    //   Unchecked conversion from Holder
    //   to Holder<? super Long>
    //   Unchecked method invocation:
    //   wildSupertype(Holder<? super T>,T)
    //   is applied to (Holder,Long)
    wildSupertype(qualified, lng);
    // wildSupertype(unbounded, lng); // Error:
    //   wildSupertype(Holder<? super T>,T) cannot be
    //   applied to (Holder<capture of ?>,Long)
    // wildSupertype(bounded, lng); // Error:
    //   wildSupertype(Holder<? super T>,T) cannot be
    //  applied to (Holder<capture of ? extends Long>,Long)
  }
} ///:~

rawArgs,编译器知道Holder是一个泛型,即使在这里被表示成一个原生类型,编译器知道向set传递一个Object是不安全的。由于是原生类型,可以将任何类型的对象传递给set,而这个对象将被向上转型为Object,因此只要使用了原生类型,都会放弃编译期检查?unboundedArg说明Holder和Holder<?>不同,Holder持有任何类型的组合,Holder<?>持有具有某种具体类型的同构集合,因此不能只是传Object。exact1和exact2都使用了确切参数,但是exac2有额外的参数。wildSubtype中,入参是任何扩展至T对象的Holder,若T是Fruit,那么holder可以是Holder<Apple>,为防止将Orange放入Holder<Apple>中,对set调用(或者对任何接受这个类型参数为参数的方法的调用)都是不允许的,但是任何来自Holder<? extends Fruit>的对象至少是Fruit,因此get()(或者任何将产生具有这个类型参数的返回值的方法)都是允许的。wildSupertype展示了超类型通配符:holder可以是持有任何T的基类型的容器。因此set可以接受T,因为任何可以工作于基类的对象都可以多态地作用于导出类(T),但是因为持有类型可能是任意超类,get唯一安全的类型就是Object。向exact1传递一个无界引用,不会有确定返回类型的类型信息。wildSubtype希望从泛型参数中返回类型确定的返回值,wildSupertype希望接受类型确定的参数。

public class CaptureConversion {
  static <T> void f1(Holder<T> holder) {
    T t = holder.get();
    System.out.println(t.getClass().getSimpleName());
  }
  static void f2(Holder<?> holder) {
    f1(holder); // Call with captured type
  }	
  //@SuppressWarnings("unchecked")
  public static void main(String[] args) {
    Holder raw = new Holder<Integer>(1);
    //f1(raw); // Produces warnings
    //f2(raw); // No warnings
    Holder rawBasic = new Holder();
    rawBasic.set(new Object()); // Warning
    //f2(rawBasic); // No warnings
    f1(rawBasic);
    // Upcast to Holder<?>, still figures it out:
    Holder<?> wildcarded = new Holder<Double>(1.0);
    f2(wildcarded);
  }
}

f1中的类型参数都是确切的,没有通配符或边界。f2中,f1被调用,而f1需要确切,参数类型在f2被捕获。在方法内部,需要使用确切类型需要使用捕获转换。不能从f2中返回T,因为T对于f2是未知的。

练习29:

static void f3(Holder<List<?>> holder, List l, List<?> j) {
    List<?> t = holder.get();
    t.clear();
    Object t1 = holder.get();
    List list = (List) t1;

    //list.
    holder.set(l);
    List t2 = holder.get();
    holder.set(j);
    System.out.println(holder.getClass().getSimpleName());
  }

  static <T> void f4(List<Holder<?>> holder, List l, List<?> j) {
    Holder<T> holder1=null;
    holder.add(holder1);
    Holder<?> holder2=null;
    holder.add(holder2);
    Holder holder3 = holder.get(0);
    Holder<?> holder4 = holder.get(0);
    Holder<T> holder5 = holder.get(0);//此处报错
  }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值