• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
风吹花落泪如雨
博客园    首页    新随笔    联系   管理    订阅  订阅

JAVA泛型(二)类型通配符

类型通配符

为了表示各种泛型List的父类,可以使用类型通配符,类型通配符是一个问号(?)。

当直接使用List<?>这种形式时,即表明这个List集合可以是任何泛型List的父类。但还有一种情况,程序只希望它代表某一类泛型的父类。

被限制的类型通配符

//它表示泛型形参必须是Shape子类的List
List<? extends Shape>

此处的问号<?>代表一个未知的类型,这个未知的类型必须是Shape的子类型(也可以是Shape本身),因此可以把Shape称为这个通配符的上限(upper bound)。

public class Canvas{
  public void drawAll(List<? extends Shape> shapes){
     for(Shape s : shapes){
       s.drwa(this);
    }
    //下面代码引起编译错误
    //shapes.add(0,new Rectangle());
  }
}

shapes.add()的第二个参数是? extends Shape,它表示Shape未知的子类,程序无法确定这个类型是什么,所以无法将任何对象添加到这种集合中(null例外)。

型变:指定通配符上限的集合,只能从集合中取出元素(取出的元素总是上限的类型),不能向集合中添加元素。

逆变:指定通配符下限的集合,只能向集合中添加元素(因为实际赋值的集合元素总是逆向声明的父类),不能取出元素(不确定取出的是哪个父类的对象)。

TreeSet(Comparable<? super E> c)
public interface Comparator<T>{
   int compare(T fst, T snd);
}

通过这种带下限的通配符的语法,可以在创建TreeSet对象时灵活地选择合适的Comparator。若创建一个TreeSet<String>集合,那么这个Comparator可以是Comparator<String>,也可以是Comparator<Object>

import java.util.*;
public class a{
  public static void main(String[] args){
    //Comparator的实际类型是TreeSet的元素类型的父类,满足要求
    TreeSet<String> ts1 = new TreeSet<>(new Comparator<Object>(){
      public int compare(Object fst, Object snd){
        return hashCode() > snd.hashCode() ? 1
           : hashCode() < snd.hashCode() ? -1 : 0;
      }
    });
     
    ts1.add("hello");
    ts1.add("wa");
    //Comparator的实际类型是TreeSet元素的类型,满足要求
    TreeSet<String> ts2 = new TreeSet<>(new Comparator<String>(){
      public int compare(String first, String second){
        return first.length() < second.length() ? -1
         : first.length() > second.length() ? 1 : 0;
      }
    });
    ts2.add("hello");
    ts2.add("wa");
    System.out.println(ts1);
    System.out.println(ts2);
  }
}

设定泛型形参的上限

Java泛型不仅允许在使用通配符形参时设定上限,也可以在定义泛型形参时设定上限。

import java.util.*;
public class a<T extends Number>{
  T col;
  public static void main(String[] args){
    a<Integer> a1 = new a<>();  
    a<Double> a2 = new a<>();
    //编译异常,String不是Number的子类型  
    //a<String> a3 = new a<>();
  }
}

可以设置多个上限(至多有一个父类上限,可以有多个接口上限),表明该泛型形参是其父类的子类(或父类本身),并且实现多个上限接口

public class Apple<T extends Number & java.io.Serializable>{...}
posted @ 2018-06-15 19:29  风吹花落泪如雨  阅读(134)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3