JAVA 反射机制
Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过 Reflection APIs 取得任何一个已知名称的 class 的内部信息,包括其modifiers(诸如 public, static 等 )、superclass(例如 Object)、实现之interfaces(例如 Cloneable),也包括 fields 和 methods 的所有信息,并可于运行时改变 fields 内容或唤起 methods。Java 反射机制容许程序在运行时加载、探知、使用编译期间完全未知的 classes。换言之, Java 可以加载一个运行时才得知名称的 class,获得其完整结构。
反射机制缺点:
反射包括了一些动态类型,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。
反射的使用
User类对象
package com.hhtc.pkg;
public class User {
public int pubIntField;
public String pubStringField;
private int prvIntField;
public User() {
Log("Default Constructor");
}
private User(int arg1, String arg2) {
pubIntField = arg1;
pubStringField = arg2;
Log("Constructor with parameters");
}
public void setIntField(int val) {
this.prvIntField = val;
}
public int getIntField() {
return prvIntField;
}
private void Log(String msg) {
System.out.println("Type:" + msg);
}
@Override
public String toString() {
return "User{" +
"pubIntField=" + pubIntField +
", pubStringField='" + pubStringField + '\'' +
", prvIntField=" + prvIntField +
'}';
}
}
类的Class对象
static void getClazz() {
// 1
Class clazz1 = User.class;
System.out.println(clazz1.getName());
// 2
try {
Class clazz2 = Class.forName("com.hhtc.pkg.User");
if (clazz2 != null) {
System.out.println(clazz2.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 3
Class<?> clazz3 = new User().getClass();
System.out.println(clazz3.getName());
}
类的Fields
static void getFields() {
User user = new User();
Class clazz = user.getClass();
try {
// public fields
Field field = clazz.getField("pubIntField");
field.setInt(user, 10);
System.out.println(user.toString());
System.out.println("-----------------");
Field field2 = clazz.getDeclaredField("prvIntField");
System.out.println(field2);
// prviate fields需要setAccessible为ture,否则会设置失败
field2.setAccessible(true);
field2.setInt(user, 20);
System.out.println(user.toString());
System.out.println("-----------------");
// 获得类的所有public属性
Field [] fields1 = clazz.getFields();
for (Field item : fields1) {
System.out.println(item);
}
System.out.println("-----------------");
// 获得类的所有属性
Field [] fields2 = clazz.getDeclaredFields();
for (Field item : fields2) {
System.out.println(item);
}
System.out.println("-----------------");
} catch (Exception e) {
e.printStackTrace();
}
}
类的Method
void getMethods() {
User user = new User();
user.setIntField(123);
Class clazz = user.getClass();
try {
// 获得类的特定public成员方法
Method method1 = clazz.getMethod("getIntField");
int getIntField = (int)method1.invoke(user);
System.out.println(getIntField);
// 获取类的特定成员方法
Method method2 = clazz.getDeclaredMethod("Log", String.class);
method2.setAccessible(true);
method2.invoke(user, new String("hello log function"));
//获得类的所有成员方法
Method[] method3 = clazz.getDeclaredMethods();
for (Method item : method3) {
System.out.println(item);
}
System.out.println(" --------------");
// 获得类的所有public成员方法
Method[] method4 = clazz.getMethods();
for (Method item : method4) {
System.out.println(item);
}
} catch (Exception e) {
e.printStackTrace();
}
}
类的Constructor
void getConstructor() {
Class<User> clazz = User.class;
// 获得类的所有public构造方法
Constructor[] constructor = clazz.getConstructors();
for (Constructor<?> constructor2 : constructor) {
System.out.println(constructor2);
}
try {
// // 获得类的public无参构造方法
Constructor<User> constructor2 = clazz.getConstructor();
User type2 = (User)constructor2.newInstance();
System.out.println(type2.toString());
// 获得类的特定构造方法(prviate and public)
Constructor<User> constructor3 = clazz.getDeclaredConstructor(int.class,String.class);
constructor3.setAccessible(true);
User type3 = (User)constructor3.newInstance(123,"fuhu");
System.out.println(type3.toString());
} catch (Exception e) {
e.printStackTrace();
}
}