当前位置:首页 > 分类 > JAVA高级 > JAVA反射机制(Class类使用)

JAVA反射机制(Class类使用)

反射通常由需要检查或修改Java虚拟机中运行的应用程序的运行时行为的程序使用。这是一个相对高级的功能,只应由对语言基础有很深了解的开发人员使用。考虑到这一警告,反射是一种强大的技术,可以使应用程序执行原本不可能的操作。

反射功能强大,但不应任意使用。如果可以在不使用反射的情况下执行操作,那么最好避免使用它。通过反射访问代码时,应牢记以下注意事项。

  • 绩效开销

  • 由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化。因此,反射操作的性能要比非反射操作慢,因此应该避免在对性能敏感的应用程序中经常调用的代码段中。

  • 安全限制

  • 反射需要运行时许可,而在安全管理器下运行时可能不存在。对于必须在受限的安全上下文(例如Applet)中运行的代码,这是一个重要的考虑因素。

  • 内部暴露

  • 由于反射允许代码执行非反射代码中非法的操作(例如访问private字段和方法),因此使用反射可能会导致意外的副作用,这可能会使代码无法正常工作并可能破坏可移植性。反射性代码破坏了抽象,因此可能会随着平台的升级而改变行为。



1,获取指定类的class对象。Class.forName

		Class<?> clazz = String.class;
Class<?> clazz2 = "www.youfengxin.com".getClass();
Class<?> clazz3 = Class.forName("java.lang.String");


2,使用java反射创建实例。clazz.newInstance()

Object a1 = clazz3.newInstance();

Object a2 = clazz3.getConstructor().newInstance();

Constructor<?> constructor3 = clazz3.getConstructor(String.class);
Object a3 = constructor3.newInstance("www.youfengxin.com");

Constructor<?> constructor4 = clazz3.getDeclaredConstructor(String.class);
constructor4.setAccessible(true);
Object a4 =constructor4.newInstance("www.youfengxin.com");

    getConstructor和getDeclaredConstructor的区别在于:getConstructor只能获取public构造器,如果用于获取private构造器将报错NoSuchMethodException;而getDeclaredConstructor可以获取public和private两种,但获取private构造器后不可直接实例化,而应该在中间加上constructor.setAccessible(true);,否则报错IllegalAccessException(Class X can not access a member of class Y with modifiers "private")。简言之getConstructor不能获取private,getDeclaredConstructor可以获取private,同时需加上constructor.setAccessible(true);。


3,调用实例方法。clazz.getDeclaredMethod

Method method= clazz3.getDeclaredMethod("replace", char.class,char.class);
method.setAccessible(true);
Object a5 = method.invoke(a3, '.',',');
System.out.println(a5);

    A,使用class对象,方法名,方法参数类型获取方法实例;

    B,把方法设为可访问状态;

    C,调用String实例a3的方法,并传入参数。由于replace方法返回新的string实例,故用a5接收,a3不变。

跟上面构造器一样,可使用getMethod或getDeclaredMethod。


4,访问实例属性。clazz.getDeclaredField

Field field =   clazz3.getDeclaredField("hash");
field.setAccessible(true);
field.set(a3, 12);
field.setInt(a3, 12);
System.out.println(field.getInt(a3));

    A,获取String实例的hash属性,没有获取value属性是因为value属性是final修饰的,虽然可以访问,但不能修改。

    B,set传入obj对象,setInt传入int。


5,判断是否使用某注解。isAnnotationPresent

//例@Deprecated
boolean classAnn = clazz.isAnnotationPresent(Deprecated.class);
boolean methodAnn = method.isAnnotationPresent(Deprecated.class);
boolean fieldAnn = field.isAnnotationPresent(Deprecated.class);

切面编程中大量使用。


6,获取父类。clazz.getSuperclass();

Type type = clazz.getSuperclass();
Class<?>[] interfaces = clazz.getInterfaces();


7,相关类。

Class,Constructor,Method,Field,Annotation,Type。