Java类反射机制

Java类反射机制

1. Person类

package com.mytest.domain;

public class Person {
    private String name;
    private int age;
    public String school;
    // 测试protected和default
    int chinese;
    protected int math;

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

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

    public Person() {
    }

    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 String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

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

    public int increment(){
        System.out.println("没有参数的方法");
        return 1;
    }

    public int increment(int v){
        System.out.println("传入一个int类型,返回:" + (v+1));
        return v + 1;
    }
}

2. 测试类

import com.mytest.domain.Person;

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

public class Main {
    public static void main(String[] args) throws Exception {
        // getClassObject();
        // testField();
        // testConstructor();
        // testMethod();
    }

    // 反射机制就是将类的各个组成部分封装为其他对象 Field、Constructor、Method
    // 在Class类中存有Field[]、Constructor[]、Method[]三个数组
    public static void getClassObject() throws Exception {
        // 获得反射中的Class对象的三种方式
        // 源代码阶段(字节码),将字节码文件通过类加载器(ClassLoader)加载进内存,返回Class对象
        Class cls1 = Class.forName("com.mytest.domain.Person"); // 类的全路径名。多用于配置文件
        // Class类对象阶段,通过类名的属性class获取
        Class cls2 = Person.class; // 多用于参数的传递
        // Runtime运行时阶段,通过对象继承自Object类的gtClass方法
        Person p = new Person();
        Class cls3 = p.getClass(); // 多用于对象的获取字节码的方式
        // 同一字节码文件在程序运行过程中,只会被加载一次,各方式获取到的Class对象都是同一个
         System.out.println(cls1 == cls2); // true
         System.out.println(cls1 == cls3); // true
        // 获取类名,得到完整路径
        String className = cls1.getName();
        System.out.println(className);
    }

    // 获取成员变量
    public static void testField() throws Exception {
        Class cls = Person.class;
        Person p = new Person("John",23,"nku");

        // 只能获取public修饰的成员变量(父类的public成员变量也能获取到)
        Field[] fields = cls.getFields();
        for(Field f : fields)
            System.out.println(f);
        // 获取指定名字的public成员变量
        Field field = cls.getField("school");
        // 获取并设置对象的属性值
        String value = (String)field.get(p);
        field.set(p,"thu");
        System.out.println(p);

        // 获取所有成员变量(public protected default private),无法获取到父类的任何属性
        fields = cls.getDeclaredFields();
        for(Field f : fields)
            System.out.println(f);
        // 获取指定名称的成员变量
        field = cls.getDeclaredField("name");
        field.setAccessible(true); // 访问、修改私有成员变量,暴力反射。不加这句会异常
        String name = (String)field.get(p);
        field.set(p,"Mike");
        System.out.println(p);
    }

    // 获取构造器
    public static void testConstructor() throws Exception{
        Class cls = Person.class;
        // 获取所有public构造器
        Constructor[] cons = cls.getConstructors();
        // 根据构造器形参类型获取构造器
        Constructor c1 = cls.getConstructor(String.class, int.class);
        // 使用构造器对象的newInstance方法创建Person对象,传入构造器参数、返回Object类型对象
        Person person = (Person)c1.newInstance("Joe", 18);
        System.out.println(person);
        // 使用类对象的newInstance()方法创建对象,等价于空构造器调用newInstance()
        person = (Person)cls.newInstance();
        System.out.println(person);
        // getDeclaredConstructors 和 getDeclaredConstructor可获取所有构造器,不再赘述,下同
    }

    // 获取方法
    public static void testMethod() throws Exception{
        Class cls = Person.class;
        Person p = new Person();
        // 获取public方法(包括父类的)
        Method[] methods = cls.getMethods();
        for(Method m : methods)
            System.out.println(m);
        // 获取指定方法,传入方法名和形参类对象列表
        Method method = cls.getMethod("increment", int.class);
        // 调用方法,传入调用的对象和实参
        method.invoke(p,2);
        // getName()得到方法名称,仅是调用的名称 如increment
        System.out.println(method.getName());
    }

}

你可能感兴趣的:(秋招,Java,java)