一般来说cast是转型的意思,但是学java的时间也不短了,class类居然还有cast这个方法,这里来学习一下这个cast有何用。

第一次看到这个cast是在Spring的源码中,

spring-framework/spring-beans/src/main/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReader.java:517处有这样的一段代码:

 /**
* Create the {@link BeanDefinitionDocumentReader} to use for actually
* reading bean definitions from an XML document.
* <p>The default implementation instantiates the specified "documentReaderClass".
* @see #setDocumentReaderClass
*/
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}

当时我就好奇了,还有这个。

一、Java api

public T cast(Object obj);

Casts an object to the class or interface represented

解释的比较笼统,意思就是将一个对象装换为类或者接口。

二、代码示例

A.java

 public class A {
public static void show() {
System.out.println("Class A show() function");
}
}

B.java

 public class B extends A {
public static void show() {
System.out.println("Class B show() function");
}
}

TestCast.java

 public class TestCast {
public static void main(String[] args) {
TestCast cls = new TestCast();
Class c = cls.getClass();
System.out.println(c); Object obj = new A();
B b1 = new B();
b1.show(); // casts object
A a = new A();
System.out.println(a.getClass()); // 1. 打印a的class对象
a = A.class.cast(b1);
a.show(); System.out.println(obj.getClass());
System.out.println(b1.getClass());
System.out.println(a.getClass()); // 2. 打印a转换后的class对象
}
}

执行结果如下图:

这个例子是网上给出来的,核心为:a = A.class.cast(b1); 把a转化为了B类型,此处容易产生把b1转成A类型误解。

但是我很不满意啊,这个例子说明了啥??没看出来有卵用。

cast方法的源码

这个方法属于Class.java的

 /**
* Casts an object to the class or interface represented
* by this {@code Class} object.
*
* @param obj the object to be cast
* @return the object after casting, or null if obj is null
*
* @throws ClassCastException if the object is not
* null and is not assignable to the type T.
*
* @since 1.5
*/
@SuppressWarnings("unchecked")
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}

有点晕,这个T是Class的泛型。这个方法只能转换当前类型或其子类下的对象。再来看一下这个isInstance方法

     /**
* Determines if the specified {@code Object} is assignment-compatible
* with the object represented by this {@code Class}. This method is
* the dynamic equivalent of the Java language {@code instanceof}
* operator. The method returns {@code true} if the specified
* {@code Object} argument is non-null and can be cast to the
* reference type represented by this {@code Class} object without
* raising a {@code ClassCastException.} It returns {@code false}
* otherwise.
*
* <p> Specifically, if this {@code Class} object represents a
* declared class, this method returns {@code true} if the specified
* {@code Object} argument is an instance of the represented class (or
* of any of its subclasses); it returns {@code false} otherwise. If
* this {@code Class} object represents an array class, this method
* returns {@code true} if the specified {@code Object} argument
* can be converted to an object of the array class by an identity
* conversion or by a widening reference conversion; it returns
* {@code false} otherwise. If this {@code Class} object
* represents an interface, this method returns {@code true} if the
* class or any superclass of the specified {@code Object} argument
* implements this interface; it returns {@code false} otherwise. If
* this {@code Class} object represents a primitive type, this method
* returns {@code false}.
*
* @param obj the object to check
* @return true if {@code obj} is an instance of this class
*
* @since JDK1.1
*/
public native boolean isInstance(Object obj);

这个isInstance(Object obj)的意思是,obj这个对象是不是与这个Class对象兼容的类。

前面一句是,b1这个对象是不是a.getClass()的实例,后面一个是a是不是a.getClass()的实例。

我想了下,把上面cast所在的那句话反过来一下:

执行结果,报错了:

不能把A转成B,A是父类,B是子类,也就是cast括号中的是源对象,前面的getClass()是待转换成为的目标对象。

或者还有这种用法:

