反射机制的详细代码理解

原创 2017年01月03日 15:02:48

1.类的加载器以及如何获取Class的实例

public class TestReflection {
	
	//关于类的加载器:ClassLoader
	@Test
	public void test5() throws Exception{
		ClassLoader loader1 = ClassLoader.getSystemClassLoader();//获取系统类加载器
		System.out.println(loader1);
		
		ClassLoader loader2 = loader1.getParent();//获取扩展类加载器
		System.out.println(loader2);
		
		ClassLoader loader3 = loader2.getParent();//引导类加载器无法被获取
		System.out.println(loader3);
		
		Class class1 = Person.class;
		ClassLoader loader4 = class1.getClassLoader();
		System.out.println(loader4);
		
		String className = "java.lang.Object";
		Class class2 = Class.forName(className);
		ClassLoader loader5 = class2.getClassLoader();//引导类加载器无法被获取
		System.out.println(loader5);
		
		ClassLoader loader = this.getClass().getClassLoader();
		InputStream is = loader.getResourceAsStream("com\\panda\\java\\jdbc.properties");
		Properties pros = new Properties();
		pros.load(is);
		String name = pros.getProperty("user");
		System.out.println(name);
		
		String password = pros.getProperty("password");
		System.out.println(password);
	}
	
	//如何获取Class的实例(3种)
	@Test
	public void test4() throws ClassNotFoundException{
		//1.调用运行时类本身的.class属性
		Class class1 = Person.class;
		System.out.println(class1.getName());
		
		Class class2 = String.class;
		System.out.println(class2.getName());
		
		//2.通过运行时类的对象获取
		Person person = new Person();
		Class class3 = person.getClass();
		System.out.println(class3.getName());
		
		//3.通过Class的静态方法获取
		String className = "com.panda.java.Person";
		Class class4 = Class.forName(className);
		System.out.println(class4.getName());
		
		//4.通过类的加载器
		ClassLoader classLoader = this.getClass().getClassLoader();
		Class class5 = classLoader.loadClass(className);
		System.out.println(class5.getName());
		
	}
	
	/*
	 * java.lang.class:是反射的源头
	 * 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
	 * 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
	 * 1.每一个运行时类只加载一次!
	 * 2.有了Class的实例以后,我们才可以进行如下的操作:
	 *     1)*创建对应的运行时类的对象
	 *     2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
	 *     3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
	 *     4)反射的应用:动态代理
	 */
	@Test
	public void test3(){
		Person person = new Person();
		Class class1 = person.getClass();//通过运行时类的对象,调用其getClass(),返回其运行时类
		System.out.println(class1);
	}
	
	//有了反射,可以通过反射创建一个类的对象,并调用其中的结构
	@Test
	public void test2() throws Exception{
		Class class1 = Person.class;
		
		//1.创建class1对应的运行时类Person类的对象
		Person person = (Person) class1.newInstance();
		//2.通过反射调用运行时类的指定的属性
		Field f1 = class1.getField("name");
		f1.set(person, "liuDeHua");
		System.out.println(person);
		
		Field f2 = class1.getDeclaredField("age");
		f2.setAccessible(true);
		f2.set(person, 20);
		System.out.println(person);
		
		//3.通过反射调用运行时类的指定的方法
		Method m1 = class1.getMethod("show");
		m1.invoke(person);
		
		Method m2 = class1.getMethod("display", String.class);
		m2.invoke(person, "CHN");
	}
	//在有反射以前,如何创建一个类的对象,并调用其中的方法、属性
	@Test
	public void test1(){
		Person person = new Person();
		person.setAge(10);
		person.setName("liming");
		System.out.println(person);
		person.show();
		//person.display("中国");
	}
}
2.通过反射获取对应的运行时类的属性

public class TestField {
	//获取对应的运行时类的属性
	@Test
	public void test1(){
		Class class1 = Person.class;
		
		//1.getFields(),只能获取到运行时类中极其父类中声明为public的属性
		Field[] fields = class1.getFields();
		for (int i = 0; i < fields.length; i++) {
			System.out.println(fields[i]);
		}
		System.out.println();
		//2.getDeclaredFields(),获取运行时类本身声明的所有的属性
		Field[] fields2 = class1.getDeclaredFields();
		for(Field f : fields2){
			System.out.println(f.getName());
		}
	}
	/*
	 * 权限修饰符 变量类型 变量名
	 * 获取属性的各个部分的内容
	 */
	@Test
	public void test2(){
		Class class1 = Person.class;
		Field[] fields2 = class1.getDeclaredFields();
		for(Field f : fields2){
			//1.获取每个属性的权限修饰符
			int i = f.getModifiers();
			String str = Modifier.toString(i);
			System.out.print(str + " ");
			
			//2.获取属性的变量类型
			Class type = f.getType();
			System.out.print(type.getName() + " ");
			
			//3.获取属性名
			System.out.print(f.getName());
	
			System.out.println();
		}
	}
	
