Class类的学习摘要:

1、Class.asSubClass();

Class<?> asSubClass(Class<?>)这个方法是什么意思呢?

从名字上看貌似是将调用的Class转成括号内的Class的子类,但是正好是反的。。。。

这个方法的作用是:父类作为参数,将父类转化为子类。



  1. public <U> Class<? extends U> asSubclass(Class<U> clazz)  

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

  1. List<String> strList = new ArrayList<String>();  
  2. Class<? extends List> strList_cast = strList.getClass().asSubclass(List.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()这个方法了,如下:

  1. Class.forName("xxx.xxx.xxx").asSubclass(List.class).newInstance();  

 当xxx.xxx.xxx是List的子类时,正常执行,当不是List的子类时,抛出ClassCastException,这时我们可以做些别的处理;

 

如果我们查看Class.asSubclass()在JDK中的中的引用的话,会发现这种用法有很多。

 

这里有必要说下 instanceof 关键字.

  1. <<object reference>> instanceof <<class/interface name>>  

它的用法用于判断一个Object是否是某个超类或者接口的一个子类或者实现类(不一定是直接超类或者直接接口),如下

  1. interface IFace {  
  2.       
  3. }  
  4.   
  5. class IFaceImpl implements IFace {  
  6.       
  7. }  
  8.   
  9. class IFaceImplExt extends IFaceImpl {  
  10.       
  11. }  
  12.   
  13. System.out.println(new IFaceImpl() instanceof IFace); // true  
  14. System.out.println(new IFaceImplExt() instanceof IFace); // true  

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

  1. // both will cause compliration error  
  2. System.out.println(IFaceImpl.class instanceof IFace);  
  3. System.out.println(IFaceImplExt.class instanceof IFace.class);  
************************************************************************************************************************************************

  看了还不是太懂

************************************************************************************************************************************************

2、cast(Object obj);

今天同学问了我一个反射的问题, 他想通过Class类的cast方法把只含有数字的一个字符串自动转换为Double类型.
他的源代码是这样的
 String value = "123";
System.out.println(Double.class.cast(d);
 结果运行时返回的是Unknow Source, 并抛出类型转换异常.
查Java API, API也说的很含糊, 只说把指定的对象强制转换成当前类型的对象:
public T cast(Object obj)
Casts an object to the class or interface represented by this Class object.
没办法, 我只好打开JDK的源代码, 查看了这个函数, 原来这个方法只能转换当前类型或其子类下的对象.其源代码如下:
 public T cast(Object obj) {
   if (obj != null && !isInstance(obj))
     throw new ClassCastException();
   return (T) obj;
}
 很明显, 这个方法只是简单的进行了强制转换, 字符类型强制转换成Double肯定是错误的.

************************************************************************************************************************************************

************************************************************************************************************************************************

3、forName(String className)返回与带有给定字符串名的类或接口相关联的 Class 对象。

   调用 forName("X") 将导致命名为 X 的类被初始化。

   forName(String name, boolean initialize, ClassLoader loader) 

关于forName()方法 
这个方法总是返回要加载的类的Class类的实例 
1、forName(String className)单参数时, initialize=true 
    a.总是使用当前类装载器(也就是装载执行forName()请求的类 的类装载器) 
    b.总是初始化这个被装载的类(当然也包括:装载、连接、初始化) 
2、forName(String className, boolean initialize, ClassLoader loader) 
    a.loader指定装载参数类所用的类装载器,如果null则用bootstrp装载器。 
     b.initialize=true时,肯定连接,而且初始化了; 
     c.false时,绝对不会初始化,但是可能被连接了,但是这里有个例外,如果在调用这个forName()前,已经被初始化了,那么返回的类型也肯定是被初始化的(当然,这里也暗含着:被同一个loader所装载的,而且这个类被初始化了) 

关于用户自定义的类装载器的loadClass()方法 
1、loadClass(String name)单参数时, resolve=false 
    a.如果这个类已经被这个类装载器所装载,那么,返回这个已经被装载的类型的Class的实例,否则,就用这个自定义的类装载器来装载这个class,这时不知道是否被连接。绝对不会被初始化 
    b.这时唯一可以保证的是,这个类被装载了。但是不知道这个类是不是被连接和初始化了 
2、loadClass(String name, boolean resolve) 
    a.resolve=true时,则保证已经装载,而且已经连接了。resolve=falses时,则仅仅是去装载这个类,不关心是否连接了,所以此时可能被连接了,也可能没有被连接 




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值