Java反射总结

这篇博客对于Java中的反射机制,做一些总结,有不完善的地方再继续补充。

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

二. 功能
在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

三. 使用
1.首先我们想通过反射获取类或者接口的属性和方法,就必须获得这个类或者接口的Class对象。有以下三种方法:
1).使用使用Class类的静态方法 Class.forName(String name)
2).类的语法,Stirng.class
3).使用类的实例化的getClass方法 obj.getClass();

2.获取类的构造器

1).public Constructor<?>[] getConstructors()      返回类中所有的public构造器集合,默认构造器的下标为0
2).public Constructor<T> getConstructor(Class<?>... parameterTypes)   返回指定public构造器,参数为构造器参数类型集合
3).public Constructor<?>[] getDeclaredConstructors()  返回类中所有的构造器,包括私有
4).public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器

3.获取类的成员变量

1).public Field getDeclaredField(String name)  获取任意指定名字的成员变量
2).public Field[] getDeclaredFields()             获取所有的成员变量
3).public Field getField(String name)           获取任意public成员变量
4).public Field[] getFields()                          获取所有的public成员变量
Field 重要方法set(Object obj, Object value),将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

4.获取类的方法

1).public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法
2).public Method[] getDeclaredMethods()  获取所有的方法
3).public Method[] getMethods()    获取所有的共有方法的集合
4).public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法
Method重要方法invoke(Object obj ,Object…parmasType),调用由此 Method 对象表示的底层方法。

getMethods()和getDeclaredMethods()区别
getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。
getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。

示例代码:
1. StudentBean类

package com.li.reflection;

public class StudentBean {

    public String id;
    public String name;
    public String sex;
    public String age;
    private String height;

    public StudentBean() {
        // TODO Auto-generated constructor stub
    }

    public StudentBean(String id) {
        super();
        this.id = id;
    }

    public StudentBean(String id, String name, String sex, String age) {
        super();
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getHeight() {
        return height;
    }

    public void setHeight(String height) {
        this.height = height;
    }


    @Override
    public String toString() {
        return "StudentBean [id=" + id + ", name=" + name + ", sex=" + sex
                + ", age=" + age + ", height=" + height + "]";
    }

    private void goToSchool(){
        System.out.println("Go to School");
    }

    public void eat(String food){
        System.out.println("eat "+food);
    }

    public boolean finishHomework(){
        System.out.println("finishHomework?");
        return true;
    }
}

2.使用
package com.li.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionDemo {

    public static void main(String[] args) throws Exception{

        /**
         * 想要通过反射来获取类或者接口的属性和方法,首先获得这个类或者接口的Class对象
         */
        Class<?> cls;

        System.out.println("------------------Get Class------------------");
        //1.Class对象的静态方法    Class.forName(包名+类名)
        cls = Class.forName("com.li.reflection.StudentBean");
        //2.获得接口的静态方法   eg String.class
//      cls = StudentBean.class;
        //3.通过类或者接口的实例化对象 getClass()方法
//      StudentBean student = new StudentBean();
//      cls = student.getClass();
        System.out.println(cls.toString()); 
//输出: class com.li.reflection.StudentBean       

        System.out.println("------------------Get Constructor------------------");
        getConstructor(cls);

        System.out.println("------------------Get Field------------------");
        getField(cls);

        System.out.println("------------------Get Method------------------");
        getMethod(cls);
    }

    /**
     * 获得构造器创建对象
     */
    public static void getConstructor(Class<?> cls) throws Exception{
        //获得构造器
        Constructor<?>[] constructors = cls.getConstructors();
//      Constructor<?>[] constructors = cls.getDeclaredConstructors();
        for(Constructor cts : constructors){
            System.out.println(cts.getName()+"-->"+cts.toString());
        }
//输出:
//      com.li.ref.StudentBean-->public com.li.ref.StudentBean()
//      com.li.ref.StudentBean-->public com.li.ref.StudentBean(java.lang.String,java.lang.String,java.lang.String,java.lang.String)
//      com.li.ref.StudentBean-->public com.li.ref.StudentBean(java.lang.String)

        //获得默认无参构造方法
        Constructor ct = cls.getDeclaredConstructor(null);
        System.out.println(ct.toString());
        //获得只有一个参数的构造方法
        Constructor ct1 = cls.getDeclaredConstructor(new Class[]{String.class});
        System.out.println(ct1.toString()); //public com.li.ref.StudentBean(java.lang.String)
        //获得含有四个参数的构造方法
        Constructor ct4 = cls.getDeclaredConstructor(new Class[]{String.class, String.class, String.class, String.class});
        System.out.println(ct4.toString());

        //需要含有默认无参的构造方法
        StudentBean stu = (StudentBean) cls.newInstance();
        System.out.println(stu.toString());  //StudentBean [id=null, name=null, sex=null, age=null, height=null]
        //创建含一个参数的对象
        StudentBean st = (StudentBean) ct1.newInstance("25");
        System.out.println(st.toString());  //StudentBean [id=25, name=null, sex=null, age=null, height=null]
        //创建含四个参数的对象
        StudentBean st4 = (StudentBean) ct4.newInstance("1001","LiLei","male","16");
        System.out.println(st4.toString());  //StudentBean [id=1001, name=LiLei, sex=male, age=16, height=null]
    }


    /**
     * 获得类的属性
     */
    public static void getField(Class<?> cls) throws Exception{
        Field[] fields = cls.getDeclaredFields();
        for(Field fd : fields){
            fd.setAccessible(true);
            System.out.println(fd.toString());
        }
//输出:       
//      public java.lang.String com.li.ref.StudentBean.id
//      public java.lang.String com.li.ref.StudentBean.name
//      public java.lang.String com.li.ref.StudentBean.sex
//      public java.lang.String com.li.ref.StudentBean.age
//      private java.lang.String com.li.ref.StudentBean.height

        Field field = cls.getDeclaredField("id");
        System.out.println(field.toString());   //public java.lang.String com.li.ref.StudentBean.id
        StudentBean stu = (StudentBean) cls.newInstance();
        field.set(stu, "10010");
        System.out.println(stu.toString()); //StudentBean [id=10010, name=null, sex=null, age=null, height=null]
    }



    /**
     * 获取方法
     */
    public static void getMethod(Class<?> cls) throws Exception{
        Method[] methods = cls.getDeclaredMethods();
        for(Method method : methods){
            System.out.println(method.getName());
        }

        Method md = cls.getDeclaredMethod("goToSchool");
        md.setAccessible(true);
        StudentBean stu = (StudentBean) cls.newInstance();
        md.invoke(stu);

        Method method = cls.getDeclaredMethod("eat", String.class);
        method.invoke(stu, "vegetable");    //输出:eat vegetable
    }
}

坑爹的编辑器,看起来有点乱,聪明如你,肯定能看明白。

posted on 2016-12-23 17:17  lishbo  阅读(118)  评论(0编辑  收藏  举报