欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java反射基础小入门(学习笔记)

程序员文章站 2024-02-07 23:11:04
...

首先,认识一下Java代码 在计算机中经历的阶段 (三个阶段)

Java反射基础小入门(学习笔记)

反射:将类的各个组成部分封装为其他对象

好处:

  1. 在程序运行中,拿到这些对象
  2. 可以解耦,提高程序的可扩展性

获取Class对象的方式:

 1. 通过类型获得
  // 语法:类名.class
  // 应用场景:确定类型等
    Class beansClass = 类名.class;
   
 2 通过实例对象获得
    // 语法:变量.getClass()
    // 应用场景:在方法内部通过参数获得类型等 
    // 先给你 new一个对象
    Beans beans = new Beans();
    Class<? extends Beans> aClass = beans.getClass();

 3 通过字符串获得
    // 语法:Class.forName("全限定类名")
    // 应用场景:通过配置获得字符串等
    Class<?> aClass1 = Class.forName("Demo01.Beans");

同一个字节码文件(*.Class)再一次程序运行过程中,只会内加载一次 无论哪一种方式获取Class对象都是同一个

Class对象功能:

获取功能:

  1. 获取成员变量

    Field[] getFields()

    Field getField(String name)

    Field[] getDeclaredFields( )

    Field getDeclaredField(String name)

  2. 获取构造方法

    Constructor<?> getConstructors()

    Constructor<T> getConstructor(类<?>... parameterTypes)

    Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)

    Constructor<?>[] getDeclaredConstructors()

  3. 获取成员方法

    Method getMethods()
    Method getMethod(String name, 类<?>... parameterTypes)

    Method[] getDeclaredMethods()
    Method getDeclaredMethod(String name, 类<?>... parameterTypes)

  4. 获取类名

    String getName()

功能演示:(获取成员变量)

Person类:

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

    public Person() {
    }

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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;
    }
}

Field[] getFields() 获取所有的成员变量

public class FieldDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //获取所有的成员变量
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
    }
}

Java反射基础小入门(学习笔记)

然而 为什么我的Person类里面有三个成员变量 可以循环只出了一个

回头 看一下我们的Person类

Java反射基础小入门(学习笔记)

除了ID 其他的成员变量都是Private修饰的 那现在我们知道了Field[] getFields()获取所有public修饰的成员变量

所以,来看 Field getField(String name) 就可以分析出 String name 获取指定名字的成员变量 ( getFields() 获取所有public修饰的成员变量) 那么 Field getField(String name) 就是 获取指定名字的public修饰的成员变量。

那么我们获取成员变量可以来干什么?

  1. 赋值

    set(Object obj, Object value) 将指定对象参数上的此 Field对象表示的字段设置为指定的新值。

  2. 获取值

    get(Object obj) 返回该所表示的字段的值 Field ,指定的对象上。

  3. setAccessible(true)

    忽略访问权限修饰符的安全检查 (后面的功能中我们都能用的到)

代码演示:(格式)

public class FieldDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //获取指定名字的public修饰的成员变量
        Field id = aClass.getField("id");
        //设置成员变量id的值
        Person person = new Person();
        id.set(person,8848);
        //获取成员变量id的值
        Object o = id.get(person);
        System.out.println("id是"+o);
    }
}

Java反射基础小入门(学习笔记)

上面的两个功能我们学会了那么 下面的两个功能就更加简单:

Field[] getDeclaredFields( ) 获取所有成员变量(不考虑修饰符)

public class FieldgetConstructorDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //不考虑 修饰符
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
    }
}

Java反射基础小入门(学习笔记)

那么Field getDeclaredField(String name) 不就是指定名字的成员变量

那我们来看一下他的 赋值取值

public class FieldgetConstructorDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //根据变量名称获取
        Field name = aClass.getDeclaredField("name");
        Person person = new Person();
        //忽略访问权限修饰符的安全检查 (暴力反射 FBI! open the door)
        name.setAccessible(true);
        //赋值
        name.set(person,"Jo级生物");
        //获取
        Object o = name.get(person);
        System.out.println("我是 :"+o);

    }
}

如果 没有setAccessible(true )私有的不能被访问 所以 会报一个 非法的访问异常

Java反射基础小入门(学习笔记)

功能演示:(获取构造方法)

public class Demo01 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("ConstructorDemo03.Person");
        //构造方法 类名和方法名是相同的
        //区分 : 参数不一样 而这里要求的参数类型是不同参数的Class对象
        Constructor<?> constructor = aClass.getConstructor(int.class,
                String.class,
                int.class);
        System.out.println(constructor);
    }
}

Java反射基础小入门(学习笔记)

Constructor:构造方法
    创建对象:T  newInstance(Object... initargs)

用法:

        Constructor<?> constructor = aClass.getConstructor(int.class,
                String.class,
                int.class);
        //创建对象
        Object o = constructor.newInstance(1, "张三", 20);
        System.out.println(o);

Java反射基础小入门(学习笔记)

创建一个空参就能好说了 :

Java反射基础小入门(学习笔记)

定义就是一个 可变参的形式

 Constructor<?> constructor = aClass.getConstructor();
        //创建对象
        Object o = constructor.newInstance();
        System.out.println(o);

也可以使用Class对象中的newInstance的方法

Class<?> aClass = Class.forName("ConstructorDemo03.Person");
Object o1 = aClass.newInstance();
System.out.println(o1);

如果说 我们的构造方法是私有的

那么就可以使用 Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)

其实用法与上面的(获取成员变量)基本相同:

public class Demo02 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("ConstructorDemo03.Person");
        //暴力反射
        Constructor<?> dct = aClass.getDeclaredConstructor(int.class,
                String.class,
               int.class);
        dct.setAccessible(true);
        Object o = dct.newInstance(1, "张三", 20);
        System.out.println(o);
    }
}

功能演示: (获取成员方法)

在Person 加入了三个方法:

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

    public Person() {
    }

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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;
    }

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

    public void eat(){
        System.out.println("我在喝刘一碗羊汤");
    }
    public void eat(int count){
        System.out.println("我在刘一碗喝了"+count+"碗羊汤");
    }
    private void swim(){
        System.out.println("我在游泳");
    }
}
public class Demo01 {
    /*
    *  执行方法
    * */
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("MethodDemo04.Person");
        //获得指定名称的方法
        Method method = aClass.getMethod("eat");
        Person person = new Person();
        //执行方法
        method.invoke(person);
        //如果方法中传入了参数
        Method method1 = aClass.getMethod("eat",int.class);
        Person person1 = new Person();
        method1.invoke(person1,60);

        //获取所有的public修饰的方法
         Method[] methods = aClass.getMethods();
         for (Method method2 : methods) {
             System.out.println(method2);
         }
        
        //拿到私有的方法
        Method swim = aClass.getDeclaredMethod("swim");
        Person person2 = new Person();
        swim.setAccessible(true);
        swim.invoke(person2);
    }
}

因为要获取所有的public修饰的方法 方法有很多所以就没有让他执行

Java反射基础小入门(学习笔记)