asSubclass方法

 /**
* Casts this {@code Class} object to represent a subclass of the class
* represented by the specified class object. Checks that the cast
* is valid, and throws a {@code ClassCastException} if it is not. If
* this method succeeds, it always returns a reference to this class object.
*
* <p>This method is useful when a client needs to "narrow" the type of
* a {@code Class} object to pass it to an API that restricts the
* {@code Class} objects that it is willing to accept. A cast would
* generate a compile-time warning, as the correctness of the cast
* could not be checked at runtime (because generic types are implemented
* by erasure).
*
* @param <U> the type to cast this class object to
* @param clazz the class of the type to cast this class object to
* @return this {@code Class} object, cast to represent a subclass of
* the specified class object.
* @throws ClassCastException if this {@code Class} object does not
* represent a subclass of the specified class (here "subclass" includes
* the class itself).
* @since 1.5
*/
@SuppressWarnings("unchecked")
public <U> Class<? extends U> asSubclass(Class<U> clazz) {
if (clazz.isAssignableFrom(this))
return (Class<? extends U>) this;
else
throw new ClassCastException(this.toString());
}

翻译一下方法上面的注释:将这个类强制转为另一个类的子类。当需要使类的类型窄化的时候,这个方法特别有用。

这是java.lang.Class中的一个方法,作用是将调用这个方法的class对象转换成由clazz参数所表示的class对象的某个子类。

上面的代码将strList.getClass()获取的class对象转换成Class<? extends List>,这么做似乎没有什么意义,因为我们很清楚strList.getClass()获取的class对象就是ArrayList,它当然是List.class的一个子类;但有些情况下,我们并不能确知一个class对象的类型,典型的情况是Class.forName()获取的class对象:Class.forName()的返回类型是Class<?>,但这显然太宽泛了,假设我们需要List.class类型的class对象,但我们传递给Class.forName的参数是未知的(可能是"java.lang.String",也可能是"java.util.ArrayList"),这时我们就可以用到asSubclass()这个方法了,如下:

asSubclass用于窄化未知的Class类型的范围,而instanceof用于判断一个对象引用是否是一个超类或者接口的子类/实现类,如果试图将instanceof用于Class类型的判断会引起编译错误。

通常在向某些参数严格限制的API传递参数时,为了避免产生编译警告,这个方法比较有用!

下次对asSubclass和cast这两个方法找一个好的例子,这里先了解一下。

最新文章

  1. node.js之开发环境搭建
  2. 构建angular项目
  3. impdp导入job
  4. gulp入坑系列(2)——初试JS代码合并与压缩
  5. Javascript基础系列之(八)Javascript的调试与优化
  6. ognl el表达式 property
  7. IAP Store Kit Guide(中文)
  8. codevs 4927 线段树练习5
  9. window.showModalDialog以及window.open用法简介
  10. static \ const \ volatile 的含义
  11. Python 入门教程 9 ---- A Day at the Supermarket
  12. 代码中实际运用memcached——java
  13. C#上位机串口控制12864显示
  14. 【转】Python正则表达式指南
  15. 2018-2019-2 20175332-实验一《Java开发环境的熟悉》实验报告
  16. Django使用redis实现缓存
  17. MariaDB 安装与启动 过程记录
  18. CentOS7 虚拟机设置文件共享 VMWareTools安装遇到的坑
  19. C++ 读取文本文件内容到结构体数组中并排序
  20. No.6 - 利用 CSS animation 制作一个炫酷的 Slider

热门文章

  1. 升级springboot 2.x 踩过的坑——跨域导致session问题
  2. 进程与multiprocessing模块
  3. web实时长图实践--摘抄
  4. 标准C程序设计七---112
  5. fetch格式
  6. AC日记——图灵机游戏 codevs 2292
  7. iOS 总结网页常用的东西
  8. 什么叫PV,UV,PR值
  9. 邁向IT專家成功之路的三十則鐵律 鐵律五:IT人穩定發展之道-去除惡習
  10. openfire Android学习(六)----总结