Class类的asSubClass()方法

来源:互联网 发布:log4j打印sql日志 编辑:程序博客网 时间:2024/05/22 08:18
    public <U> Class<? extends U> asSubclass(Class<U> clazz) {        if (clazz.isAssignableFrom(this))            return (Class<? extends U>) this;        else            throw new ClassCastException(this.toString());    }

这个方法实现的功能很好懂,主要是什么时候需要用到它。

其作用是将一个Class对象转换成为指定了泛型的Class对象,经常用于你不知道Class对象是什么类型的时候,例如Class.forName(str)他只能返回一个Class<?>,这时你需要将其转换为一个Class<? extends XXX>的对象(可能是添加到制定了泛型的集合里面)。

这样说还是有点抽象,有个具体的例子

  public static List<Class<? extends CompressionCodec>> getCodecClasses(Configuration conf) {    String codecsString = conf.get("io.compression.codecs");    if (codecsString != null) {      List<Class<? extends CompressionCodec>> result        = new ArrayList<Class<? extends CompressionCodec>>();      StringTokenizer codecSplit = new StringTokenizer(codecsString, ",");      while (codecSplit.hasMoreElements()) {        String codecSubstring = codecSplit.nextToken();        if (codecSubstring.length() != 0) {          try {            Class<?> cls = conf.getClassByName(codecSubstring);            if (!CompressionCodec.class.isAssignableFrom(cls)) {              throw new IllegalArgumentException("Class " + codecSubstring +                                                 " is not a CompressionCodec");            }            result.add(cls.asSubclass(CompressionCodec.class));          } catch (ClassNotFoundException ex) {            throw new IllegalArgumentException("Compression codec " +                                                codecSubstring + " not found.",                                               ex);          }        }      }      return result;    } else {      return null;    }  }

codecsString是一个类名的字符串,以逗号分隔,例如:"djava.lang.String,java.io.InputStream,java.util.List"

 现在需要将字符串里面的类名生成对应的Class对象放到List里面,并返回。

看try块的内容,首先通过Class.forName(conf.getClassByName就是调用Class.forName)获得Class<?>对象,但是这个对象是不能放到结果List里面否则会编译错误,List指定了泛型保证插入到List的对象是实现Writable接口的类。所以就需要进行转换。

在转换前做了一个类型检查,使用isAssignableFrom方法,检查通过后再进行强制转换。当然看JDK源码,asSubClass也会进行类型检查,其实这段代码完全可以改成这样

        if (codecSubstring.length() != 0) {          try {            result.add(conf.getClassByName(            codecSubstring).asSubclass(CompressionCodec.class));          } catch (ClassNotFoundException ex) {            throw new IllegalArgumentException("Compression codec " +                                                codecSubstring + " not found.",                                               ex);          } catch (ClassCastException ex) {          throw new IllegalArgumentException("Class " + codecSubstring +                              " is not a CompressionCodec");          }        }


可以看出,asSubClass这个方法会用于你不知道你持有的Class对象的泛型是什么,而且你需要进行泛型参数向下转型


Java泛型方面可能说简单了很简单,说复杂了非常复杂。由于我们大部分做Java基本上用到的都是泛型的基本使用

(List<XXX> list = new ArrayList<XXX>())来进行编译器类型检查来避免潜在的ClassCastException,有些可能纯粹是为了不让IDE发出黄色下划线的警告,涉及不到复杂的东西罢了。



0 0
原创粉丝点击