动态语言
程序运行的时,可以改变程序结构或变量类型。典型的语言:
Python,ruby,javascript等
如javascript代码:
function test(){
var s = "var a = 3, var b = 4; alert(a+b)";
eval(s);
}
C、C++、Java不是动态语言,但是Java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。
Java的动态性让编程的时候更加灵活。
反射机制
指的是可以运行时加载、探知、使用编译期间完全未知的类。
程序在运行状态中,可以加载一个只有名称的类,对于任意一个已加载的类,都能够知道它的方法 和属性,对于任意一个对象,都能调用它的任意一个方法和属性。
加载完类之后,在堆内存(HotSpot虚拟机是在方法区),就会产生一个Class对象(一个类只用一个Class 对象),这个对象包含整个类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,通过这个镜子可以个看到 类的结构,所以我们称之为“反射”。
Class类介绍
jdk对Class的介绍:
Class类的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。 Class没有公共构造方法。Class对象是在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。
总结:
Class类的对象包含了某个被加载类的结构,一个被加载类的对应一个Class对象。
当一个类被加载,或当加载器的defineClass()被JVM掉用,JVM便自动产生一个Class对象。
Class类是反射的根源。
获取Class对象
public class ClassTest {
public static void main(String[] args) throws ClassNotFoundException {
// (1)forName()获取Class对象(最常用)
Class clazz1 = Class.forName("reflection.Student");
System.out.println(clazz1.hashCode());
// (2).class获取Class对象
Class clazz2 = String.class;
System.out.println(clazz2.hashCode());
// (3)getClass()获取Class对象
// 一个类只对应一个Class对象
Class clazz3 = "reflection.Student".getClass();
System.out.println(clazz3.hashCode());
//每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象
int[] arr01 = new int[10];
int[][] arr02 = new int[30][3];
int[] arr03 = new int[30];
double[] arr04 = new double[10];
System.out.println(arr01.getClass().hashCode());
System.out.println(arr02.getClass().hashCode());
System.out.println(arr03.getClass().hashCode());
System.out.println(arr04.getClass().hashCode());
}
}
反射调用方法、属性、构造器
public class Student {
public String name;
private int 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;
}
private void myPrivateMethod(){
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//默认构造器反射的时候不要省略
public Student() {
}
}
public class ClassTest {
public static void main(String[] args) throws Exception {
// 获得类型
Class clazz = Class.forName("reflection.Student");
System.out.println(clazz.getName());
System.out.println(clazz.getSimpleName());
// 获得属性
// 获取全部方法
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("全部的属性:" + field.getName());
}
// 获取public修饰的方法
Field[] fields1 = clazz.getFields();
for (Field field : fields1) {
System.out.println("私有的属性:" + field.getName());
}
// 获得方法
// 获得全部方法
Method[] methods = clazz.getDeclaredMethods();
// 方法名字 + 无参数
Method m01 = clazz.getDeclaredMethod("getName", null);
// 方法名 + 有参数
Method m02 = clazz.getDeclaredMethod("setName", String.class);
for(Method m:methods){
System.out.println("方法:"+m);
}
// 获得构造器
Constructor[] constructors = clazz.getDeclaredConstructors();
Constructor c = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println("获得构造器:"+c);
for(Constructor temp:constructors){
System.out.println("构造器:"+temp);
}
}
}
//反射生成对象、调用普通方法、修改属性
public class ClassTest3 {
public static void main(String[] args) throws Exception {
//默认构造器产生对象
Class<Student> clazz = (Class<Student>) Class.forName("reflection.Student");
System.out.println(clazz.newInstance());
//指定构造器产生对象
Constructor<Student> c = clazz.getDeclaredConstructor(String.class, int.class);
Student student = c.newInstance("xiaoming", 12);
System.out.println("指定构造器产生对象后获取姓名: " + student.getName());
//反射调用普通方法
Method m = clazz.getDeclaredMethod("setName", String.class);
m.invoke(student, "XIAOHUA ");
System.out.println("反射调用普通方法修改姓名后获取姓名: " + student.getName());
//修改该属性
Student student1 = clazz.newInstance();
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
field.set(student1, "wjk");
System.out.println(student1.getName());
System.out.println(field.get(student1));
}
}
反射的效率
setAccessible(boolean flag)
(1) 将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
(2) 设置false效率提高。
//验证
public class ClassTest4 {
public static void test1() {
Student student = new Student();
long start = System.currentTimeMillis();
for (Long i = 1L; i < 1000000L; i++) {
student.getName();
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static void test2() throws Exception {
Student student = new Student();
Class clazz = student.getClass();
Method method = clazz.getDeclaredMethod("getName", null);
long start = System.currentTimeMillis();
for (Long i = 1L; i < 1000000L; i++) {
method.invoke(student);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static void test3() throws Exception {
Student student = new Student();
Class clazz = student.getClass();
Method method = clazz.getDeclaredMethod("getName", null);
method.setAccessible(true);
long start = System.currentTimeMillis();
for (Long i = 1L; i < 1000000L; i++) {
method.invoke(student);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static void main(String[] args) throws Exception {
test1();
test2();
test3();
}
}
//结果
37
72
48
反射操作泛型
public class ClassTest5 {
public static void test1(List<String> strings, Map<String, Object> map) {
System.out.println("test1");
}
public static List<String> test2() {
return null;
}
public static void main(String[] args) throws Exception {
Class clazz = ClassTest5.class;
Method m = clazz.getMethod("test1", List.class, Map.class);
Type[] t = m.getGenericParameterTypes();
for (Type type : t) {
System.out.println("#" + type);
if (type instanceof ParameterizedType) {
Type[] genericTypes = ((ParameterizedType) type).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("泛型类型:" + genericType);
}
}
}
Method m2 = ClassTest5.class.getMethod("test2", null);
Type returnType = m2.getGenericReturnType();
if (returnType instanceof ParameterizedType) {
Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("返回值,泛型类型:" + genericType);
}
}
}
}
//结果
#java.util.List<java.lang.String>
泛型类型:class java.lang.String
#java.util.Map<java.lang.String, java.lang.Object>
泛型类型:class java.lang.String
泛型类型:class java.lang.Object
返回值,泛型类型:class java.lang.String
反射操作注解
参考:http://my.oschina.net/u/2361475/blog/597726