Java的反射

来源:互联网 发布:他知而自不知的我属于 编辑:程序博客网 时间:2024/06/05 06:30

本文主要围绕以下几个点来详解反射:
1、反射机制是什么?
2、反射机制能做什么?
3、Java中反射的API以及应用

1.反射机制是什么?

借用百度百科的定义:

反射机制是在运行状态中:
1、对于任意一个类,都能够知道这个类的所有属性和方法;
2、对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

之所以强调属性、方法,是因为属性、方法是开发者对于一个类最关注的两个部分。实际上通过反射,不仅仅可以获知类的属性、方法,还可以获知类的父类、接口、包等信息

至于反射的原理,不难,Java类加载机制中讲到了,一个类在加载的时候,会在内存中生成一个代表这个.class文件的java.lang.Class对象,.classs文件里面就包含了描述这个类的信息的一切内容。至于.class文件,是由Java编译器(注意是Java编译器,指的不仅仅是Javac)编译而来的,是编译原理的领域。

2. 反射机制能做什么?

下面第二个问题,反射机制能做什么?
反射机制主要提供了以下功能:
1. 在运行时判断任意一个对象所属的类;
2. 在运行时构造任意一个类的对象;
3. 在运行时判断任意一个类所具有的成员变量和方法;
4. 在运行时调用任意一个对象的方法;
5. 生成动态代理。

3.发射机制的API以及应用实例

Class类库与java.lang.reflect类库一起对反射机制提供了支持。

1.通过一个实例对象获取完整的包名和类名

@Testpublic void test1(){    ReflectTest reflectTest = new ReflectTest();    System.out.println(reflectTest.getClass().getName());}/**output~test.ReflectTest*/

2.实例化class类对象

@Testpublic void test2() throws ClassNotFoundException {    Class<?> class1 = null;    class1 = Class.forName("test.ReflectTest");    System.out.println("类名称是:"+class1);}/**output~类名称是:class test.ReflectTest*/

3.获取一个对象的父类与实现的接口

