Java反射机制

如果要通过一个对象找到一个类的名称,此时就需要用到反射机制(反射技术是用来做框架的,一般情况下Java私有对象不能被访问,但是暴力反射可以访问私有对象)

任何一个类如果没有明确地声明继承自哪个父类的时候,则默认继承Object类,所以getClass()方法是Object类中的。

文件在包java_reflect目录

 

// 类名:Y
// 属性:
// 方法:
class Y{
	
}

 

class Y{
	
}

//主类
//Function        : 	GetClass_demo;
public class GetClass_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Y y = new Y();
		System.out.println(y.getClass().getName());
	}

}

 输出  

 

 

 

 

实例化Class类对象的3种方法

class Y{
	
}

public class GetClass_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		
		Class<?> c1 = null;
		Class<?> c2 = null;
		Class<?> c3 = null;
		try{
			c1 = Class.forName("java_basic.Y");							//通过forName()方法实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		
		c2 = new Y().getClass();									//通过Object类中的方法实例
			
		c3 = Y.class;													//通过类.class实例化
		System.out.println("类名称"+c1.getName());
		System.out.println("类名称"+c2.getName());
		System.out.println("类名称"+c3.getName());
	}

}

 输出   

 

Class类的使用

Class类在开发中最常见的用法就是实例化对象的操作,即可以通过一个给定的字符串(此字符串包含了完整的“包.类”的路径)来实例化一个类的对象

 

  1.通过无参构造实例化对象

如果要想通过Class类对象实例化其他类的对象,则可以使用newInstance()方法,但是必须要保证被实例化的类中存在一个无参构造方法

public class InstanceClass_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c = null;		//指定泛型
		try{
			c = Class.forName("person");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		person per = null;			//声明person对象
		try{
			per = (person)c.newInstance();	//实例化person对象
		}catch(Exception e){
			e.printStackTrace();
		}
		per.setAge(30);
		per.setName("张三");
		System.out.println(per);
	}

}

输出  

 

  2.调用有参构造实例化对象

import java.lang.reflect.Constructor;

public class InstanceClass_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c = null;		//指定泛型
		try{
			c = Class.forName("person");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		person per = null;						//声明person对象
		Constructor<?> cons[] = null;		//声明一个表示构造方法的数组
		cons = c.getConstructors();			//通过反射取得全部构造
		try{	
			per = (person) cons[0].newInstance("张三",30);	//实例化person对象
		}catch(Exception e){
			e.printStackTrace();
		}
//		per.setAge(30);
//		per.setName("张三");
		System.out.println(per);
	}

}

 输出  

 

可以通过反射得到一个类的完整结构,需要使用到java.lang.reflect包中的以下几个类。

Constructor:表示类中的构造方法

Field:表示类中的属性

Method:表示类中的方法

这3个类都是AccessibleObject类中的子类

interface China{
	public static final String NATIONAL = "China";
	public static final String AUTHOR = "张三";
	public void sayChina();
	public String sayHello(String name,int age);
}

class Person_5 implements China{

	private String name;
	private int age;
	
	public Person_5(){		//无参构造方法
		
	}
	
	public Person_5(String name) {	//声明两个参数的构造方法
		super();
		this.name = name;
	}


	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 Person_5(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public void sayChina() {
		// TODO 自动生成的方法存根
		System.out.println("作者:"+AUTHOR+"国籍:"+NATIONAL);
	}

	@Override
	public String sayHello(String name, int age) {
		// TODO 自动生成的方法存根
		return name+"age:"+age;
	}


	
}

public class ConstructorClass_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		Class<?> c[] = c1.getInterfaces();			//取得实现的全部接口
		for(int i=0;i<c.length;i++){
			System.out.println("实现的接口名称:"+c[i].getName());
		}
		
	}

}

 

取得父类

一个类可以实现多个接口,但是只能继承一个父类,所以如果要取得一个类的父类,可以直接使用class类中的getSuperclass()方法

interface China{
	public static final String NATIONAL = "China";
	public static final String AUTHOR = "张三";
	public void sayChina();
	public String sayHello(String name,int age);
}

class Person_5 implements China{

	private String name;
	private int age;
	
	public Person_5(){		//无参构造方法
		
	}
	
	public Person_5(String name) {	//声明两个参数的构造方法
		super();
		this.name = name;
	}


	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 Person_5(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public void sayChina() {
		// TODO 自动生成的方法存根
		System.out.println("作者:"+AUTHOR+"国籍:"+NATIONAL);
	}

	@Override
	public String sayHello(String name, int age) {
		// TODO 自动生成的方法存根
		return name+"age:"+age;
	}


	
}

public class ConstructorClass_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		
		Class<?> c2 = c1.getSuperclass();			//取得父类
		System.out.println("实现的接口名称:"+c2.getName());
	}

}

 

