Java之反射机制

什么是反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。

测试类

public class Person {
    private Integer id;
    private String name;
    private Integer age;
    private String address;
    //有参构造
    public Person(){}
    //无参构造
    public Person(Integer id, String name, Integer age, String address) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }


    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    //重写toString
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age
                + ", address=" + address + "]";
    }

    //静态无参方法
    public static void show(){
        System.out.println("调用无参静态方法");
    }

    //静态有参方法
    public static String showTwo(String mes){
        return mes;
    }
}

Class对象

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和double)和关键字 void 也表示为 Class 对象。 Class 没有公共构造方法。Class 对象是在加载类时由 Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。

在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。Class类不是我们认为创建的,是由java虚拟机,在我们生成.class文件的时候创建的。以下是获取Class对象三种方法:

//通过类全名获取Class对象
Class<?> clazz = Class.forName("java.lang.String");

//通过对象获取类的Class对象
Person obj=new Person();
Class<?> clazz = obj.getClass();

//通过类名获取类的Class对象
Class<?> clazz = Person.class;

获取对象成员

//通过类名获取类的Class对象
//Class<?> clazz = Person.class;
Class<?> clazz = Class.forName("com.yzx.reflect.Person");
//通过Class对象获取类的全部方法
Method[] methods = clazz.getDeclaredMethods();
for(Method m : methods){
    System.out.println(m);
}

//获取指定方法(无参),参数为方法名称,参数类型Class数组
Method method1 = clazz.getDeclaredMethod("getName", new Class[]{});
System.out.println(method1);

//获取指定方法(有参)
Method method2 = clazz.getDeclaredMethod("setName", new Class[]{String.class});
System.out.println(method2);

//获取全部属性
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields){
    System.out.println(f);
}

//获取指定属性
Field field = clazz.getDeclaredField("address");
System.out.println(field);

//获取全构造器
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for(Constructor c : constructors){
    System.out.println(c);
}

//获取指定构造器(无参)
Constructor<?> constructor1 = clazz.getDeclaredConstructor(new Class[]{});
System.out.println(constructor1);

//获取指定构造器(有参)
Constructor<?> constructor2 = clazz.getDeclaredConstructor(new Class[]{Integer.class,String.class,Integer.class,String.class});
System.out.println(constructor2);

创建对象

Class<?> clazz = Class.forName("com.yzx.reflect.Person");
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{});
//通过构造器创建对象(无参)
Object instance = constructor.newInstance(new Object[]{});
System.out.println(instance);

//通过构造器创建对象(有参)
Constructor<?> constructor1 = clazz.getDeclaredConstructor(new Class[]{Integer.class,String.class,Integer.class,String.class});
Object instance2 = constructor1.newInstance(new Object[]{1,"李四",23,"北京"});
System.out.println(instance2);

方法调用

Class<?> clazz = Class.forName("com.yzx.reflect.Person");
//获取类的构造器
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{});

//通过构造器创建对象
Object instance = constructor.newInstance(new Object[]{});
System.out.println(instance);

//获取指定方法
Method setName = clazz.getDeclaredMethod("setName", new Class[]{String.class});
//调用方法并传值
setName.invoke(instance, new Object[]{"李四"});
System.out.println(instance);

//获取指定方法
Method getName = clazz.getDeclaredMethod("getName", new Class[]{});
//调用方法并传值
Object invoke = getName.invoke(instance, new Object[]{});
System.out.println(invoke);

//调用无参静态方法
Method show = clazz.getDeclaredMethod("show", new Class[]{});
show.invoke(null, null);

//调用有参静态方法
Method showTwoMethod = clazz.getDeclaredMethod("showTwo", new Class[]{String.class});
Object ret = showTwoMethod.invoke(instance, new Object[]{"调用有参静态方法"});
System.out.println(ret);

私有属性赋值

Class<?> clazz = Class.forName("com.yzx.reflect.Person");
//获取类的构造器
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[]{});

//通过构造器创建对象
Object instance = constructor.newInstance(new Object[]{});
System.out.println(instance);

//获取属性
Field nameField = clazz.getDeclaredField("name");
//获取属性类型
Class<?> type = nameField .getType();
System.out.println(type);
//私有属性设置为true
nameField.setAccessible(true);
nameField.set(instance, "李四");
System.out.println(nameField.get(instance));

拷贝对象

public static void main(String[] args) throws Exception {
        Person p=new Person();
        p.setName("李四");

        Object newObj=copyObject(p);
        System.out.println(newObj);
    }

public static Object copyObject(Object obj)throws Exception{ 
    Class<? extends Object> clazz = obj.getClass();
    Field[] fields = clazz.getDeclaredFields();

    Constructor<? extends Object> constructor = clazz.getConstructor(new Class[]{});

    //创建一个对象
    Object instance = constructor.newInstance(new Object[]{});
    for(Field f:fields){
        //获取属性名
        String fName=f.getName();
        //获取属性类型
        Class<?> type = f.getType();

        //获取属性对应的get、set方法
        String setMethodName="set"+fName.substring(0,1).toUpperCase()+fName.substring(1);
        String getMethodName="get"+fName.substring(0,1).toUpperCase()+fName.substring(1);

        //获得get方法
        Method gMethod = clazz.getDeclaredMethod(getMethodName, null);
        Object gResult = gMethod.invoke(obj, null);

        //获得set方法
        Method sMethod = clazz.getDeclaredMethod(setMethodName,new Class[]{gMethod.getReturnType()});
        sMethod.invoke(instance, new Object[]{gResult});
    }
    return instance;
}

反射是一种强大的工具,但也存在一些不足。一个主要的缺点是对性能有影响。使用反射基本上是一种解释操作,您可以告诉JVM您希望做什么并且它满足您的要求。这类操作总是慢于直接执行相同的操作。

相关文章
引入反射 Java反射机制详解 Java反射机制 深入解析Java反射

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值