Java 反射


反射用于在程序运行过程中更改程序的行为。


Java框架,例如Spring,用反射比较多。反射很强大和灵活,比如可以访问类的private属性。比如在程序运行过程中,根据类名(字符串)创建一个类的对象。但反射也有缺点:性能问题、安全问题、暴露了程序的内部细节。

在程序运行时,创建引用类型(非基本数据类型)的对象时,同时会创建一个Class对象,提供方法用于查询引用类型对象的运行时属性,包含类和成员信息。Class对象也用于创建引用类型的对象。Class对象是所有反射操作的入口。

得到Class对象

有下面3种方式得到Class对象:

  • 通过对象的getClass方法。例如Class<?> c = "dog".getClass();
  • 通过.class写法。例如:Class<?> c = String.class;
  • 通过Class.forName方法。例如:Class<?> c = Class.forName("java.lang.String");

得到类的修饰符

类的修饰符有下面几种:

  • 访问修饰符,包含public、protected、private。
  • 需要重载修饰符:abstract。
  • 只能有一个实例修饰符:static。
  • 只读修饰符:final。
  • 注解:Annotation接口。

下面是反射得到类的修饰符的例子:

import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

public class ReflectModifier {
    public static void main(String[] args) {
        try {
            Class<?> c = Class.forName("java.lang.String");
            System.out.println("modifiers : " + Modifier.toString(c.getModifiers()));
                //  modifiers : public final

            Type[] interfaces = c.getGenericInterfaces();
            for (Type t : interfaces)
                System.out.println("\t" + t.toString());
                    // interface java.io.Serializable
                    // java.lang.Comparable<java.lang.String>
                    // interface java.lang.CharSequence

            Class<?> father = c.getSuperclass();
            System.out.println("\t\t" + father.getName());    // java.lang.Object
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


得到类的属性和方法

下面是反射得到类的属性和方法的例子:

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

public class ReflectMember {
    public static void main(String[] args) {
        try {
            Class<?> c = Class.forName("java.util.HashSet");

            Member[] constructors = c.getConstructors();
            for (Member m : constructors)
                System.out.println(((Constructor<?>)m).toGenericString());
                    // public java.util.HashSet(int)
                    // public java.util.HashSet(int,float)
                    // ...

            Member[] fields = c.getDeclaredFields();
            for (Member m : fields)
                System.out.println("\t" + ((Field)m).toGenericString());
                    // static final long java.util.HashSet.serialVersionUID
                    // private transient java.util.HashMap<E, java.lang.Object> java.util.HashSet.map
                    // ...

            Member[] methods = c.getMethods();
            for (Member m : methods)
                System.out.println("\t\t" + ((Method)m).toGenericString());
                    // public boolean java.util.HashSet.add(E)
                    // public boolean java.util.HashSet.remove(java.lang.Object)
                    // ...
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}