java反射机制总结

1.概念

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

该图转载于其他帖子

该图转载于其他帖子,http://blog.csdn.net/sinat_38259539/article/details/71799078

2.使用反射

2.1. 通过反射获取类的class对象
有三种获取class对象的方式来使用反射 1.通过对象Object的getClass()方法
通过已经实例化的对象的静态方法getClass()来实现
 public final native Class<?> getClass();
2.通过类的静态class属性
任何类都有一个静态属性class,通过调用它来实现
3.通过Class类的静态方法forName(String className)
这是Class类forName的代码块,他将抛出一个ClassNotFoundException ,要求使用者继续抛出或者捕捉
  public static Class<?> forName(String className)
                throws ClassNotFoundException {
public class HelloReflex {
    public static void main(String[] args) {
        Student student = new Student();
        //第一種方式,通過已經實例化的對象的getClass()方法得到該對象的Class對象
        Class<Student> studentClass1=(Class<Student>) student.getClass();
        //第二種方式,通過該類的靜態屬性class得到該類的Class對象
        Class<Student> studentClass2 = Student.class;
        //第三種方式,通過Class類的靜態方法,forName(String className)獲取,記住,參數要傳入全類名
        Class<Student> studentClass3 = null;
        try {
            studentClass3 = (Class<Student>) Class.forName("reflex.Student");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //打印class的全類名
        System.out.println(studentClass1.getName());
        //確認兩者是否為同一個Class對象
        System.out.println(studentClass1==studentClass2);
        System.out.println(studentClass2==studentClass3);

    }
}
2.2. 通过反射获取类的构造器

通过反射,可以获取类的构造器,包括有访问范围限制的

这是关于Student类的一些信息

public class Student {
    private String name;
    private int age;
    //默认构造器
     public Student() {
         super();
         System.out.println("你调用了默认构造器");
     }
     //私有构造器,传入单参
     private Student(int age){
         System.out.println("你调用了私有构造器,传入了参数 "+age);
     }
     //公开构造器,传入单参
    public Student(String name) {
        super();
        this.name = name;
        System.out.println("你调用了公开构造器,传入了参数 "+name);
    }
    //受保护构造器,传入多参数
    protected Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
        System.out.println("你调用了受保护构造器,传入了参数 "+name+","+age);
    }
}

关于通过Class类获取构造器的一些方法

    //该方法会得到所有构造器(私有,受保护,默认,公开),将会抛出一个SecurityException,返回一个Constructor数组
    public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
    //该方法会得到所有公开的构造器,与上面的方法结构类似
    public Constructor<?>[] getConstructors() throws SecurityException {
    //该方法能获取单个任何访问范围的构造器,传入一个构造器参数类型的Class对象
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
    //该方法能获取单个“公开”的构造器,传入一个构造器参数类型的Class对象
    public Constructor<T> getConstructor(Class<?>... parameterTypes)

将构造器实例化的方法

    //该方法是Constructor类的方法,在通过上面的方式得到构造器后,可以通过这个方法把构造器实例化
    //该方法参数需要传入你获取的构造器的初始参数,如果无,传null,将抛出异常,返回T类型
     public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
    {

代码示例

public class HelloReflex {
    public static void main(String[] args) throws Exception{
        Class<Student> stuClass = (Class<Student>) Class.forName("reflex.Student");

        //获取所有公开构造器
        Constructor<Student>[] allPublicConstructors = (Constructor<Student>[]) stuClass.getConstructors();
        //获取所有访问范围构造器
        Constructor<Student>[] allConstructors = (Constructor<Student>[]) stuClass.getDeclaredConstructors();
        //获取单个公开构造器,这里获取默认构造器
        Constructor<Student> defaultConstructor = stuClass.getConstructor(null);
        //获取单个构造器,这里获取int类型为参数的构造器
        Constructor<Student> intParameterConstructor = stuClass.getDeclaredConstructor(int.class);
        //打印每个构造器
        System.out.println("------所有公开构造器--------");
        for(Constructor<Student> publicConstructor:allPublicConstructors){
            System.out.println(publicConstructor);
        }
        System.out.println("------所有访问范围构造器--------");
        for(Constructor<Student> constructor:allConstructors){
            System.out.println(constructor);
        }
        System.out.println("------默认构造器--------");
        System.out.println(defaultConstructor);
        System.out.println("------获取int类型为参数的构造器-----");
        System.out.println(intParameterConstructor);
        /*这里会抛出一个错误java.lang.IllegalAccessException: Class reflex.HelloReflex can not access a member of class reflex.Student with modifiers "private"
        构造器实例化的话会受访问范围的限制,如果要忽视访问修饰符,要使用setAccessible()方法进行设置,传入true参数,再进行实例化*/
        intParameterConstructor.setAccessible(true);
        Student s = intParameterConstructor.newInstance(29);
        //这里初始化默认构造器,传入参数为null
        Student stu = defaultConstructor.newInstance(null);
    }
}   
运行结果
——所有公开构造器——–
public reflex.Student(java.lang.String)
public reflex.Student()
——所有访问范围构造器——–
protected reflex.Student(java.lang.String,int)
public reflex.Student(java.lang.String)
private reflex.Student(int)
public reflex.Student()
——默认构造器——–
public reflex.Student()
——获取int类型为参数的构造器—–
private reflex.Student(int)
你调用了私有构造器,传入了参数 29
你调用了默认构造器
2.3. 通过反射获取类的字段
    //获取类的某个"public"修饰的字段,传入参数为字段名,将会抛出异常,返回Field对象
    public Field getField(String name)
        throws NoSuchFieldException, SecurityException 
    //获取类的某个任何访问修饰符修饰的字段,传入参数为字段名,将会抛出异常,返回Field对象
    public Field getDeclaredField(String name)
        throws NoSuchFieldException, SecurityException {
     //获取类的所有"public"修饰的字段,返回Field数组
     public Field[] getFields() throws SecurityException {
     //获取类的所有(任何访问修饰符修饰)的字段,返回Field数组
      public Field[] getDeclaredFields() throws SecurityException {

设置字段的方法

//该方法是Field类的方法,通过这个方法可以设置字段的值。第一个传入参数是该字段所属的对象,第二个参数是值
//由于一个类可以有多个Object,但只能有一个Class,通过反射得到的Class根植与类,所以与对象有区分,设置值要根植于对象
public void set(Object obj, Object value)
        throws IllegalArgumentException, IllegalAccessException

获取字段值的方法

//通过这个方法可以获取字段的值。传入参数是该字段所属的对象
 public Object get(Object obj)
        throws IllegalArgumentException, IllegalAccessException
    {

下面开始代码演示,首先是Student的代码块

public class Student {
    private String name;
    public int age;
    protected String Grade;
    String address;


    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", Grade=" + Grade + ", address=" + address + "]";
    }
}

主程序代码块

public class HelloReflex {
    public static void main(String[] args) throws Exception {
        Class<Student> stuClass = (Class<Student>) Class.forName("reflex.Student");

        // 获取所有公开字段
        Field[] allPublicFields = stuClass.getFields();
        // 获取所有访问范围字段
        Field[] allFields = stuClass.getDeclaredFields();
        // 获取单个公开字段,这里获取age字段
        Field ageField = stuClass.getField("age");
        // 获取单个所有访问范围字段字段,这里获取name字段
        Field nameField = stuClass.getDeclaredField("name");
        // 打印每个字段
        System.out.println("------所有公开字段--------");
        for (Field publicField : allPublicFields) {
            System.out.println(publicField);
        }
        System.out.println("------所有访问范围字段--------");
        for (Field field : allFields) {
            System.out.println(field);
        }
        System.out.println("------age字段--------");
        System.out.println(ageField);
        System.out.println("------name字段-----");
        System.out.println(nameField);

        //设置字段的值(公开)
        Student s = stuClass.getConstructor(null).newInstance(null);
        ageField.set(s, 11);
        System.out.println("-----s对象---");
        System.out.println(s.toString());
        System.out.println("-----s对象的age字段---");
        System.out.println(ageField.get(s));
        //如果是有访问权限的呢?如private,将会抛出一个异常java.lang.IllegalAccessException: Class reflex.HelloReflex can not access a member of class reflex.Student with modifiers "private"
        //如果要忽视访问修饰符,要使用setAccessible()方法进行设置,传入true参数,
        nameField.setAccessible(true);
        nameField.set(s, "黄明");
        System.out.println("-----s对象---");
        System.out.println(s.toString());
        System.out.println("-----s对象的name字段---");
        System.out.println(nameField.get(s));
    }
}
运行结果
——所有公开字段——–
public int reflex.Student.age
——所有访问范围字段——–
private java.lang.String reflex.Student.name
public int reflex.Student.age
protected java.lang.String reflex.Student.Grade
java.lang.String reflex.Student.address
——age字段——–
public int reflex.Student.age
——name字段—–
private java.lang.String reflex.Student.name
—–s对象—
Student [name=null, age=11, Grade=null, address=null]
—–s对象的age字段—
11
—–s对象—
Student [name=黄明, age=11, Grade=null, address=null]
—–s对象的name字段—
黄明
2.4. 通过反射获取类的方法

关于通过Class类获取方法的一些方法

    //该方法会得到所有方法(私有,受保护,默认,公开)包括其父类,将会抛出一个SecurityException,返回一个Method数组
    public Method[] getDeclaredMethods() throws SecurityException {
    //该方法会得到所有公开的方法,与上面的方法结构类似
     public Method[] getMethods() throws SecurityException {
    //该方法能获取单个任何访问范围的方法,传入该方法的方法名,参数类型的Class对象(由于方法可以重载)
      public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
    //该方法能获取单个“公开”的方法,传入该方法的方法名,参数类型的Class对象
     public Method getMethod(String name, Class<?>... parameterTypes)

通过Class类获取方法的调用

    //该方法基于Method类,第一个传入参数是方法所在的对象,第二个乃至更多是要调用的方法需要传入的参数
    public Object invoke(Object obj, Object... args)
     throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {

实例
先看下Student类的结构

public class Student {

    public void sayHello(String name){
        System.out.println(name+",你好");
    }
    protected int add(int i){
        System.out.println("调用了add方法,参数为"+i);
        return ++i;
    }
    void walk(){
        System.out.println("走路中....");
    }
    private void lecture(String name,int audienceNum){
        System.out.println(name+"在演讲,观众有"+audienceNum+"人");
    }
}

主程序

public class HelloReflex {
    public static void main(String[] args) throws Exception {
        Class<Student> stuClass = (Class<Student>) Class.forName("reflex.Student");

        // 获取所有公开方法
        Method[] allPublicMethods = stuClass.getMethods();
        // 获取所有访问范围方法
        Method[] allMethods = stuClass.getDeclaredMethods();
        // 获取单个公开方法,这里获取sayHello方法
        Method sayHelloMethod = stuClass.getMethod("sayHello",String.class);
        // 获取单个所有访问范围方法,这里获取lecture方法
        Method lectureField = stuClass.getDeclaredMethod("lecture",String.class,int.class);
        // 打印每个方法
        System.out.println("------所有公开方法--------");
        for (Method publicMethod : allPublicMethods) {
            System.out.println(publicMethod);
        }
        System.out.println("------所有访问范围方法--------");
        for (Method method : allMethods) {
            System.out.println(method);
        }
        System.out.println("------sayHelloMethod--------");
        System.out.println(sayHelloMethod);
        System.out.println("------lectureField-----");
        System.out.println(lectureField);

        //设置字段的值(公开)
        Student s = stuClass.getConstructor(null).newInstance(null);
        sayHelloMethod.invoke(s, "李明");
        //如果是有访问权限的呢?如private,将会抛出一个异常java.lang.IllegalAccessException: Class reflex.HelloReflex can not access a member of class reflex.Student with modifiers "private"
        //如果要忽视访问修饰符,要使用setAccessible()方法进行设置,传入true参数,
        lectureField.setAccessible(true);
        lectureField.invoke(s, "李明",15);
    }
}
运行结果
——所有公开方法——–
public void reflex.Student.sayHello(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
——所有访问范围方法——–
protected int reflex.Student.add(int)
public void reflex.Student.sayHello(java.lang.String)
private void reflex.Student.lecture(java.lang.String,int)
void reflex.Student.walk()
——sayHelloMethod——–
public void reflex.Student.sayHello(java.lang.String)
——lectureField—–
private void reflex.Student.lecture(java.lang.String,int)
李明,你好
李明在演讲,观众有15人

总结
该帖子是我关于反射机制的总结,为了更方便自己理解,学习过程中参考了http://blog.csdn.net/sinat_38259539/article/details/71799078
这张帖子

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值