Java中的反射[转载]

转自:https://blog.csdn.net/sinat_38259539/article/details/71799078#commentBox

1.什么是反射?

 反射是通过一个类可以知道其中所含的属性和方法,并且对于一个对象可以调用它的任意属性和方法;

 这种动态获取信息以及动态调用对象的方法就是JAVA语言的反射机制。

2. 反射就是把JAVA类中的各种成分映射成一个对象

比如类中有成员变量,方法,构造方法等信息,利用反射技术对一个类进行解剖,把各个组成部分映射成为一个对象

//因为每个类定义是只有一个的,对象可以实例化很多个,以前的理解还是太粗浅了。

3.重要的Class类

获取Class对象的三种方法:

package fanshe;
/**
 * 获取Class对象的三种方式
 * 1 Object ——> getClass();
 * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
 * 3 通过Class类的静态方法:forName(String  className)(常用)
 *
 */
public class Fanshe {
    public static void main(String[] args) {
        //第一种方式获取Class对象  
        Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
        Class stuClass = stu1.getClass();//获取Class对象
        System.out.println(stuClass.getName());
        
        //第二种方式获取Class对象
        Class stuClass2 = Student.class;
        System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
        
        //第三种方式获取Class对象
        try {
            Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
            System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
    }
}

 

1)通过对象的getClass()函数获取

2)通过对象的class属性获取(任何数据类型,包括基本数据类型都有一个静态的class属性)

3)通过Class类的静态方法forName("报名.类名");

在运行期间,一个类只有一个class对象产生。

第三种方法是常用的,可以通过一个字符串来创建对象。

并且给出了一些例子,

例1:

可以反射数据成员、方法、构造函数、并且可以反射main方法:

Student类:

package fanshe.main;
 
public class Student {
 
    public static void main(String[] args) {//定义了一个main方法。
        System.out.println("main方法执行了。。。");
    }
}

 

Main类:

package fanshe.main;
 
import java.lang.reflect.Method;
 
/**
 * 获取Student类的main方法、不要与当前的main方法搞混了
 */
public class Main {
    
    public static void main(String[] args) {
        try {
            //1、获取Student对象的字节码
            Class clazz = Class.forName("fanshe.main.Student");
            
            //2、获取main方法
             Method methodMain = clazz.getMethod("main", String[].class);//第一个参数:方法名称,第二个参数:方法形参的类型,
            //3、调用main方法
            // methodMain.invoke(null, new String[]{"a","b","c"});
             //第一个参数,对象类型,因为方法是static静态的,所以为null可以,第二个参数是String数组,这里要注意在jdk1.4时是数组,jdk1.5之后是可变参数
             //这里拆的时候将  new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。
             methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一
            // methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        
    }
}

例2:

可以通过配置文件来定义

public class Student {
    public void show(){
        System.out.println("is show()");
    }
}

 

配置文件pro.txt

className = cn.fanshe.Student
methodName = show

 

测试类:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
 
/*
 * 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改
 * 我们只需要将新类发送给客户端,并修改配置文件即可
 */
public class Demo {
    public static void main(String[] args) throws Exception {
        //通过反射获取Class对象
        Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
        //2获取show()方法
        Method m = stuClass.getMethod(getValue("methodName"));//show
        //3.调用show()方法
        m.invoke(stuClass.getConstructor().newInstance());
        
    }
    
    //此方法接收一个key,在配置文件中获取相应的value
    public static String getValue(String key) throws IOException{
        Properties pro = new Properties();//获取配置文件的对象
        FileReader in = new FileReader("pro.txt");//获取输入流
        pro.load(in);//将流加载到配置文件对象中
        in.close();
        return pro.getProperty(key);//返回根据key获取的value值
    }
}

 

posted @ 2018-09-10 23:32  lypbendlf  阅读(137)  评论(0编辑  收藏  举报