@Testpublic void test3() throws ClassNotFoundException {    Class<?> clazz = null;    clazz = Class.forName("test.ReflectTest");    //获取父类    Class<?> parentClass = clazz.getSuperclass();    System.out.println("clazz的父类为:" + parentClass.getName());    // 获取所有的接口    Class<?> intes[] = clazz.getInterfaces();    System.out.println("clazz实现的接口有:");    for (int i = 0; i < intes.length; i++) {        System.out.println((i + 1) + ":" + intes[i].getName());    }}/**output~clazz的父类为:java.lang.Objectclazz实现的接口有:1:java.io.Serializable*/

4.获取某一个类中全部构造函数 以及 实例化一个类对象

@Testpublic void test4() throws Exception {    Class<?> class1 = null;    class1 = Class.forName("test.User");    // 第一种方法,实例化默认构造方法,调用set赋值    User user = (User) class1.newInstance();    user.setAge(23);    user.setName("LouLou");    System.out.println(user);    // 结果 User [age=20, name=Rollen]    // 第二种方法 取得全部的构造函数 使用构造函数赋值    Constructor<?> cons[] = class1.getConstructors();    // 查看每个构造方法需要的参数    for (int i = 0; i < cons.length; i++) {        Class<?> clazzs[] = cons[i].getParameterTypes();        System.out.print("cons[" + i + "] (");        for (int j = 0; j < clazzs.length; j++) {            if (j == clazzs.length - 1)                System.out.print(clazzs[j].getName());            else                System.out.print(clazzs[j].getName() + ", ");        }        System.out.println(")");    }    // 结果    // cons[0] (int, java.lang.String)    //cons[1] (java.lang.String)    //cons[2] ()    user = (User) cons[0].newInstance(23, "LouLou");    System.out.println(user);    // 结果 User [age=23, name=LouLou]    user = (User) cons[1].newInstance("LouLou");    System.out.println(user);    // 结果 User [age=0, name=LouLou]}//实体类class User {    private int age;    private String name;    public User() {        super();    }    public User(String name) {        super();        this.name = name;    }    public User(int age, String name) {        super();        this.age = age;        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "User [age=" + age + ", name=" + name + "]";    }}

5.获取某个类的全部属性

class Parent {    private Integer pf1=1;    protected Integer pf2=2;    public Integer pf3=3;    Integer pf4=4;}public class ReflectTest extends Parent implements Serializable{    private String field1="field1";    protected String field2="field2";    public String field3="field3";    String field4="field3";    @Test    public void test5() throws Exception {        Class<?> clazz = null;        clazz = Class.forName("test.ReflectTest");        System.out.println("===============本类属性===============");        Field[] field = clazz.getDeclaredFields();//获取本类的全部属性(不包括父类或则实现的接口)        for (int i = 0; i < field.length; i++) {            // 权限修饰符            int mo = field[i].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = field[i].getType();            System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");        }        System.out.println("==========本类或则实现的接口或者父类的public的属性==========");        // 取得实现的接口或者父类的属性        Field[] filed1 = clazz.getFields();        for (int j = 0; j < filed1.length; j++) {            // 权限修饰符            int mo = filed1[j].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = filed1[j].getType();            System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");        }    }}/**output~===============本类属性===============private java.lang.String field1;protected java.lang.String field2;public java.lang.String field3; java.lang.String field4;==========本类或则实现的接口或者父类的public的属性==========public java.lang.String field3;public java.lang.Integer pf3;*/

从上面的运行结果可知:
Class.getDeclaredFields()方法放回的是当前类里面的所有属性。Class.getFields()返回的是当前类已及父类和实现的接口的所有public修饰的属性。

6.获取某个类的全部方法

private void testtttt(){}/** * 获取某个类的全部方法 * @throws Exception */@Testpublic void test6() throws Exception {    Class<?> clazz = Class.forName("test.ReflectTest");    Method[] method = clazz.getMethods();//获取本类以及继承类\实现接口的所有public修饰的方法    //Method[] method = clazz.getDeclaredMethods();//只获取本类的所有方法    for(int i=0; i<method.length; i++){        int mod = method[i].getModifiers();        String modifier = Modifier.toString(mod);//获取方法修饰符        Class<?> returnType = method[i].getReturnType();//获取返回值类型        Class<?> [] para = method[i].getParameterTypes();//获取参数类型        System.out.print(modifier + " ");        System.out.print(returnType.getName() + "  ");        System.out.print(method[i].getName() + " ");        System.out.print("(");        for (int j = 0; j < para.length; ++j) {            System.out.print(para[j].getName() + " " + "arg" + j);            if (j < para.length - 1) {                System.out.print(",");            }        }        Class<?> exce[] = method[i].getExceptionTypes();        if (exce.length > 0) {            System.out.print(") throws ");            for (int k = 0; k < exce.length; ++k) {                System.out.print(exce[k].getName() + " ");                if (k < exce.length - 1) {                    System.out.print(",");                }            }        } else {            System.out.print(")");        }        System.out.println();    }}

1)clazz.getMethods();//获取本类以及继承类\实现接口的所有public修饰的方法
//执行结果是:
这里写图片描述
可知,里面都是public修饰的方法,private修饰的testtttt()并没有打印出来;

2)clazz.getDeclaredMethods();//只获取本类的所有方法
//执行结果是:
这里写图片描述
本类的所有方法都被获取到了。

7.通过反射机制调用某个类的方法

public void reflect1() {    System.out.println("Java 反射机制 - 调用某个类的方法1.");}public void reflect2(int age, String name) {    System.out.println("Java 反射机制 - 调用某个类的方法2.");    System.out.println("age -> " + age + ". name -> " + name);}/** * 通过反射机制调用某个类的方法 */@Testpublic void test7() throws Exception{    Class<?> clazz = Class.forName("test.ReflectTest");    // 调用TestReflect类中的reflect1方法    Method method = clazz.getMethod("reflect1");    method.invoke(clazz.newInstance());    //output: Java 反射机制 - 调用某个类的方法1.    // 调用TestReflect的reflect2方法    method = clazz.getMethod("reflect2", int.class, String.class);    method.invoke(clazz.newInstance(), 20, "张三");    // Java 反射机制 - 调用某个类的方法2.    //output:  age -> 20. name -> 张三}

8.通过反射机制操作某个类的属性

private String proprety = null;/** * 通过反射机制操作某个类的属性 */@Testpublic void test8() throws Exception{    Class<?> clazz = Class.forName("test.ReflectTest");    Object obj = clazz.newInstance();    // 可以直接对 private 的属性赋值    Field field = clazz.getDeclaredField("proprety");    field.setAccessible(true);    field.set(obj, "Java反射机制");    System.out.println("proprety="+field.get(obj));}

所有源代码的github地址

0 0
原创粉丝点击