取得全部构造方法

要取得一个类中的全部构造方法,则必须使用Class类中的getConstructors()方法

import java.lang.reflect.Constructor;

interface China{
	public static final String NATIONAL = "China";
	public static final String AUTHOR = "张三";
	public void sayChina();
	public String sayHello(String name,int age);
}

class Person_5 implements China{

	private String name;
	private int age;
	
	public Person_5(){		//无参构造方法
		
	}
	
	public Person_5(String name) {	//声明两个参数的构造方法
		super();
		this.name = name;
	}


	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 Person_5(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public void sayChina() {
		// TODO 自动生成的方法存根
		System.out.println("作者:"+AUTHOR+"国籍:"+NATIONAL);
	}

	@Override
	public String sayHello(String name, int age) {
		// TODO 自动生成的方法存根
		return name+"age:"+age;
	}


	
}

public class ConstructorClass_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		
		Constructor<?> c[] = c1.getConstructors();			//取得全部的构造方法
		for(int i=0;i<c.length;i++){
			System.out.println("全部的构造方法:"+c[i]);
		}
	}

}

 

取得全部方法

要取得一个类中的全部方法,可以使用Class类中的getMethods()方法,此方法返回一个Method类的对象数组。

如果要进一步取得方法的具体信息,例如,方法的参数、抛出的异常声明等,则就必须依靠Method类。

 

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class GetMethod_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		
		Method m[] = c1.getMethods();		//取得全部的方法
		for(int i=0;i<m.length;i++){				//循环输出
			Class<?> r = m[i].getReturnType();	//得到方法的返回值类型
			Class<?> p[] = m[i].getParameterTypes();	//得到全部的参数类型
			int xx = m[i].getModifiers();				//得到方法的修饰符,即public
			
			System.out.print(Modifier.toString(xx)+" ");	//还原修饰符
			System.out.print(r.getName()+" ");					//得到方法返回值
			System.out.print(m[i].getName());					//取得方法的名称
			System.out.print("(");
			for(int x=0;x<p.length;x++){
				System.out.print(p[x].getName()+" "+"arg"+x);	//输出参数
				if(x<p.length-1){
					System.out.print(",");
				}
			}
			Class<?> ex[] = m[i].getExceptionTypes();	//得到全部的异常抛出
			if(ex.length>0){													//判断是否有异常
				System.out.print(") throws ");
			}else{
				System.out.print(") ");
			}
			for(int j=0;j<ex.length;j++){								
				System.out.println(ex[j].getName());		//输出异常信息
				if(j<ex.length-1){
					System.out.println(",");
				}
			}
			System.out.println();
		}
	}

}

 

 

取得全部属性

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class GetMethod_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		
//		Method m[] = c1.getMethods();		//取得全部的方法
//		for(int i=0;i<m.length;i++){				//循环输出
//			Class<?> r = m[i].getReturnType();	//得到方法的返回值类型
//			Class<?> p[] = m[i].getParameterTypes();	//得到全部的参数类型
//			int xx = m[i].getModifiers();				//得到方法的修饰符,即public
//			
//			System.out.print(Modifier.toString(xx)+" ");	//还原修饰符
//			System.out.print(r.getName()+" ");					//得到方法返回值
//			System.out.print(m[i].getName());					//取得方法的名称
//			System.out.print("(");
//			for(int x=0;x<p.length;x++){
//				System.out.print(p[x].getName()+" "+"arg"+x);	//输出参数
//				if(x<p.length-1){
//					System.out.print(",");
//				}
//			}
//			Class<?> ex[] = m[i].getExceptionTypes();	//得到全部的异常抛出
//			if(ex.length>0){													//判断是否有异常
//				System.out.print(") throws ");
//			}else{
//				System.out.print(") ");
//			}
//			for(int j=0;j<ex.length;j++){								
//				System.out.println(ex[j].getName());		//输出异常信息
//				if(j<ex.length-1){
//					System.out.println(",");
//				}
//			}
//			System.out.println();
//		}
		
		{
			Field f[] = c1.getDeclaredFields();			//取得本类属性			
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType();			//取出属性的类型
				int mo = f[i].getModifiers();		//得到修饰符数字
				String priv = Modifier.toString(mo);	//取得属性的修饰符
				System.out.print("本类属性:");
				System.out.print(priv + " ");						//输出修饰符
				System.out.print(r.getName()+" "); 		//输出属性类型
				System.out.print(f[i].getName()); 			//输出属性名称
				System.out.println(" ;");
			}
		}
			
		{
			Field f[] = c1.getFields();			//取得父类公共属性			
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType();			//取出属性的类型
				int mo = f[i].getModifiers();		//得到修饰符数字
				String priv = Modifier.toString(mo);	//取得属性的修饰符
				System.out.print("本类属性:");
				System.out.print(priv + " ");						//输出修饰符
				System.out.print(r.getName()+" "); 		//输出属性类型
				System.out.print(f[i].getName()); 			//输出属性名称
				System.out.println(" ;");
			}
		}
		
		
	}

}

 