	//调用运行时类指定的属性
	@Test
	public void test3() throws Exception, SecurityException{
		Class class1 = Person.class;
		//1.获取指定的属性
		//getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
		Field name = class1.getField("name");
		//2.创建运行时类的对象
		Person person = (Person) class1.newInstance();
		//3.将运行时类的指定的属性赋值
		name.set(person, "Jack");
		System.out.println(person);
		
		System.out.println();
		//getDeclaredField(String fieldName):获取运行时类中指定属性名为fieldName的属性
		Field age = class1.getDeclaredField("age");
		//由于属性权限修饰的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作
		age.setAccessible(true);
		age.set(person, 22);
		System.out.println(person);
	}
}

3.通过反射获取运行时类的方法

public class TestMethod {
	//1.获取运行时类的方法
	@Test
	public void test1(){
		Class class1 = Person.class;
		//1.getMethods(),获取运行时类及其父类中所有的声明为public的方法
		Method[] methods = class1.getMethods();
		for(Method m : methods){
			System.out.println(m);
		}
		System.out.println();
		
		//2.getDeclaredMethods(),获取运行时类本身声明的所有的方法
		Method[] methods2 = class1.getDeclaredMethods();
		for(Method m : methods2){
			System.out.println(m);
		}
	}
	
	
	//注解 权限修饰符 返回值类型 方法名 形参列表 异常
	@Test
	public void test2(){
		Class class1 = Person.class;
		
		Method[] methods2 = class1.getDeclaredMethods();
		for(Method m : methods2){
			//1.注解
			Annotation[] ann = m.getAnnotations();
			for(Annotation a : ann){
				System.out.println(a);
			}
			
			//2.权限修饰符
			String str = Modifier.toString(m.getModifiers());
			System.out.print(str + " ");
			
			//3.返回值类型
			Class returnType = m.getReturnType();
			System.out.print(returnType.getName() + " ");
			
			//4.方法名
			System.out.print(m.getName() + " ");
			
			//5.形参列表
			System.out.print("(");
			Class[] params = m.getParameterTypes();
			for(Class p : params){
				System.out.print(p.getName() + " ");
			}
			System.out.print(")");
			
			//6.异常类型
			Class[] exps = m.getExceptionTypes();
			for (int i = 0; i < exps.length; i++) {
				System.out.println(exps[i].getName());
			}
			System.out.println();
		}
	}
	//调用运行时类中的指定的方法
	@Test
	public void test3() throws Exception{
		Class class1 = Person.class;
		//getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
		Method m1 = class1.getMethod("show");
		Person person = (Person) class1.newInstance();
		//调用指定的方法:Object invoke(Object obj,Object ... obj)
		Object returnVal = m1.invoke(person);//我是一个人
		System.out.println(returnVal);//null
		
		Method m2 = class1.getMethod("toString");
		Object returnVal1 = m2.invoke(person);
		System.out.println(returnVal1);//Person [name=null,age=0]
		
		//对于运行时类中静态方法的调用
		Method m3 = class1.getMethod("info");
		m3.invoke(Person.class);//中国人
		
		//getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
		Method m4 = class1.getDeclaredMethod("display",String.class);
		m4.setAccessible(true);
		Object value = m4.invoke(person,"CHN");//我的国籍是:CHN
		
	}
}
4.通过反射调用指定的构造器

public class TestConstructor {
	@Test
	public void test1() throws Exception{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		
		//创建对应的运行时类的对象.使用newInstan(),实际上就是调用了运行时类的空参的构造器
		//要想能创建成功:1.要求对应的运行时类要有空参的构造器。2.构造器的权限修饰符的权限要足够
		Object object = class1.newInstance();
		Person person = (Person) object;
		System.out.println(person);
	}
	
