Java反射

一、Java反射概述

        Java反射机制指的是在Java程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法;对于给定的一个对象,都能够调用它的任意一个属性和方法。这种动态获取类的内容以及动态调用对象的方法称为反射机制。

       Java的反射机制允许编程人员在对类未知的情况下,获取类相关信息的方式变得更加多样灵活,调用类中相应方法,是Java增加其灵活性与动态性的一种机制。

二、Java反射的使用

  1、想要使用Java反射,就必须先获取类的字节码文件对象,而获取字节码文件对象的方式有如下三种:

      (1)Class.forName("类的全路径");

      (2)对象.getClass();  其中包括 this.getClass()

      (3)类型.class;

  2、通过Java反射获取构造方法并调用

        2.1、创建一个Student实体类,用于反射调用

package com.reflex.pojo;

public class Student {

    //无参数的公开构造方法
    public Student(){
        System.out.println("Student类的无参数的公开构造方法被调用");
    }

    //带有一个参数的公开构造方法
    public Student(String name){
        System.out.println("Student类带有一个参数的公开构造方法被调用,name="+name);
    }

    //带有两个参数的公开构造方法
    public Student(String name, Integer age){
        System.out.println("Student类带有两个参数的公开构造方法被调用,name="+name+" age="+age);
    }

    //带有一个参数的私有构造方法
    private Student(Integer age){
        System.out.println("Student类带有一个参数的私有构造方法被调用,age="+age);
    }

}

     

        2.2、获取构造方法的测试类

package com.reflex.program;

import java.lang.reflect.Constructor;

public class MyConstructor {

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