反射机制还可以调用类中的指定方法或指定属性,并且可以通过反射完成对数组的操作。

通过反射调用类中的方法

import java.lang.reflect.Method;

public class InvokeChina_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		try{
			Method met = c1.getMethod("sayChina");		//取得一个Method对象
			met.invoke(c1.newInstance());							//使用invoke进行调用,必须传递对象实例
		}catch(Exception e){
			e.printStackTrace();
		}
	}

}

 

可以向方法中传递两个参数

import java.lang.reflect.Method;

public class InvokeChina_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		try{
			
			Method met = c1.getMethod("sayHello",String.class,int.class);	//此方法需要两个参数
			String rv = null;			//接收方法的返回值
			rv = (String)met.invoke(c1.newInstance(),"李四",32);							//使用invoke进行调用,必须传递对象实例
			System.out.println(rv); 			
		}catch(Exception e){
			e.printStackTrace();
		}
	}

}

 

调用setter和getter方法

import java.lang.reflect.Method;

public class InvokeSetGet_demo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//指定泛型
		Object obj = null;		//声明一个对象
		try{
			c1 = Class.forName("Person_5");			//传入要实例化类的完整包.类名称
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
		try{
			obj = c1.newInstance();			//实例化操作对象
		}catch(InstantiationException | IllegalAccessException e){
			e.printStackTrace();
		}
		
		setter(obj, "name", "张三", String.class);
		setter(obj, "age", 25, int.class);
		System.out.println("姓名:");
		getter(obj, "name");
		System.out.println("年龄:");
		getter(obj, "age");
	}
	
	public static void setter(Object obj,String att,Object value,Class<?> type){
		try{
			Method met = obj.getClass().getMethod("set"+initStr(att),type);	//设置方法参数类型
			met.invoke(obj, value);				//调用方法
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void getter(Object obj,String att){
		try{
			Method met = obj.getClass().getMethod("get"+initStr(att));	
			System.out.println(met.invoke(obj)); 		//接收方法的返回值
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static String initStr(String old){
		String str = old.substring(0, 1).toUpperCase()+old.substring(1);	//首字母大写
		return str;
		
	}

}

 

直接操作类中的属性

import java.lang.reflect.Field;

public class InvokeField_demo {

	public static void main(String[] args) throws Exception {
		// TODO 自动生成的方法存根
		Class<?> c1 = null;		//声明Class对象
		Object obj = null;		//声明一个对象
		
		c1 =Class.forName("Person_5");	//实例化Class对象
		obj = c1.newInstance();					//实例化对象
		
		Field nameField = null;		//表示name属性
		Field ageField = null;			//表示age属性
		nameField = c1.getDeclaredField("name");	//取得name属性
		ageField = c1.getDeclaredField("age");			//取得age属性
		
		nameField.setAccessible(true); 						//将name属性设置成可被外部访问
		nameField.set(obj, "张三"); 								//设置name属性内容
		ageField.setAccessible(true); 							//将age属性设置成可被外部访问
		ageField.set(obj, 33); 											//设置age属性内容
		
		System.out.println("姓名:"+nameField.get(obj));	//通过get取得属性内容
		System.out.println("年龄:"+ageField.get(obj));
	}

}

通过反射操作数组

import java.lang.reflect.Field;
import java.lang.reflect.Array;

public class InvokeField_demo {

	public static void main(String[] args) throws Exception {
		// TODO 自动生成的方法存根
		
		int temp[] = {1,2,3};
		Class<?> c = temp.getClass().getComponentType();	//取得数组的Class对象
		
		System.out.println("类型:"+c.getName()); 				//得到数组类型名称
		System.out.println("长度:"+Array.getLength(temp)); 				//得到数组长度
		System.out.println("第一个内容:"+Array.get(temp,0)); 			//得到第一个内容
		Array.set(temp,0,6);		//修改第一个内容
		System.out.println("第一个内容:"+Array.get(temp,0)); 			//得到第一个内容
	}

}

 

posted @ 2016-03-18 16:25  tonglin0325  阅读(147)  评论(0编辑  收藏  举报