java反射学习

java反射学习

Administrator 18 2024-08-25

java反射学习

反射概述:

反射可以帮助我们在动态运行的时候,对于任意一个类,可以获得其所有方法,所有的变量(是所有的!包括私有!)

图片-amag.png

Class类:

Java中java.lang.Class类用于表示一个类的字节码(.class)文件
如何得到某个class文件对应的Class对象
已知类和对象的情况下
类名.class
对象.getClass() — Object 类提供
未知类和对象的情况下
Class.forName(“包名.类名”)

图片-rjts.png

写一个Animal类:

package org.example;

public class Animal {
    public String name;
    private int id;
    public Animal(){
        System.out.println("我是无参构造方法");
    }
    public Animal(int id,String name){
        this.setId(id);
        this.setName(name);
        System.out.println("我是有参构造方法");
    }

    public void eat(){
        System.out.println("我是公有方法");
    }
    private void drink(){
        System.out.println("我是私有方法");
    }
    private void play(String name,String sex){
        System.out.println("我是私有带参方法");
    }

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

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

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

然后写一个获取Class对象的反射调用的类

package org.example;

public class Classtest {
    public void demo() throws ClassNotFoundException{
        Class class1 = Animal.class;   //1.通过类名.class的方式


        Animal animal =new Animal();
        Class class2 = animal.getClass();   //2.通过对象.getClass()的方式

  
        Class class3 = Class.forName("org.example.Animal");   //3.Class类forName();获得
  
    }

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


    }

}

Constructor类:

Constructor类的实例对象代表类的一个构造方法
得到某个类所有的构造方法
Constructor [] constructors = Class.forName(“java.lang.String”).getConstructors();
得到指定的构造方法并调用
Constructor constructor = Class.forName(“java.lang.String”).getConstructors(String.class);
String str = (String)constructor.newInstance(“abc”);
Class类的newInstance()方法用来调用类的默认构造方法
String obj = (String)Class.forName(“java.lang.String”).newInstance();

写一个通过反射进行调用方法的类

package org.example;
import java.lang.reflect.Constructor;
public class ConstructorTest {
    public void demo1() throws Exception{
    Class class1 = Class.forName("org.example.Animal");
    Constructor c = class1.getConstructor();
    Animal animal = (Animal) c.newInstance();
    }/**
     demo1是通过反射获取无参构造方法
     **/

    public void demo2() throws Exception{
        Class  class1 = Class.forName("org.example.Animal");
        Constructor c = class1.getConstructor(int.class,String.class);
        Animal animal = (Animal) c.newInstance(2,"猴子");
        System.out.println(animal.toString());
    }
    /**
     demo2是通过反射获得有参构造方法
     **/

    public static void main(String[] args) throws Exception{
    ConstructorTest c =new ConstructorTest();
    c.demo1();
    System.out.println("-----------------------------");
    c.demo2();

    }

}

运行的结果:

图片-dsfk.png

再后面我们再新建立一个demo3函数,作用:获取所有的构造方法

代码如下:

package org.example;
import java.lang.reflect.Constructor;
public class ConstructorTest {
    public void demo1() throws Exception{
    Class class1 = Class.forName("org.example.Animal");
    Constructor c = class1.getConstructor();
    Animal animal = (Animal) c.newInstance();
    }/**
     demo1是通过反射获取无参构造方法
     **/


    public void demo2() throws Exception{
        Class  class1 = Class.forName("org.example.Animal");
        Constructor c = class1.getConstructor(int.class,String.class);
        Animal animal = (Animal) c.newInstance(2,"猴子");
        System.out.println(animal.toString());
    }
    /**
     demo2是通过反射获得有参构造方法
     **/

    public void demo3() throws Exception{
        Class class1 = Class.forName("org.example.Animal");
        Constructor[] c = class1.getConstructors();
        for (Constructor constructor : c){
            System.out.println("Constructor"+constructor);
        }
    }
    /**
     demo3是通过反射获取所有的构造方法
     **/

    public static void main(String[] args) throws Exception{
    ConstructorTest c =new ConstructorTest();
    c.demo1();
    System.out.println("-----------------------------");
    c.demo2();
    System.out.println("-----------------------------");
    c.demo3();
    }

}