        System.out.println("------------------获取无参的公开构造方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazz = Class.forName("com.reflex.pojo.Student");
        //2、获取无参数的公开构造方法
        Constructor<?> constructor = clazz.getConstructor();
        //3、创建对象实例并调用无参数的公开构造方法
       constructor.newInstance();


        System.out.println("------------------带有一个参数的公开构造方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzForOne = Class.forName("com.reflex.pojo.Student");
        //2、获取带有一个参数的公开构造方法
        Constructor<?> constructorForOne = clazzForOne.getConstructor(String.class);
        //3、创建对象实例并调用带有一个参数的公开构造方法
        constructorForOne.newInstance("张三");


        System.out.println("------------------带有两个参数的公开构造方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzForTwo = Class.forName("com.reflex.pojo.Student");
        //2、获取带有两个参数的公开构造方法
        Constructor<?> constructorForTwo = clazzForTwo.getConstructor(String.class,Integer.class);
        //3、创建对象实例并调用带有两个参数的公开构造方法
        constructorForTwo.newInstance("李四",18);


        System.out.println("------------------带有一个参数的私有构造方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzForPrivate = Class.forName("com.reflex.pojo.Student");
        //2、获取带有一个参数的私有构造方法 (注意:获取私有构造方法的方法名称是 getDeclaredConstructor)
        Constructor<?> constructorForPrivate = clazzForPrivate.getDeclaredConstructor(Integer.class);
        //3、设置带有一个参数的私有构造方法的访问权限
        constructorForPrivate.setAccessible(true);
        //4、创建对象实例并调用带有一个参数的私有构造方法
        constructorForPrivate.newInstance(18);

    }
}

         2.3、测试输出结果如下:

------------------获取无参的公开构造方法------------------
Student类的无参数的公开构造方法被调用

------------------带有一个参数的公开构造方法------------------
Student类带有一个参数的公开构造方法被调用,name=张三

------------------带有两个参数的公开构造方法------------------
Student类带有两个参数的公开构造方法被调用,name=李四 age=18

------------------带有一个参数的私有构造方法------------------
Student类带有一个参数的私有构造方法被调用,age=18

3、通过Java反射获取方法并调用

      3.1、创建一个Student实体类,用于反射调用

package com.reflex.pojo;

public class Student {

    //无参数的公开构造方法
    public Student(){}

    //无参数的showMessage方法
    public void showMessage(){
        System.out.println("Student类无参数的showMessage方法被调用");
    }

    //带有一个参数的showName方法
    public void showName(String name){
        System.out.println("Student类带有一个参数的showName方法被调用,name="+name);
    }

    //带有两个参数的showNameAndAge方法
    public void showNameAndAge(String name, Integer age){
        System.out.println("Student类带有两个参数的showNameAndAge方法被调用,name="+name+" age="+age);
    }

    //带有一个参数的私有showAge方法
    private void showAge(Integer age){
        System.out.println("Student类带有一个参数的私有showAge方法被调用,age="+age);
    }

    //Student类的main方法
    public static void main(String[] args) {
        System.out.println("Student类的main方法被调用");
    }

}

      3.2、获取方法的测试类

package com.reflex.program;

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

public class MyMethod {

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

        System.out.println("------------------获取无参的showMessage方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazz = Class.forName("com.reflex.pojo.Student");
        //2、获取无参数的公开构造方法
        Constructor<?> constructor = clazz.getConstructor();
        //3、创建对象实例并调用无参数的公开构造方法
        Object object = constructor.newInstance();
        //4、获取无参数的showMessage方法
        Method showMessage = clazz.getMethod("showMessage");
        //5、调用showMessage方法
        showMessage.invoke(object);

        
        System.out.println("------------------获取带有一个参数的showName方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzForOne = Class.forName("com.reflex.pojo.Student");
        /*
         * Constructor<?> constructorForOne = clazzForOne.getConstructor();
         * Object object = constructorForOne.newInstance();
         * 等价于
         * Object object = clazzForOne.newInstance();
         */
        //2、创建对象实例并调用无参的构造方法
        Object objectForOne = clazzForOne.newInstance();
        //3、获取带有一个参数的showName方法 (第一个参数为方法名,后面的参数为参数的字节码)
        Method showName = clazzForOne.getMethod("showName",String.class);
        //4、调用showName方法 (第一个参数为调用该方法的对象,后面的参数为方法的实参)
        showName.invoke(objectForOne,"张三");

        
        System.out.println("------------------获取带有两个参数的showNameAndAge方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzForTwo = Class.forName("com.reflex.pojo.Student");
        //2、创建对象实例并调用无参的构造方法
        Object objectForTwo = clazzForTwo.newInstance();
        //3、获取带有两个参数的showNameAndAge方法
        Method showNameAndAge = clazzForTwo.getMethod("showNameAndAge",String.class,Integer.class);
        //4、调用showNameAndAge方法
        showNameAndAge.invoke(objectForTwo,"张三",18);

        
        System.out.println("------------------获取带有一个参数的私有showAge方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzForPrivate = Class.forName("com.reflex.pojo.Student");
        //2、创建对象实例并调用无参的构造方法
        Object objectForPrivate = clazzForPrivate.newInstance();
        //3、获取带有一个参数的私有showAge方法 (注意:获取私有方法的方法名称是 getDeclaredMethod)
        Method showAge = clazzForPrivate.getDeclaredMethod("showAge",Integer.class);
        //4、设置带有一个参数的私有showAge方法的访问权限
        showAge.setAccessible(true);
        //5、调用showAge方法
        showAge.invoke(objectForPrivate,18);


        System.out.println("------------------获取Student类的静态main方法------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzFoMain = Class.forName("com.reflex.pojo.Student");
        //2、获取Student类的静态main方法
        Method main = clazzFoMain.getMethod("main",String[].class);

        /*
         *调用Student类的静态main方法 (由于main方法是静态方法,所以第一个参数可以给对象,也可以给null)
         *另一种调用方式  main.invoke(null,new Object[]{new String[]{"a","b","c"}});
         */
        main.invoke(null,(Object)new String[]{"a","b","c"});
        
    }

}

      3.3、测试输出结果如下:

------------------获取无参的showMessage方法------------------
Student类无参数的showMessage方法被调用

------------------获取带有一个参数的showName方法------------------
Student类带有一个参数的showName方法被调用,name=张三

------------------获取带有两个参数的showNameAndAge方法------------------
Student类带有两个参数的showNameAndAge方法被调用,name=张三 age=18

------------------获取带有一个参数的私有showAge方法------------------
Student类带有一个参数的私有showAge方法被调用,age=18

------------------获取Student类的静态main方法------------------
Student类的main方法被调用

4、通过Java反射获取字段并打印

      4.1、创建一个Student实体类,用于反射调用

package com.reflex.pojo;

public class Student {

   private String name;

   private static Integer age;

    public String getName() {
        return name;
    }

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

    public static Integer getAge() {
        return age;
    }

    public static void setAge(Integer age) {
        Student.age = age;
    }
}

     

      4.2、获取字段的测试类

package com.reflex.program;

import com.reflex.pojo.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class MyField {

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

        System.out.println("------------------获取私有name字段------------------");
        //1、获取类的字节码文件对象
        Class<?> clazz = Class.forName("com.reflex.pojo.Student");
        //2、获取无参数的公开构造方法
        Constructor<?> constructor = clazz.getConstructor();
        //3、创建对象实例并调用无参数的公开构造方法
        Student object = (Student)constructor.newInstance();
        //4、获取私有name字段 (注意:获取私有字段的方法名称是 getDeclaredField)
        Field name = clazz.getDeclaredField("name");
        //5、设置私有name字段的访问权限
        name.setAccessible(true);
        //6、为私有字段name赋值 (第一个参数为调用该字段的对象,后面的参数为字段的值)
        name.set(object,"张三");
        //7、输出该字段的值
        System.out.println("私有name字段的值为:"+object.getName());


        System.out.println("------------------获取私有静态age字段------------------");
        //1、获取类的字节码文件对象
        Class<?> clazzForAge = Class.forName("com.reflex.pojo.Student");
        //1、获取私有静态age字段
        Field age = clazzForAge.getDeclaredField("age");
        //5、设置私有静态age字段的访问权限
        age.setAccessible(true);
        //6、为私有静态字段age赋值 (由于age字段是静态字段,所以第一个参数可以给对象,也可以给null)
        age.set(null,18);
        //7、输出该字段的值
        System.out.println("私有静态age字段的值为:"+Student.getAge());

    }

}

      4.3、测试输出结果如下:

------------------获取私有name字段------------------
私有name字段的值为:张三

------------------获取私有静态age字段------------------
私有静态age字段的值为:18

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值