简介java反射机制

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射提供了在运行时,获取类信息的方式。而不必编译器在编译时必须知道该类(这样,使得java作为静态语言拥有了动态语言的特性)。
反射机制主要提供了以下功能: 
1.在运行时判断任意一个对象所属的类;
2.在运行时构造任意一个类的对象;
3.在运行时判断任意一个类所具有的成员变量和方法;
4.在运行时调用任意一个对象的方法;
5.生成动态代理。

Class对象,包含了与类相关的信息,每当编写并编译一个新类,就会产生一个Class对象,及是保存在一个同名的.class文件中。一个类的所有对象就是根据这个类被加载进内存的Class对象创建的。
运行的时候,某个类无论生成多少个对象,他们都会对应同一个Class对象,它表示正在运行程序中的类和接口。

如何取得操作类的Class对象,常用的有三种方式:
1.调用Class的静态方法forName。
2.使用类的.class。
3.调用对象的getClass方法。
package com;

public class TestMain {
	public static void main(String[] args) {
		Class c = null;
		try {
			c = Class.forName("com.Test");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//
		c = Test.class;
		//
		Test t = new Test();
		c = t.getClass();
	}
}

class Test {

}

使用java的反射,一般需要遵循三步:
1.获得你想操作类的Class对象
2.通过第一步获得的Class对象去取得操作类的方法或是属性名

3.操作第二步取得的方法或是属性

public class TestMain {
	public static void main(String[] args) {
		Class c = null;
		try {
			// 获取Class对象
			c = Class.forName("com.Test");
			// 获取method
			Method m = c.getMethod("write", String.class);
			// 操作属性
			String b = (String) m.invoke(c.newInstance(), "test");
			// 打印返回值
			System.out.println(b);
		} catch (ClassNotFoundException 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 (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();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class Test {
	public String write(String s) {
		System.out.println(s);
		return "back:" + s;
	}
}


主要的概念信息:
1.Class 类的实例表示正在运行的 Java 应用程序中的类和接口(枚举是一种类,注释是一种接口)。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。 
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的

2.Method提供关于类或者接口上单独某个方法及如何访问该方法的信息。所反映的可能是类方法,实例方法或者抽象方法。

Method 允许在匹配要调用的实参与底层方法的形参时进行扩展转换;但如果要进行收缩转换,则会抛出 IllegalArgumentException。

3.Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。 
Array 允许在执行 get 或 set 访问操作期间进行扩展转换,但如果将发生收缩转换,则抛出一个 IllegalArgumentException。 

下面介绍下常见的一些用途:

public class TestMain {
	public static void main(String[] args) {
		Class c = null;
		try {
			c = Class.forName("com.ReBean");
			// 获取包
			System.out.println("包:" + c.getPackage().getName());
			// 获取超类
			System.out.println("超类: " + c.getSuperclass());
			// 获取简称
			System.out.println("简称:" + c.getSimpleName());
			// 获取完整名称
			System.out.println("路径:" + c.getName());
			// 获取注释
			System.out.println("注释:" + c.getAnnotation(ReBean.class));

			// 获取类或者接口的整型修饰符
			System.out.println("修饰符:" + c.getModifiers());
			// 获取指定属性
			System.out.println("指定属性: " + c.getDeclaredField("s"));
			// 获取指定构造方法
			System.out.println("指定构造方法:" + c.getConstructor(String.class));
			// 获取指定方法
			System.out.println("指定方法:"
					+ c.getDeclaredMethod("setS", String.class));

			// 获取所有属性
			System.out.println("打印所有属性:");
			Field[] arrfield = c.getDeclaredFields();
			for (Field field : arrfield) {
				System.out.println(field);
			}

			// 获取所有构造方法
			System.out.println("打印所有构造方法:");
			Constructor[] arrconstructor = c.getConstructors();
			for (Constructor cons : arrconstructor) {
				System.out.println(cons);
			}

			// 获取所有方法
			System.out.println("打印所有方法:");
			Method[] arrmethod = c.getMethods();
			for (Method method : arrmethod) {
				System.out.println(method);
			}

			// 获取所有接口
			System.out.println("打印所有接口:");
			Class[] arrinters = c.getInterfaces();
			for (Class in : arrinters) {
				System.out.println(in);
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

interface ReInterface {
	void r_print();
}

class ReBean implements ReInterface {
	private String s0;
	private String s= "**";

	public ReBean() {
	}

	public ReBean(String s) {
		this.s = s;
	}

	public String getS() {
		return s;
	}

	public void setS(String s) {
		this.s = s;
	}

	public String back() {
		return "back:" + s;
	}

	@Override
	public void r_print() {
		// TODO Auto-generated method stub
		System.out.println("r_print");
	}

}

打印结果:

包:com
超类: class java.lang.Object
简称:ReBean
路径:com.ReBean
注释:null
修饰符:0
指定属性: private java.lang.String com.ReBean.s
指定构造方法:public com.ReBean(java.lang.String)
指定方法:public void com.ReBean.setS(java.lang.String)
打印所有属性:
private java.lang.String com.ReBean.s0
private java.lang.String com.ReBean.s
打印所有构造方法:
public com.ReBean()
public com.ReBean(java.lang.String)
打印所有方法:
public void com.ReBean.setS(java.lang.String)
public java.lang.String com.ReBean.back()
public void com.ReBean.r_print()
public java.lang.String com.ReBean.getS()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
打印所有接口:
interface com.ReInterface

在获取对象的时,有时候考虑到其是否是公共的,因此针对注释,成员,构造方法,普通方法和字段都有两个不同的方法:

1.获取所有的。如获取所有声明的字段:

Field getDeclaredField(String name) 
          返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段 

2.获取公共的。如获取公共的成员字段:

Field getField(String name) 
          返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 


Class.newInstance新建的各个实例之间是没关系的,就是新建的不同对象,其他的操作属性和方法,道理一样,就不多说了。

 T newInstance() 
          创建此 Class 对象所表示的类的一个新实例。 
这个实例,也许可以帮助你理解。

                Class c1 = null;
		Class c2 = null;
		Method m1 = null;
		Method m2 = null;
		try {
			c1 = Class.forName("com.ReBean");
			ReBean re=(ReBean) c1.newInstance();
			m1 = c1.getMethod("setS", String.class);
			m1.invoke(re, "test c1");
			c2 = Class.forName("com.ReBean");
			m2 = c2.getMethod("back");
			m2.invoke(re);
			
			m1 = c1.getMethod("setS", String.class);
			m1.invoke(c1.newInstance(), "test c1");
			c2 = Class.forName("com.ReBean");
			m2 = c2.getMethod("back");
			m2.invoke(c2.newInstance());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
执行效果:
back:test c1
back:**






你可能感兴趣的:(java,反射)