Java 反射的概念与使用

一,反射的概念

对于一个人来说,了解自己的能力、本事、特点,对于他去干事创业来说,是很重要的。

同样的,对于一门面向对象的语言来说,了解类(对象其实就是类的实现)本身也是重要的,可以在很多地方帮助程序更好的进行。

那么类/对象本身包含那些内容呢,无非就是类名称;父类;继承的接口;类的属性;类的方法,这些都属于是类的信息

好的,那么这些信息程序员都知道啊,类的信息在定义类的时候不是都写的明明白白的吗。但是反射的意义却是:在程序跑起来之后可以使用代码去获取类的信息。这个,没有反射可办不到。

Java是面向对象的,所有的东西都是有类别的。所以哦,类的信息也是一种类型(就像用户信息可以用UserInfo类描述),类的信息对应的Java类为Class类,注意不是关键字class哈。

举个最常见的栗子:

public class ClassDemo {
    public static void main(String[] args) {
        try {
            Class mysqlDriver=Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

这里Class.forName很明显是Class类的一个static方法,这个方法的意思就是按类名(完整的带包路径的类名)返回类对应的Class对象。因为forName的参数是可以随便写的嘛,所以会抛出一个ClassNotFoundException。

Class.forName方法是在程序运行时按类名称获取类的信息的方法,这就是反射机制。

二,如何获取类的Class对象

我们定义一个普通类Student,可以有三种方式获取到Student的类型信息:

package temp;
public class Student {
    String studentName;
    public String getStudentName(){
        return studentName;
    }
    public static void main(String[] args) throws ClassNotFoundException {
        //方式1 利用类名称
        Class class1 = Class.forName("temp.Student");  
        //方式2 利用类
        Class class2=Student.class;
        //方式3 利用对象
        Student student=new Student();
        Class class3=student.getClass();
    }
}

三,通过类的Class对象获取类的属性和方法

获取到Class(类的类型)之后,再获取属性和方法就简单了,直接使用Class类封装的方法即可。

getDeclaredFields:获取类属性
getDeclaredMethods():获取类方法

使用一个完整的程序演示如下:

package temp;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Student {
    String studentName;
    public String getStudentName(){
        return studentName;
    }
    public static void main(String[] args) throws ClassNotFoundException {
        Class classStu=Student.class;
        Field[] fields = classStu.getDeclaredFields();
        for(Field field:fields){
            System.out.println("属性类型:"+field.getType().getSimpleName()+",属性名称:"+field.getName());
        }
        Method[] methods=classStu.getDeclaredMethods();
        for(Method method:methods){
            System.out.println("方法名称:"+method.getName()+",返回类型"+method.getReturnType());
        }
    }
}

执行结果如下:

属性类型:String,属性名称:studentName
方法名称:main,返回类型void
方法名称:getStudentName,返回类型class java.lang.String

可见,通过Class类封装的方法,可以在程序运行时候直接获取类的信息。

四,反射的意义

凡是都有正反两个方面,先说不好的消息吧,用了反射,性能肯定是会降低的。注意此处的性能低,并不是说通过反射获取类的信息性能低,因为除了反射也没有啥可以获取类的信息的机制了。

性能低是指通过反射调用方法性能低,看下面的例子,通过反射获取到方法之后,可以将该方法应用到一个对象上实现该对象的方法调用。本来可以直接调用,反射之后再调用肯定效率要低的。

Class classStu=Student.class;
Student student=new Student();
Method methodGet=classStu.getDeclaredMethod("getStudentName");
//可以通过Method类的invoke方法调用类方法,当然必须得提供对象
String name=(String)methodGet.invoke(student);
System.out.println(name);

但是反射的正面意义还是光辉的,首先提供了一种了解类的信息的手段,使程序运行编写、运行更加自由灵活,充满了更多可能性。

简单的想,在将对象转换为json时,键值对的键不就是对象的属性名称么,用反射获取对象的属性名称是多么爽快的事情啊。

点赞