Java反射机制起步

反射:

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

         反射常用对象的概述:

                   Class:

                            --Class类的实例表示正在运行的java应用程序中的类和接口

                   Constructor:

                            --关于类的单个构造方法的信息以及对它的访问权限

                   Filed:

                            --提供有关类或接口的单个字段的信息,以及对它的动态访问权限。

                   Method:

                            --提供关于类或接口上单独某个方法的信息


测试对象(以下eg例子的测试对象):

public class Person {
    public String name;
    private int age;

    public Person(){
        super();
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

//    public String getName() {
//        return name;
//    }
//
//    public void setName(String name) {
//        this.name = name;
//    }
//
//    public int getAge() {
//        return age;
//    }
//
//    public void setAge(int age) {
//        this.age = age;
//    }

    public void eat(){
        System.out.println("吃.....");
    }

    public void speak(){
        System.out.println(name + ":" + age);
    }

    private void run(){
        System.out.println("跑。。。。。");
    }

    private String say(String name){
        return "Hello " + name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


Class类:Class类代表某个类的字节码,并提供了加载字节码的方法:

         Java.lang.Class类用于表示一个类的字节码(.class)文件

         如何得到某个class文件对应的Class对象:

            1、  已知类和对象的情况下:

                a)        类名.class

                b)        对象.getClass() ---Object类提供的

            2、  未知类和对象的情况下:

                a)        Class.forName(“包名.类名”)

                            forName方法用于加载类字节码到内存中,并封装成一个Class对象

eg:

importorg.junit.jupiter.api.Test;

public classClassTest {

    @Test

    /**

     * Class对象的获取:

     */

    public void demo(){

        //1、类名.class

        Class clazz1 = Person.class;

        //2、对象.getClass()

        Person p = new Person();

        Class clazz2 = p.getClass();

        try {

            //3、Class.forName("包名.类名");

            Class clazz3 =Class.forName("com.luyue.classtest.Person");//推荐使用

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }

    }

}


Constructor类:

         Constructor类的实例对象代表类的一个构造方法

            1、  得到某个类所有的构造方法

                Constructor[] constructors = Class.forName(“java.lang.String”).getConstructors();

            2、  得到指定的构造方法并调用:

                Constructorconstructor = Class.forName(“java.lang.String”).getConstructor(String.class);

                String str = (String)constructor.newInstance(“abc”);

            3、  Class类的newInstance()方法用来调用类的默认构造方法

                String obj = (String)Class.forName(“java.lang.String”).newInstance();

Eg:

importorg.junit.jupiter.api.Test;

importjava.lang.reflect.Constructor;

importjava.lang.reflect.InvocationTargetException;

public classConstructorTest {

    @Test

    /**

     * 获得无参构造方法

     */

    public void demo() throws Exception{

        //先获得Class对象

        Class clazz =Class.forName("com.luyue.classtest.Person");

        //获得Constructor对象

        Constructor constructor =clazz.getConstructor();//无参构造不需要参数

        Person person =(Person)constructor.newInstance();//实例化一个对象

        person.eat();

    }

    @Test

    /**

     * 获得有参数的构造方法

     */

    public void demo1() throws Exception {

        //一样先获得Class对象

        Class clazz =Class.forName("com.luyue.classtest.Person");

        //获得Constructor对象

        Constructor constructor =clazz.getConstructor(String.class, Integer.class);

        //实例化一个对象

        Person person =(Person)constructor.newInstance("我", 11);

        person.eat();

        person.speak();

    }

}


Field类:

         Field类代表某个类中的一个成员变量,并提供动态的访问权限

         Field对象的获得:

            1、  得到所有的成员变量:

                    a)        Field[] fields = claszz.getFields();//取得所有public属性(包括父类继承)

                    b)        Field[] fields = claszz.getDeclaredFields();//取得所有声明的属性

            2、  得到指定的成员变量:

                    a)        Field name = claszz.getField(“name”);

                    b)        Field name = claszz.getDeclaredField(“name”);

        field.setAccessible(Boolean);//设置Filed变量是否可以访问,设置为true,那么私有属性可以被访问

        3、  Field变量值的读取和设置

                --field.get(obj)//读取

                --field.set(obj,value);//设置

Eg:

importorg.junit.jupiter.api.Test;

importjava.lang.reflect.Field;

publicclass FieldTest {

    @Test

    /**

     * 测试共有属性

     */

    public void demo() throws Exception {

        //获取Class

        Class clazz = Class.forName("com.luyue.classtest.Person");

        //获得公有属性

        Field field =clazz.getField("name");

        //操作属性

        //设置值

        Person p = (Person)clazz.newInstance();

        field.set(p, "李四");

        System.out.println(p);

        //获得值

        Object obj = field.get(p);

        System.out.println(obj);

    }

    @Test

    /**

     * 测试私有属性

     */

    public void demo2() throws Exception  {

        //一样先获取Class

        Class clazz =Class.forName("com.luyue.classtest.Person");

        //获得Field

        Field field =clazz.getDeclaredField("age");

        //操作属性,这里有个前提:操作私有属性之前先要设置field变量是否可以被访问

        Person p = (Person)clazz.newInstance();

        field.setAccessible(true);//设置field可以被访问

        //设置值

        field.set(p, 20);

        System.out.println(p);

        //获取值

        Object obj = field.get(p);

        System.out.println(obj);

    }

}


Method类:

         代表某个类的一个成员方法

         Method对象的获得

         ---获得所有方法:

                   getDeclaredMethods()//获得所有方法,无论公有私有

                   getMethods()         //获得所有公有的方法

         ---获得指定的方法

                   getDeclaredMethod(Stringname, Class<?>…parameterTypes)

                   getMethod(Stringname, Class<?>…parameterTypes)

         通过反射执行方法:

                   invoke(Objectobj, Object..args)

         eg:

importorg.junit.jupiter.api.Test;

import java.lang.reflect.Method;

public class MethodTest {

   @Test

   /**

    * 测试无参公有方法

    */

   public void demo1() throws Exception{

       //获取Class

       Class clazz = Class.forName("com.luyue.classtest.Person");

       Person p = (Person)clazz.newInstance();

       //获取Method

       Method method = clazz.getMethod("eat");

       //执行

       method.invoke(p);

    }

   @Test

   /**

    * 测试无参私有方法

    */

   public void demo2() throws Exception{

       //获取Class

       Class clazz = Class.forName("com.luyue.classtest.Person");

       Person p = (Person)clazz.newInstance();

       //过得Method

       Method method = clazz.getDeclaredMethod("run");

       //设置访问权限

       method.setAccessible(true);

       //执行

       method.invoke(p);

    }

   @Test

   /**

    * 测试有参私有方法,有参公有方法一样

    */

   public void demo3() throws Exception{

       //获得Class

       Class clazz = Class.forName("com.luyue.classtest.Person");

       Person p = (Person)clazz.newInstance();

       //获得Method

       Method method = clazz.getDeclaredMethod("say", String.class);

       //设置访问权限

       method.setAccessible(true);

       //执行

       Object obj = method.invoke(p, "辛巴");

       System.out.println(obj);

    }

}


补充一点:如果方法参数中有数组参数,需要稍微变一下

因为:

invoke方法的第二个参数接受的是Object数组,并把数组的每一个元素作为方法的一个参数。所以如果某一个参数为数组,要在外面用newObject[]{}包起来

像这样:



猜你喜欢

转载自blog.csdn.net/qq_37585236/article/details/80622664