Java 反射

Java反射是什么?

反射就是通过Java提供的一些相关Api来获取类本身的一些属性或方法,进而操作类!

Java类到底有什么?

public class Test
{
}

这是最简的一个类,

  • public 表示Java 访问控制的一个关键字,也就是外部类可以访问此类
  • class 也是表示Java关键字,它表示这个Test 是一个类!
  • Test 就是表示这个类的类名

我们通过反射获取这个类的名

public class Test
{
  public static void main(String[] args) {
    System.out.println("类名1 = " + Test.class.getName());
    System.out.println("类名2 = " + Test.class.getSimpleName());
  }
}

运行结果如下:

类名1 = com.pangugle.framework.reflect.Test
类名2 = Test

从上面的结果我们可以看到

  • Test.class.getName() 表示获取类的包名和类名
  • Test.class.getSimpleName() 表示只是获取类的名称

反射获取类信息汇总

方法 用途
asSubclass(Class<U> clazz) 把传递的类的对象转换成代表其子类的对象
Cast 把对象转换成代表类或是接口的对象
getClassLoader() 获得类的加载器
getClasses() 返回一个数组,数组中包含该类中所有公共类和接口类的对象
getDeclaredClasses() 返回一个数组,数组中包含该类中所有类和接口类的对象
forName(String className) 根据类名返回类的对象
getName() 获得类的完整路径名字
newInstance() 创建类的实例
getPackage() 获得类的包
getSimpleName() 获得类的名字
getSuperclass() 获得当前类继承的父类的名字
getInterfaces() 获得当前类实现的类或是接口

反射类名我们知道了,那如何反射方法名呢?

public class Test
{
  public static void main(String[] args) {
    Method[] methods = Test.class.getMethods();
    for(Method m : methods)
    {
      System.out.println("method name = " + m.getName());
    }
  }
}

运行结果如下:

method name = main
method name = wait
method name = wait
method name = wait
method name = equals
method name = toString
method name = hashCode
method name = getClass
method name = notify
method name = notifyAll

看到上面的结果很多的人都疑惑,怎么会有这么多的方法呢?

首先 main 方法这个不用我解释,代码就在那里,关键是后面的方法哪里来的呢? 要回答这个问题,首先我们要知道,

所有的Java类都是继承于Object!

了解了这一点,我们再看看Object 有哪些方法?

  • 有wait 方法
  • equals 方法
  • hasCode 方法

... 等等, 现在我们知道了这些方法是由于Test默认都是继承Object, 自然就拥有了 Object 的方法!

而从输出的结果顺序我们可以看到,是先打印 Test 中的 main 方法,再打印出父类方法,

也就是说类的方法反射是先装自己的方法,再装父类的方法!

反射获取方法信息汇总

方法 用途
getAnnotation(Class<A> annotationClass) 返回该类中与参数类型匹配的公有注解对象
getAnnotations() 返回该类所有的公有注解对象
getDeclaredAnnotation(Class<A> annotationClass) 返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations() 返回该类所有的注解对象

一个类除了有类名,有方法,它还有属性!

public class Test {
	private String username;
	public static void main(String[] args)
	{
		Field[] arrf=Test.class.getDeclaredFields();
		for(Field f : arrf)
		{
			System.out.println("field name = " + f.getName());
		}
	}
}

运行结果

field name = username

从上面我们可以看到反射获取属性的方法是 getDeclaredFields()

反射属性相关方法汇总

方法 用途
getField(String name) 获得某个公有的属性对象
getFields() 获得所有公有的属性对象
getDeclaredField(String name) 获得某个属性对象
getDeclaredFields() 获得所有属性对象

通过反射可以类的构造信息

方法 用途
getConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法
getConstructors() 获得该类的所有公有构造方法
getDeclaredConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的构造方法
getDeclaredConstructors() 获得该类所有构造方法

通过反射可以类的运行时期的类泛型信息、 annotation (注解) 等信息

方法 用途
isAnnotation() 如果是注解类型则返回true
isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果是指定类型注解类型则返回true
isAnonymousClass() 如果是匿名类则返回true
isArray() 如果是一个数组类则返回true
isEnum() 如果是枚举类则返回true
isInstance(Object obj) 如果obj是该类的实例则返回true
isInterface() 如果是接口类则返回true
isLocalClass() 如果是局部类则返回true
isMemberClass() 如果是内部类则返回true