反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
1)关于机制
Reflection 是Java被视为动态关键性质。这个机制允许程序在APIs取得任何一个已知名称的cmodifiers(诸如public, stati例如Object)、实现之interfa,也包括fields和methods的所变fields内容或调用methods
2)Java 反射机制主要提供了以下功能:
• 在运行时判断任意一个对象所属的类。
• 在运行时构造任意一个类的对象。
• 在运行时判断任意一个类所具有的成员变量和方法。
• 在运行时调用任意一个对象的方法
Java反射机制实现
1)实现Java反射机制
主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
– Class类:代表一个类。
– Field 类:代表类的成员变量(成员变量也称为类的属性)。
– Method类:代表类的方法。
– Constructor 类:代表类的构造方法。
– Array类:提供了动态创建数组,以及访问数组的元素的静态方法
2)获取class的三种方式
a) 使用Class类的静态方法forName:Class.forName(“java.lang.String”);
Class<?> classType = Class.forName(“java.lang.Object”);
Method[] methods = classType.getDeclaredMethods();
b) 使用类的.class 语法:String.class;
Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
Method addMethod = classType.getMethod("add", new Class[] { int.class,
int.class });
Object result = addMethod.invoke(invokeTester, new Object[]{1, 2});
c) 使用对象的getClass()方法:
主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
– Class类:代表一个类。
– Field 类:代表类的成员变量(成员变量也称为类的属性)。
– Method类:代表类的方法。
– Constructor 类:代表类的构造方法。
– Array类:提供了动态创建数组,以及访问数组的元素的静态方法
2)获取class的三种方式
a) 使用Class类的静态方法forName:Class.forName(“java.lang.String”);
Class<?> classType = Class.forName(“java.lang.Object”);
Method[] methods = classType.getDeclaredMethods();
b) 使用类的.class 语法:String.class;
Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
Method addMethod = classType.getMethod("add", new Class[] { int.class,
int.class });
Object result = addMethod.invoke(invokeTester, new Object[]{1, 2});
c) 使用对象的getClass()方法:
Fruit e = new Fruit();
classType = (Class<Fruit>) e.getClass();
3)若想通过类的不带参数的构造方法来生成对象,我们有两种方式
a) 先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可
Class<?> classType = String.class;
Object obj = classType.newInstance();
b) 先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
c)若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});
Object obj = cons.newInstance(new Object[]{“hello”, 3});
4)对象数组
Class<?> classType = Class.forName("java.lang.String");
classType = (Class<Fruit>) e.getClass();
3)若想通过类的不带参数的构造方法来生成对象,我们有两种方式
a) 先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可
Class<?> classType = String.class;
Object obj = classType.newInstance();
b) 先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
c)若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});
Object obj = cons.newInstance(new Object[]{“hello”, 3});
4)对象数组
Class<?> classType = Class.forName("java.lang.String");
Object array = Array.newInstance(classType, 10);
Array.set(array, 5, "hello");
String str = (String)Array.get(array, 5);//hello
5)多维数组
int[] dims = new int[] { 5, 10, 15 };
Object array = Array.newInstance(Integer.TYPE, dims);
Object arrayObj = Array.get(array, 3);
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][]) array;
6)访问私有
Private p = new Private();
Class<?> classType = p.getClass();
Field field = classType.getDeclaredField("name");//获取属性
field.setAccessible(true);//压制Java对访问修饰符的检查
field.set(p, "lisi");
Private p = new Private();
Class<?> classType = p.getClass();
//获取属性
Method method=classType.getDeclaredMethod("hello",new Class[] { String.class });
method.setAccessible(true);//压制Java的访问控制检查
String str = (String)method.invoke(p, new Object[]{"zhangsan"});
Array.set(array, 5, "hello");
String str = (String)Array.get(array, 5);//hello
5)多维数组
int[] dims = new int[] { 5, 10, 15 };
Object array = Array.newInstance(Integer.TYPE, dims);
Object arrayObj = Array.get(array, 3);
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][]) array;
6)访问私有
Private p = new Private();
Class<?> classType = p.getClass();
Field field = classType.getDeclaredField("name");//获取属性
field.setAccessible(true);//压制Java对访问修饰符的检查
field.set(p, "lisi");
Private p = new Private();
Class<?> classType = p.getClass();
//获取属性
Method method=classType.getDeclaredMethod("hello",new Class[] { String.class });
method.setAccessible(true);//压制Java的访问控制检查
String str = (String)method.invoke(p, new Object[]{"zhangsan"});
综合实例
public class TestReflection {
public static void main(String[] args) throws Exception {
Class<?> classType = null;
//获取类方式一
classType = Class.forName("com.Fruit");
//获取类方式二
classType = Fruit.class;
//获取类方式三
Fruit e = new Fruit();
classType = (Class<Fruit>) e.getClass();
//实例方式一
Object invokeTester = classType.newInstance();
//实例方式二 利用构造
Constructor cons = classType.getConstructor(new Class[]{});
invokeTester = cons.newInstance(new Object[]{});
//方式三 利用带参构造
cons = classType.getConstructor(new Class[]{String.class, String.class});
invokeTester = cons.newInstance(new Object[]{"apple", "red"});
Method addMethod = classType.getMethod("add", new Class[] { int.class,
int.class });
Object result = addMethod.invoke(invokeTester, new Object[] { 1, 2 });
System.out.println(result.toString());//3
//对象数组
classType = Class.forName("java.lang.String");
Object array = Array.newInstance(classType, 10);
Array.set(array, 5, "hello");
String str = (String)Array.get(array, 5);
System.out.println(str);//hello
//多维数组
int[] dims = new int[] { 5, 10, 15 };
Object arrayOut = Array.newInstance(Integer.TYPE, dims);
Object arrayObj = Array.get(arrayOut, 3);
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][]) arrayOut;
//访问私有方法
classType = Fruit.class;
Fruit fruit = new Fruit();
Field field = classType.getDeclaredField("price");
field.setAccessible(true);//压制Java对访问修饰符的检查
field.set(fruit, 5);
System.out.println(fruit.getPrice());//5
Method method=classType.getDeclaredMethod("sell",new Class[] { String.class });
method.setAccessible(true);//压制Java的访问控制检查
String methodstr = (String)method.invoke(fruit, new Object[]{"suning"});//sell
}
}
反射与框架
没有反射,很多框架就不存在了。(No Reflection,No most frameworks)。
比如读取配置文件的字符串生成实体(如果是配置则结合注解读取)
JUnit4的执行的一般流程:
a) 首先获得待测试类所对应的Class对象。
b) 然后通过该Class对象获得当前类中所有public方法所对应的Method数组。
c) 遍历该Method数组,取得每一个Method对象
d) 调用每个Method对象的isAnnotationPresent(Test.class)方法,判断该方法是否被Test注解所修饰。
e) 如果该方法返回true,那么调用method.invoke()方法去执行该方法,否则不执行。
比如读取配置文件的字符串生成实体(如果是配置则结合注解读取)
JUnit4的执行的一般流程:
a) 首先获得待测试类所对应的Class对象。
b) 然后通过该Class对象获得当前类中所有public方法所对应的Method数组。
c) 遍历该Method数组,取得每一个Method对象
d) 调用每个Method对象的isAnnotationPresent(Test.class)方法,判断该方法是否被Test注解所修饰。
e) 如果该方法返回true,那么调用method.invoke()方法去执行该方法,否则不执行。
反射机制和注解的综合使用
测试目标类:
public class Goal {
@MyAnnotation(hello = "aaa", world = "bbb")
@Deprecated
@SuppressWarnings("unchecked")
public void output() {
System.out.println("output something!");
}
}
注解类:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
String hello() default "hello u";
String world();
}
测试:
public class Test {
public static void main(String[] args) throws Exception {
//反射类
Class<?> classType = Goal.class;
Object myTest = classType.newInstance();
Method method = classType.getDeclaredMethod("output", new Class[]{});
//注解处理
if(method.isAnnotationPresent(MyAnnotation.class)) {
method.invoke(myTest, new Object[]{});
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
String hello = myAnnotation.hello();
String world = myAnnotation.world();
System.out.println(hello + ", " + world);
}
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation.annotationType().getName());
}
}
}