	@Test
	public void test2() throws ClassNotFoundException{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		
		Constructor[] cons = class1.getDeclaredConstructors();
		
		for(Constructor constructor : cons){
			System.out.println(constructor);
		}
	}
	//调用指定的构造器,创建运行时类的对象
	@Test
	public void test3() throws Exception{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		Constructor constructor = class1.getDeclaredConstructor(String.class,int.class);
		constructor.setAccessible(true);
		Person person = (Person) constructor.newInstance("李明",21);
		System.out.println(person);
	}
} 
5.通过反射获取其他
public class TestOthers {
	//1.获取运行时类的父类
	@Test
	public void test1(){
		Class class1 = Person.class;
		Class supercClass = class1.getSuperclass();
		
		System.out.println(supercClass);
	}
	//2.获取带泛型的父类
	@Test
	public void test2(){
		Class class1 = Person.class;
		Type type = class1.getGenericSuperclass();
		
		System.out.println(type);
	}
	
	//3.获取父类的泛型
	@Test
	public void test3(){
		Class class1 = Person.class;
		Type type = class1.getGenericSuperclass();
		
		ParameterizedType pType = (ParameterizedType) type;
		Type[] ars = pType.getActualTypeArguments();
		System.out.println(((Class)ars[0]).getName());
	}
	
	//4.获取实现的接口
	@Test
	public void test4(){
		Class class1 = Person.class;
		Class[] interfaces = class1.getInterfaces();
		
		for(Class c : interfaces){
			System.out.println(c);
		}
	}
	
	//5.获取所在的包
	@Test
	public void test5(){
		Class class1 = Person.class;
		Package package1 = class1.getPackage();
		
		System.out.println(package1);
	}
	
	//6.获取注解
	@Test
	public void test6(){
		Class class1 = Person.class;
		Annotation[] anns = class1.getAnnotations();
		
		for(Annotation annotation : anns){
			System.out.println(annotation);
		}
	}
}
附录:

1.父类Creature

public class Creature<T> {
	public double weight;
	
	public void breath(){
		System.out.println("呼吸!");
	}
}

2.Person类

@MyAnnotation(value = "panda")
public class Person extends Creature<String> implements Comparable,MyInterface{

	public String name;
	private int age;
	int id;
	
	public Person() {
		super();
	}

	public Person(String name) {
		super();
		this.name = name;
	}

	public Person(String name, int age) {
		super();
		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 int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@MyAnnotation(value = "abc123")
	public void show(){
		System.out.println("我是一个人");
	}
	private void display(String nation)throws Exception{
		System.out.println("我的国籍是:" + nation);
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	public static void info(){
		System.out.println("中国人!");
	}
	class Bird{
		
	}
}
3.注解类

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	String value();
}
4.接口类
public interface MyInterface extends Serializable{

}
5.jdbc.properties文件
user=root
password=123456











相关文章推荐

java反射机制相当详细的资料

  • 2010年09月02日 15:45
  • 166KB
  • 下载

C#反射机制详细概括

  • 2013年04月28日 18:39
  • 26KB
  • 下载

Java反射机制详细示例及动态代理

反射可以在程序运行过程中动态获取类的相关信息,包括类由哪个类加载器进行加载,类中的成员变量,成员方法,访问修饰符,返回值类型,构造方法等等; 首先要获取类的Class对象.获取Class对象有三种方法...

反射机制代码实例的描述

  • 2009年05月21日 00:14
  • 12KB
  • 下载

JAVA反射机制原理及代码

  • 2011年12月29日 16:06
  • 135KB
  • 下载

c++反射机制的实现(完整代码,相当靠谱)

下面是c++反射机制的一个实现,比较完整。出自:http://www.oschina.net/code/snippet_230828_9913 虽然这是windows下写的代码,但是比较合理,非人云...
  • hzhsan
  • hzhsan
  • 2013年05月12日 09:18
  • 7397

Java 反射机制 代码的实例

  • 2009年07月27日 18:42
  • 15KB
  • 下载

JAVA反射机制的入门代码

  • 2013年04月26日 16:30
  • 7KB
  • 下载

Android中利用反射机制创建实例的代码

反射机制创建对象的最大优点是利用了Java语言的多态性,这样使得代码更加灵活。在观看源码的时候有这样一段代码就是典型的例子,可以借鉴: 出自SystemServiceManager的startSer...

抄google工程师的代码:通过读setting的源代码,利用反射机制调用系统隐藏的API

步骤: 1.根据设置中的界面,搜索关键的字符串信息,通常我们首先跟踪到string.xml或者某个布局文件中。 2.找到该字符串相应的id获得点击事件的函数名,再次搜索,1到2次就能跟踪到一个sr...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:反射机制的详细代码理解
举报原因:
原因补充:

(最多只允许输入30个字)