java基础学习-反射

反射

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()方法:
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");
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"});
综合实例
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()方法去执行该方法,否则不执行。

反射机制和注解的综合使用

测试目标类:
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());
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章