黑马程序员---反射的学习

---------------------- android培训java培训、期待与您交流! ----------------------


反射,是Java中非常重要的一个功能,如果没有反射,可以说很多框架都难以实现。

什么是反射?说白了就是可以通过Java代码获取装载到方法区的类信息的手段。

当装载一个类时,会在方法区产生一个数据结构,该结构中包含着装载的类的相关信息。字节码可以看成是数据流,那么方法区的这种数据结构可以说是字节码数据流的结构化表现。装载的最终产物就是java.lang.Class类的一个对象,它是Java程序与方法区内部数据结构之间的接口。
那么,我们能通过这个接口访问内部数据结构的哪些信息呢?接下来介绍关于反射常用的一些内容。反射的大部分方法大都与安全管理器有关,本文忽略此部分。

假设有以下代码(一个简单的文章管理代码)

packagecom.ticmy.reflect;

  

/**

 文章管理接口

 * @author Administrator

 */

publicinterfaceArticleInterface {

    publicvoiddel(longid)throwsException;

    publicvoidadd(String content)throwsException;

    publicvoidmodify(longid, String content)throwsException;

}


一个简单实现

package  com.ticmy.reflect;
  
import  java.util.Map;
import  java.util.Random;
import  java.util.concurrent.ConcurrentHashMap;
import  java.util.concurrent.atomic.AtomicLong;
  
public  class  ArticleManage  implements  ArticleInterface {
     private  final  Map<Long, String> articles;
     private  boolean  needCheck;
     private  final  AtomicLong idIncr =  new  AtomicLong( 1 );
     public  ArticleManage( boolean  needCheck) {
         System.out.println( "带参数的构造方法" );
         this .needCheck = needCheck;
         articles =  new  ConcurrentHashMap<Long, String>();
     }
  
     public  ArticleManage() {
         System.out.println( "默认构造方法" );
         this .needCheck =  true ;
         articles =  new  ConcurrentHashMap<Long, String>();
     }
  
     public  void  del( long  id)  throws  Exception {
         System.out.println( "删除文章" );
         articles.remove(id);
     }
  
     public  void  add(String content)  throws  Exception {
         if ((!isNeedCheck()) || checkContent()) {
             System.out.println( "添加文章" );
             articles.put(idIncr.getAndIncrement(), content);
         }
     }
  
     public  void  modify( long  id, String content)  throws  Exception {
         if ((!isNeedCheck()) || checkContent()) {
             System.out.println( "修改文章内容" );
             articles.put(id, content);
         }
     }
  
     public  boolean  checkContent()  throws  Exception {
         System.out.println( "检查文章内容" );
         Random random =  new  Random();
         int  value = random.nextInt( 100 );
         if (value <  20 ) {
             //20%概率失败
             throw  new  Exception( "文章内容不合法" );
         }
         return  true ;
     }
  
     public  boolean  isNeedCheck() {
         return  needCheck;
     }
}

1、生成一个ArticleInterface实现类的一个对象。

package  com.ticmy.reflect;
public  class  Test {
     public  static  void  main(String[] args)  throws  Exception {
         ArticleInterface inst = (ArticleInterface)Class.forName( "com.ticmy.reflect.ArticleManage" )
                 .newInstance();
         inst.add( "this is a short article" );
     }
}

我们可能有以上代码来生成一个ArticleManage的实例。如果以前没接触过反射,肯定会纳闷,这里完全可以用ArticleInterface inst = new ArticleManage();这句来取代反射,用反射来创建对象的意义何在。如果在写这段代码的时候,已经知道要new ArticleManage了,可能确实意义不大。但假如在写代码的时候还不知道com.ticmy.reflect.ArticleManage的存在呢或者压根就是留给二次开发的人去做的呢?可能需要一个配置,里面配置着ArticleInterface实现类的全限定名,而此时在不知道其实现类的情况下,可以用上述方式来创建类的对象了。就好像写spring的那些人,他们根本不知道你要注入的对象类型,无论如何他们也无法在代码中使用new的,反射就能很好的解决这个问题。
上面的代码运行后会发现,newInstance调用后使用的是ArticleManage的默认构造方法,那么该如何使用带boolean参数的构造方法呢?这就是下面要说的内容。

2、获取类的构造方法。
Class类中有几个方法可以用来获取构造方法,getConstructors()、getConstructor(Class… parameterTypes)以及getDeclaredConstructors()、getDeclaredConstructor(Class… parameterTypes)。其中含有Declared的表示获取所有的构造方法,不管其是private,protected,public还是包内可见的。Class中还有其它带来Declared的方法,其情况跟这里类似。而不带Declared的,表示获取的是声明为public的内容。再看参数情况,不带参数的表示获取所有能获取的构造方法(getConstructors获取所有public的构造方法,getDeclaredConstructors获取所有声明的构造方法),而带参数的表示构造方法的参数类型。我们在例子中声明的都是public构造方法,想要调的是带boolean参数的构造方法,因此我们可以用如下方式实现:

package  com.ticmy.reflect;
import  java.lang.reflect.Constructor;
public  class  Test {
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> clazz = Class.forName( "com.ticmy.reflect.ArticleManage" );
         Constructor<?> constructor = clazz.getConstructor( boolean . class );
         ArticleInterface inst = (ArticleInterface)constructor.newInstance( false );
         inst.add( "this is a short article" );
     }
}


Constructor里也有newInstance方法,如果构造方法有参数,就按构造方法声明的顺序将参数传进去;如果没有,则可以不传参数。



---------------------- android培训java培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net/heima

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值