Java反射机制常用方法介绍

最近恰好用到反射机制,我把相关的知识整理了一下贴在下面。

〇、 Java反射机制简介

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

Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库。Java reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。Java 的这一特性非常强大,并且是其它一些常用语言,如 C、C++、Fortran 或者 Pascal 等都不具备的。

但反射有两个缺点。第一个是性能问题。用于字段和方法接入时反射要远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。即使测试中最坏情况下的计时图显示的反射操作只耗用几微秒。仅反射在性能关键的应用的核心逻辑中使用时性能问题才变得至关重要。

一、测试代码

首先看测试用的Student类与main函数

Student:

import java.io.Serializable;

public class Student implements Serializable,Cloneable {
    private String name;
    private static final String DEFAULT_NAME = "DEFAULT_NAME";

    public String getName() {
        return name;
    }

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

    public Student() {
        this.name = DEFAULT_NAME;
    }

    public Student(String name) {
        this.name = name;
    }

    public Object clone() {
        Student o = null;
        try {
            o = (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
}

main函数部分:

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Main {
    public static void main(String[] args) {
        Student student1 = new Student("aaa");
        System.out.println(student1.getClass().getName());

        try {
            // 下面三种获得Class的方法效果是一样的。
            Class cls1 = Class.forName(student1.getClass().getName());
            Class cls2=Student.class;
            Class cls3=student1.getClass();


            System.out.println("\n获取属性:");
            Field[] fields = cls1.getDeclaredFields();
            for(Field field:fields){
                String str="";
                str+=(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
                str+=(field.getType().getSimpleName() + " ");//属性的类型的名字
                str+=(field.getName()+";");//属性的名字+回车

                System.out.println(str);
            }
//            for(Field field: fields){
//                System.out.println(field);
//            }

            System.out.println("\n获取方法:");
            Method[] methods = cls1.getMethods();
            for (Method method : methods) {
                System.out.println(method);
            }

            System.out.println("\n创建新对象,然后调用方法:");
            Object object=cls1.newInstance();
            Method getNameMethod=cls1.getMethod("getName");
            String msg=(String)getNameMethod.invoke(object);// 此时还是默认name
            System.out.println(msg);

            // 注意后面跟变量类型
            Method setNameMethod=cls1.getMethod("setName", String.class);
            setNameMethod.invoke(object,"new name"); // 执行setName更新name
            msg=(String)getNameMethod.invoke(object);
            System.out.println(msg);
        // 获取实例的方法2
            Student newStu=(Student)cls1.newInstance();
            System.out.println(newStu.getName());
            newStu.setName("hhhh");
            System.out.println(newStu.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }  catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

**

二、 反射常用功能及实现

**
2.1 通过对象,获取该对象的包+类名
如:

Student student1 = new Student("aaa");
System.out.println(student1.getClass().getName());

2.2 利用反射获取类

// 下面三种获得Class的方法效果是一样的。
Class cls1 = Class.forName(student1.getClass().getName());
Class cls2=Student.class;
Class cls3=student1.getClass();

2.3 获取类中的属性

Field[] fields = cls1.getDeclaredFields();
for(Field field:fields){
     String str="";
     str+=(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
     str+=(field.getType().getSimpleName() + " ");//属性的类型的名字
     str+=(field.getName()+";");//属性的名字+回车

     System.out.println(str);
}

运行结果:

private String name;
private static final String DEFAULT_NAME;

2.4 获取类中的方法

Method[] methods = cls1.getMethods();
for (Method method : methods) {
    System.out.println(method);
}

运行结果:

public java.lang.Object Student.clone()
public java.lang.String Student.getName()
public void Student.setName(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

2.5 创建新的实例,并且调用类中的方法

// 
Object object=cls1.newInstance();
Method getNameMethod=cls1.getMethod("getName");
String msg=(String)getNameMethod.invoke(object);// 此时还是默认name
System.out.println(msg);

// 注意后面跟变量类型
Method setNameMethod=cls1.getMethod("setName",String.class);
setNameMethod.invoke(object,"new name");// 执行setName更新name
msg=(String)getNameMethod.invoke(object);
System.out.println(msg);

// 获取实例的方法2
Student newStu=(Student)cls1.newInstance();
System.out.println(newStu.getName());
newStu.setName("hhhh");
System.out.println(newStu.getName());

运行结果:

DEFAULT_NAME
new name
DEFAULT_NAME
hhhh
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值