打印结果:

图片-fqbl.png

可以看到获取了Animal类中的所有的构造方法

Field类:

Field类代表某个类中的一个成员变量,并提供动态的访问权限
Field对象的获得
Field[] fields = c.getFields();//取得所有public属性(包括父类继承)
Field[] fields = c.getDeclaredFields();//取得所有声明的属性
得到指定的成员变量
Field name = c.getField(“name”);
Field name = c.getDeclaredField(“name”);
设置Filed变量是否可以访问
field.setAccessible(boolean);
-Field变量值的读取,设置
field.get(obj);
filed.set(obj,value);

创建一个FieldTest类

package org.example;
import java.lang.reflect.Field;
public class FieldTest {
    //测试共有方法:
    public void demo1() throws Exception{
    Class class1 = Class.forName("org.example.Animal");  //首先获取class类
    Field field = class1.getField("name");  //获取属性
         /**
          以下俩个行代码是进行操作属性:
          **/
    Animal animal = (Animal) class1.getConstructor().newInstance(); //获取Animal无参构造方法
    field.set(animal,"老虎");  //将Animal.name="老虎";
    //获取属性:
    Object obj= field.get(animal);
    System.out.println(obj);
    System.out.println(animal);  //会自动调用toString()方法;
    }
    //测试私有方法
    public void demo2() throws Exception{
    //获得Class:
    Class class1 = Class.forName("org.example.Animal");
    //获得私有属性:
    Field field = class1.getDeclaredField("id");
    //操作属性:
    Animal animal = (Animal) class1.getConstructor().newInstance();   //获取Animal无参构造
    field.setAccessible(true);   //私有属性,需要设置一个可访问的权限
    field.set(animal,2);
    //获取值:
    Object obj = field.get(animal);
    System.out.println(obj);
    System.out.println(animal);
    }


    public static void main(String[] args) throws Exception{
        FieldTest fieldTest = new FieldTest();
        fieldTest.demo1();
        System.out.println("-----------------------------------");
        fieldTest.demo2();
    }
}

打印结果:

图片-npvz.png

Method类:

Method类代表某个类中的一个成员方法
Method对象的获得
获得所有方法
getDeclaredMethods()
getMethods()
-获得指定的方法
getDeclaredMethod(String name,Class…parameterTypes) getMethod(String name,Class…parameterTypes)
通过反射执行方法
invoke(Object obj,Object…args)

创建一个MethodTest类

package org.example;

import java.lang.reflect.Method;

public class MethodTest {
    public void demo1() throws Exception{
    //获取Class对象:
    Class class1 = Class.forName("org.example.Animal");
    //实例化:
    Animal animal = (Animal) class1.getConstructor().newInstance();
    //获得公有方法
    Method method = class1.getMethod("eat");
    //执行方法
    method.invoke(animal); //相当于animal.eat();

    }

    public void demo2() throws Exception{
        //获取class对象
        Class class1 = Class.forName("org.example.Animal");
        //实例化
        Animal animal = (Animal) class1.newInstance();
        //获取私有方法
        Method method = class1.getDeclaredMethod("drink");          //私有方法,使用getDeclaredMethod
        //设置私有的访问权限
        method.setAccessible(true);
        //执行该方法
        method.invoke(animal);     //相当于animal.drink();

    }
    public void demo3() throws Exception{
        //获取Class对象
        Class class1 = Class.forName("org.example.Animal");
        //实例化
        Animal animal = (Animal) class1.newInstance();
        //获取私有带参方法
        Method method = class1.getDeclaredMethod("play", int.class, String.class);
        //设置私有访问权限
        method.setAccessible(true);
        //执行方法
        Object obj = method.invoke(animal,2,"孔雀");
        System.out.println(obj);

    }



    public static void main(String[] args) throws Exception{
    MethodTest methodTest = new MethodTest();
    methodTest.demo1();
    System.out.println("--------------------------");
    methodTest.demo2();
        System.out.println("--------------------------");
        methodTest.demo3();
    }


}

运行结果:

图片-rqxq.png

总结:

对于Constructor类、Field类、Method类首先需要获得Class对象,然后进行newInstance实例化。