您的位置:首页 > 编程语言 > Java开发

JAVA反射机制(及反射调用的性能简测)

2016-04-15 22:38 651 查看
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">我们知道大多数脚本语言都是动态语言,例如Perl、Python、ruby之类的。他们都有用一共同的特点数据类型可在程序运行时动态的改变其类型、结构和属性。基本都是解释型语言,而JAVA在程序运行前需要通过编译器先进行源码编译(编译成字节码),然后有jvm加载运行。同样java也引入动态加载的相关机制----反射机制。从而实现动态加载类对象,提高程序设计的灵活性。</span>
1.java的反射机制:

反射机制允许程序在运行状态中知道类对象的所有方法和属性。对于任意对象都可以调用其任意方法。

java反射机制相关的API在JDK的java.lang.reflect包中。

Member接口该接口可以获取有关类成员(域或者方法)后者构造函数的信息。
AccessibleObject类该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。

它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。
Array类该类提供动态地生成和访问JAVA数组的方法。
Constructor类提供一个类的构造函数的信息以及访问类的构造函数的接口。
Field类提供一个类的域的信息以及访问类的域的接口。
Method类提供一个类的方法的信息以及访问类的方法的接口。
Modifier类提供了 static 方法和常量,对类和成员访问修饰符进行解码。
Proxy类提供动态地生成代理类和类实例的静态方法。
2.Class对象的获取(Class类是一个特殊的类对象,它本身也是一个对象):

1>.通过类对象的.getClass()方法:

Class class1 = [对象].getClass();

2>.通过Class的静态方法.forName()获取:

Class class2 = Class.forName();

3>.通过类的.class属性获取:

Class class3 = Boolean.class;

3.获取fields

Java的Class中提供几个方法来获取类中声明的字段。方法如下:

public FieldgetField()、 public Field[] getFields()、 public Field getDeclaredField(String name)、public Field[] getDeclareds().

4.获取Class的Method

同获取声明字段一样Class同样提供了如下方法:

public Method getMethod(String name, Class<?>, parameterTypes)、getMethods()、public Method getDeclaredMethod(String name, Class<?> ... parameterTypes)、public
Method[] getDeclaredMethod().

5.获取构造函数:

同样使用 public Constructor getConstructor(Class<T>...parameterTypes ).等方法可以获取到类的公共构造方法。方法详情请API中自行查找。

6.程序实例:

1>.user Class Code:

public class User {
public int age;
private String fristName;
private String lastName;

public User(){}

public User(int age, String fristName, String lastName) {
this.age = age;
this.fristName = fristName;
this.lastName = lastName;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getFristName() {
return fristName;
}

public void setFristName(String fristName) {
this.fristName = fristName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

}
2> TestReflest Class Code:

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

public class TestReflect {
/**
* @param args
* @throws NoSuchFieldException
*/
public static void main(String[] args) throws NoSuchFieldException {
// TODO Auto-generated method stub
User user = new User();
//获取类类型
Class class1 = User.class;
Class class2 = user.getClass();
try {
Class class3 = Class.forName("User");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获取field
try {
Field [] fields = class1.getFields();
System.out.println(fields.length);
Field ageField = class1.getField("age");
System.out.println(ageField.toString());
}  catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println();
//获取方法
Method[] methods = class1.getMethods();
for (Method m : methods)
{
System.out.println(m);
}
System.out.println();
Constructor[] constructors = class1.getConstructors();
for(Constructor c: constructors) {
System.out.println(c);
}
System.out.println();
//创建对象
try {
User user2 = (User) class1.newInstance();
System.out.println(user2);
System.out.println();
Constructor constructor = class1.getConstructor();
User user3 = (User) constructor.newInstance();
System.out.println(user3);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println();
//调用方法
try {
Method setAge = class1.getMethod("setAge", int.class);
setAge.invoke(user, 10);
System.out.println(user.getAge());
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

代码写的比较粗狂简单,通过调用上述的一些方法完成了class、field、method、constructor等类信息。同时通过调用invoke() 和newInstance()等方法完成方法调用和类对象的创建。

反射调用的性能问题:

反射调用是程序在运行时态下,获取对象的类信息,包括类属性,方法。因为java反射是要解析字节码,对内存中的对象
对象进行解析操作,尤其是在包括动态类型的属性时对于jvm来说无法实现编译状态下的代码优化,从而在带来性能低的问题。
准备了一个简单实例:
* Created by cike on 16/6/28.
*/
public class User {
private String name;
private int age;

public User() {}

public User(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String  playing() {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 1000; i++) {
stringBuffer.append(i);
}
return stringBuffer.toString();
}
}


测试main方法:
public static void main(String[] args) {
Class userClass = User.class;
try {
Method method = userClass.getMethod("playing", null);
User user = (User) userClass.newInstance();
long start = System.currentTimeMillis();
System.out.println(method.invoke(user,null));
System.out.println("反射调用方法耗时:" + String.valueOf(System.currentTimeMillis() - start));

User user1 = new User();
long start1 = System.currentTimeMillis();
System.out.println(user1.playing());
System.out.println("常规调用方法耗时:" + String.valueOf(System.currentTimeMillis() - start1));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
多次运行代码测试结果如下:







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: