反射的简单理解

1.反射:一个类有多个组成部分,例如,成员变量,成员方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。( 解析编译好之后的.class文件 ) 

   变成时什么情况下才需要加载类,并解剖出类的各个组成部分?  
当只有一个类的.class文件或不知道类的内部结构的时候,或只知道某个包名下的.class文件并且知道这个类里边大方法名称,需要反射,解析出需要的原有java类的成员变量,成员方法,构造方法等。 

2.详解: 
  2-1. 反射的主要步骤: 
      第一步:先加载类 
      第二部:解析出所需类型的构造器 
      第三部:创建解析出来的实体 
      第四步:根据实体对象解析出实体对象里的成员方法或成员属性 

  2-2. 加载类:java中有一个Class类用于代表某一个类的字节码,并且提供了加载某个类字节码的方法forName(),forName()方法用于加载某个类的字节码到内存中并使用.class对象进行封装,还有另外两种得到class对象的方式 : 
     --- 类名.class, 
     --- 对象.getClass() 
    例:  //1.加载类--直接加载 
          Class cla=Class.forName("cn.isoftstone.reflect.Student"); 
    
         //2.加载类--创建对象,调用.getClass 
Student stu=new Student(); 
Class cla1= stu.getClass(); 

         //3.加载类--直接 类名.class 
Class cla2=Student.class; 

     2-3.实例演示: 
public class Student { 

/**单纯的声明一个变量那么它可以叫做一个字段,当这个字段有get方法返回的时候那么它就可以叫做属性 
* 不声明字段,直接返回生命get方法的时候,例:getEmail()那么Email就是一个属性 
* */ 
private String name; 

private int sum; //字段 
private String args[]; 
   
public String getEmail(){ //属性 
return "zhangsansan@163.com"; 

public String getName(){ 
return name; 

public Student() { 
        //解析默认不带参数的构造器 

private  Student(List list) { 
//解析带List参数的构造器 


public Student(String name, int age) { 
//解析带基本数据类型参数的构造器 

public Student(String str[]) { 


    
public Student(String args[],double dou) { 
//解析带数组参数的构造器 

  
//返回无返回值不带参数的成员方法 
public void study() { 
System.out.println("学习中,请勿打扰 ... ... "); 


//解析无返回值 带参数的成员方法 
public void study(Integer i){ 
System.out.println(1); 


//解析待返回值带参数的成员方法 
public int getSum(int a,int b){ 
sum=a+b; 
return sum; 

    
//解析主方法 
public static void main(String[] args) { 
System.out.println("-------"); 


解析Student类的各种情况下的构造方法,Junit测试类: 

@Test 
public void test1() throws Exception{ 
//解析Student类 

//1.加载类 
Class cla=Class.forName("cn.isoftstone.reflect.Student"); 
//2.解析---通过无参数的构造器解析 
Constructor constructor=cla.getConstructor(null); 
//3.创建类的实例 
Student entity=(Student) constructor.newInstance(null); 
entity.study(); 


@Test 
public void test2() throws Exception{ 
//解析带参数的构造器 

//1.加载类 
Class cla=Student.class; 
//2.解析---通过带参数的构造器解析 
Constructor constructor=cla.getConstructor(String.class,int.class); 
    //3.创建类的实例 
Student stu=(Student) constructor.newInstance("zhang sansan",90); 
stu.study(); 
System.out.println(stu.getName()); 


@Test 
public void test3(){ 
//怎么知道类中有哪些构造器 

Class cla=Student.class; 
Constructor csr[]=cla.getConstructors(); 
for(Constructor c:csr){ 
System.out.println(c.toGenericString()); 



@Test 
public void test4()throws Exception{ 
//解析带数组参数的构造器 ---解析带数组的构造器,不能只有一个参数(jdk1.4 jdk1.5的区别) ........... 
/* ---或者参数必须声明在外面 ,把数组强制造型成一个Object对象,如下: 
String str[]={"a","b","c"}; 
Student stu=(Student) con.newInstance((Object)str); 
*/ 
  Class cla=Class.forName("cn.isoftstone.reflect.Student"); 
  Constructor constructor=cla.getConstructor(String[].class,double.class); 
  Student stu=(Student) constructor.newInstance(new String[]{"test","test1","test2"},9.0); 
  stu.study(); 


@Test 
public void test6() throws Exception{ 
//解析私有构造器,私有方法,私有属性要用getDeclaredConstructor(x.class),getDeclaredMethod(ClassObject)解析 
Class cla=Class.forName("cn.isoftstone.reflect.Student"); 
Constructor con=cla.getDeclaredConstructor(List.class); 
con.setAccessible(true); //暴力访问 ,强制修改访问权限 

Student stu=(Student) con.newInstance(new ArrayList()); 

stu.study(); 


@Test 
public void test8() throws Exception{//解析Student类中固定的成员方法 
/** 
*  注:如果解析的是private的私有成员方法,那么解析成员方法的时候要用getDeclaredMethod()方法, 
* 然后Method对象调用setAccessible(true)方法强制执行反射 
* */ 
Class cla=Student.class;
Student entity=(Student) cla.newInstance();//解析出实体对象的新实例,使用con.newInstance()方法的时候,必须保证Student类中有一个无参的构造方法 

//1.解析出所有的成员方法,并遍历 
Method methods[]=cla.getMethods(); 
for(Method method:methods){ 
System.out.println(method.toGenericString()); 


//2.解析不带返回值 不带参数的成员方法 
Method mt1=cla.getMethod("study",null); //解析出目标成员方法,第二个参数是待解析方法的参数数据类型 
mt1.invoke(entity,null);//执行解析出的成员方法,第一个参数是方法对应的实体对象,第二个参数是给待解析方法传的值 

//3.解析不带返回值的成员方法 
Method mt2=cla.getMethod("study",Integer.class); //解析出目标成员方法,第二个参数是待解析方法的参数数据类型 
mt2.invoke(entity, 1);//执行解析出的成员方法,第一个参数是方法对应的实体对象,第二个参数是给待解析方法传的值 

//4.解析带返回值 带参数的成员方法 
Method mt3=cla.getMethod("getSum",int.class,int.class); 
Object obj=mt3.invoke(entity, 2,3);//返回的是一个Object 
System.out.println(obj); 

/**解析主函数main函数   
* jdk1.4 -- main(String args[])当做数组来处理 
* jdk1.5 -- main(String...str )当做可变参数来处理 
* */
Method mt4=cla.getMethod("main",String[].class);
mt4.invoke(entity, new Object[]{new String[]{"aa"}}); 

/*或  String args[]={}; 
     mt4.invoke(entity, (Object)args); 
*/



@Test 
public void test9() throws Exception{ //解析成员属性或字段,注,解析的成员属性必须是定义好的 
Class cla=Class.forName("cn.isoftstone.reflect.Student"); 
Student entity=(Student) cla.newInstance(); 

//1.解析所有的成员属性,解析私有的成员属性调用getDeclaredFields()方法,然后强制执行 
Field fields[]=cla.getDeclaredFields(); 
for(Field field:fields){ 
field.setAccessible(true);//强制执行 
System.out.println(field.getName()); 


//2.解析并操作字段或属性---例:赋值 
Field fd1=cla.getDeclaredField("name"); 
fd1.setAccessible(true); 
fd1.set(entity, "zhangsansan");//赋值 
//System.out.println(stu.getName());//直接通过实体对象的get方法获取值---X 
String value=(String) fd1.get(entity);//通过实体对象获取值 
System.out.println(value); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值