Java中的反射

Class

1.Class是一个用来描述类的类,封装了当前对象所对应的类的信息。
一个类中有属性,方法,构造器等。
2.Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等。
3.Class对象只能由系统建立对象,一个类在JVM中只会有一个Class实例。
4.封装了描述方法的Method,描述字段的Field,描述构造器的Constructor等属性。

获取Class对象的三种方式
1.通过类名获取 类名.class
2.通过对象获取 对象名.class
3.通过全类名获取 Class.forName(全类名) ,会抛出异常

//第一种方法获取class对象,new产生一个Animal对象和一个Class对象
		Animal animal = new Animal();
		//对象名获取类的Class对象
		Class anclass = animal.getClass();
		//输出类名
		System.out.println("对象名获取类名:"+anclass.getName());
		
		System.out.println();
		//第二种方式获取class对象,类名.class
		Class anclass2 = Animal.class;
		System.out.println("类名.class  获取类名:"+anclass2.getName());
		
		
		//第三种方法获取Class对象,常用这种方法
		
		//注意在运行期间一个类只有一个class对象产生
		
		
			// "包名+类名"
			Class getclass = Class.forName("Java反射.Animal");
			System.out.println("包名+类名   获取类名:"+getclass.getName());

反射是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API 取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
Java反射机制提供了以下功能:

  1. 在运行时构造任意一个类的对象;
  2. 在运行时获取任意一个类所具有的成员变量和方法;
  3. 在运行时调用任意一个对象的方法(属性)

反射获取构造方法:

System.out.println("获取该类的所有公有构造方法");
			//getclass.getConstructor(parameterTypes),其中parameterTypes可以设定多个或者没有参数
			Constructor[] conArray = getclass.getConstructors();
			
			//利用forech遍历输出
			System.out.println("共有   "+conArray.length+"  种公有构造方法");
			for(Constructor c : conArray) {
				System.out.println(c);
			}
			
			System.out.println();
			System.out.println("获取该类的所有构造方法");
			conArray = getclass.getDeclaredConstructors();
			System.out.println("共有   "+conArray.length+"  种构造方法");
			for(Constructor c : conArray) {
				System.out.println(c);
			}
			
			
			System.out.println();
			System.out.println("获取该类的公有无参构造方法");
			//()中填写的是参数的类型,返回描述无参构造函数的类对象
			Constructor con = getclass.getConstructor();
			System.out.println("返回的类对象  :"+con);
			
			//调用构造方法
			//这里使用newInstance方法来创建该构造方法的声明类的新实例对象
			Object obj = con.newInstance();
//			System.out.println("返回的对象"+obj);
//			Animal an = (Animal)obj;
//			System.out.println("返回的对象"+an);
			
			System.out.println();
			System.out.println("获取该类的私有构造方法并调用");
			con = getclass.getDeclaredConstructor(String.class);
			System.out.println("得到的私有构造方法  :"+con);
			
			//调用构造方法
			con.setAccessible(true);//暴力访问(忽略访问修饰符)
			obj = con.newInstance("10009");

反射获取成员变量

//获取字段
			System.out.println("获取所有公有的字段");
			Field[] fieldArray = getclass.getFields();
			//遍历输出
			for(Field f:fieldArray) {
				System.out.println(f);
			}
			
			System.out.println();
			System.out.println("获取所有字段");
			fieldArray = getclass.getDeclaredFields();
			//遍历输出
			for(Field f:fieldArray) {
				System.out.println(f);
			}
			
			System.out.println();
			System.out.println("获取公有字段并调用");
			Field f = getclass.getField("age");
			System.out.println(f);
			
			//获取一个对象  Animal对象
			Object obj1 = getclass.getConstructor().newInstance();
			//为字段赋值
			f.set(obj1, 3);
			Animal animal1 = (Animal)obj1;
			System.out.println("验证age的设置  :"+animal1.age);
			
			System.out.println();
			System.out.println("获取私有字段并调用");
			f = getclass.getDeclaredField("name");
			System.out.println(f);
			f.setAccessible(true);//暴力反射,解除私有限定
			//为私有字段赋值
			f.set(obj1, "elephant");
			System.out.println("验证私有name属性的设置  :"+animal1);
			

反射获取成员方法

//这里的方法还包含了Object父类继承而来的方法
			System.out.println("获取所有的公有方法");
			Method[] methodArray = getclass.getMethods();
			System.out.println("共有"+methodArray.length+"种公有方法");
			//遍历输出
			for(Method m : methodArray) {
				System.out.println(m);
			}
			
			System.out.println();
			System.out.println("获取所有的方法");
			methodArray = getclass.getDeclaredMethods();
			System.out.println("共有"+methodArray.length+"种方法");
			//遍历输出
			for(Method m : methodArray) {
				System.out.println(m);
			}
			
			System.out.println();
			System.out.println("获取公有的有参方法method2");
			//这里需要将方法中的Integer类型改为int类型才可以识别该方法,或者多多尝试运行几次
			Method m1 = getclass.getMethod("method2", int.class) ;
			System.out.println(m1);
			//实例化一个Animal对象
			Object obj2 = getclass.getConstructor().newInstance();
			m1.invoke(obj2, 34);
			
			System.out.println();
			System.out.println("获取私有的有参方法method3");
			//这里需要将方法中的Integer类型改为int类型才可以识别该方法,或者多多尝试几次
			Method m2 = getclass.getDeclaredMethod("method3", int.class, String.class);
			System.out.println(m2);
			m2.setAccessible(true);//解除私有限定
			//调用有参私有方法
			Object result = m2.invoke(obj2, 21,"tiger");
			

反射获取main方法

//获取Animal的main方法
			Method methodMain = getclass.getMethod("main", String[].class);
			
			//调用main方法
			//参数1:对象类型,因为方法是静态的,所以为null
			//参数2:String数组(jdk1.5之后是可变参数,)
			//注意需要将new String[]{"Hello ","World!"}进行强制转换
			methodMain.invoke(null, (Object)new String[]{"Hello ","World!"});
			

反射越过泛型检查

//例如:有一个String泛型的集合,怎么向这个集合添加一个Integer类型的值
			ArrayList<String> strlist = new ArrayList<>();
			strlist.add("Hello ");
			strlist.add("World!");
			
			//获取ArrayListde Class对象,反相调用add()方法,添加数据
			//得到strlist对象
			Class listclass = strlist.getClass();
			//获取add方法
			Method addMethod = listclass.getMethod("add", Object.class);
			//调用该add方法
			addMethod.invoke(strlist, 100);
			
			//遍历输出集合strlist
			for(Object obj5 : strlist) {
				System.out.println(obj5);
			}
			

反射实现接口

//第一步定义自己的Animal对象接口类interface1
public interface interface1{
public void setName(String name);
public String getName();
}

public class MyInterfaceView implements InvocationHandler{
//第二步实现自己的InvocationHandler接口

		//map用来存储Animal对象的数据,这样Animal中的接口无需创建实现类,
		//直接定义接口就可以代理直接使用该类,对于实际项目的开发很有用
		private Map<Object,Object> map = null;
		
		public static  Object newInstance(Class[] interfaces) {
			return Proxy.newProxyInstance(MyInterfaceView.class.getClassLoader(), interfaces, new MyInterfaceView());
		}
		
		private MyInterfaceView() {
			this.map = new HashMap<Object,Object>();
		}
		
		
		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			
			String methodName = method.getName();
			if(methodName.startsWith("get")) {
				String name = methodName.substring(methodName.indexOf("get")+3);
				return map.get(name);
			}else if(methodName.startsWith("set")) {
				String name = methodName.substring(methodName.indexOf("set")+3);
				map.put(name, args[0]);
				return null;
			}
			
			return null;
		}

}

//第三步
interface1 interface_1 = (interface1)MyInterfaceView.newInstance(new Class[] {interface1.class});
interface_1.setName(“MyInterfaceShowName”);
System.out.println(“Interface name :” + interface_1.getName());

测试以上反射机制:

结果如下:

---------通过反射获取类名---------

调用公有构造方法1
对象名获取类名:Java反射.Animal

类名.class  获取类名:Java反射.Animal
包名+类名   获取类名:Java反射.Animal

---------通过反射获取构造方法并使用---------

获取该类的所有公有构造方法
共有   3  种公有构造方法
public Java反射.Animal(int,java.lang.String)
public Java反射.Animal(int)
public Java反射.Animal()

获取该类的所有构造方法
共有   5  种构造方法
private Java反射.Animal(java.lang.String)
public Java反射.Animal(int,java.lang.String)
public Java反射.Animal(int)
public Java反射.Animal()
protected Java反射.Animal(char)

获取该类的公有无参构造方法
返回的类对象  :public Java反射.Animal()
调用公有构造方法1

获取该类的私有构造方法并调用
得到的私有构造方法  :private Java反射.Animal(java.lang.String)
调用私有构造方法1
传入num的参数:10009

---------通过反射获取成员变量并调用---------

获取所有公有的字段
public int Java反射.Animal.age
public java.lang.String Java反射.Animal.num

获取所有字段
public int Java反射.Animal.age
private java.lang.String Java反射.Animal.name
private char Java反射.Animal.gender
public java.lang.String Java反射.Animal.num
protected int Java反射.Animal.size

获取公有字段并调用
public int Java反射.Animal.age
调用公有构造方法1
验证age的设置  :3

获取私有字段并调用
private java.lang.String Java反射.Animal.name
验证私有name属性的设置  :Animal [age = 3,name = elephant,gender = m,num = 10010,size = 100]

---------通过反射获取成员方法并调用---------

获取所有的公有方法
共有12种公有方法
public static void Java反射.Animal.main(java.lang.String[])
public java.lang.String Java反射.Animal.toString()
public void Java反射.Animal.method2(int)
public void Java反射.Animal.method1()
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 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()

获取所有的方法
共有6种方法
public static void Java反射.Animal.main(java.lang.String[])
public java.lang.String Java反射.Animal.toString()
public void Java反射.Animal.method2(int)
private void Java反射.Animal.method3(int,java.lang.String)
void Java反射.Animal.method4()
public void Java反射.Animal.method1()

获取公有的有参方法method2
public void Java反射.Animal.method2(int)
调用公有构造方法1
调用公有有参方法2
传入age的参数:34

获取私有的有参方法method3
private void Java反射.Animal.method3(int,java.lang.String)
调用私有有参方法3
传入age的参数:21 和 name的参数:tiger

---------通过反射获取main方法并调用---------

main方法被执行

---------通过反射越过泛型检查---------

Hello 
World!
100

---------通过反射获取当前类的父类---------

class java.lang.Object

---------通过反射实现接口---------

Interface name  :MyInterfaceShowName

源代码(含测试代码)

Animal类

package Java反射;

public class Animal {
	public int age = 0;
	private String name = "cat";
	private char gender = 'm';
	public String num = "10010";
	protected int size = 100;
	
	public String toString() {
		return "Animal [age = "+age+",name = "+name+",gender = "+gender+",num = "+num+",size = "+size+"]";
	}
	
	//公有构造方法1
	public Animal() {
		System.out.println("调用公有构造方法1");
	}
	
	//公有构造方法2
	public Animal(int age) {
		System.out.println("调用公有构造方法2");
		System.out.println("传入age的参数:"+age);
	}
	
	//公有构造方法3
	public Animal(int age,String name) {
		System.out.println("调用公有构造方法3");
		System.out.println("传入age的参数:"+age+"和name的参数:"+name);
	
	}
	
	//私有构造方法1
	private Animal(String num) {
		System.out.println("调用私有构造方法1");
		System.out.println("传入num的参数:"+num);
	}
	
	//受保护的构造方法1
	protected Animal(char gender) {
		System.out.println("调用受保护的构造方法1");
		System.out.println("传入gender的参数:"+gender);
	}
	
	//定义公有无参方法1
	public void method1() {
		System.out.println("调用公有无参方法1");
	}
	
	//定义公有有参方法2
	public void method2(int age) {
		System.out.println("调用公有有参方法2");
		System.out.println("传入age的参数:"+age);
		
	}
	
	//定义私有有参方法3
	private void method3(int age,String name) {
		System.out.println("调用私有有参方法3");
		System.out.println("传入age的参数:"+age+" 和 name的参数:"+name);
		
	}
	
	//定义default默认方法
	void method4(){
		System.out.println("调用了默认的无参的方法4");
	}
	
	
	public static void main(String[] args) {
		System.out.println("main方法被执行");
	}
	
	//第一步定义自己的Animal对象接口类interface1
	public interface interface1{
		public void setName(String name);
		public String getName();
	}
}

实现接口类

package Java反射;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class MyInterfaceView implements InvocationHandler{
	//第二步实现自己的InvocationHandler接口
	
			//map用来存储Animal对象的数据,这样Animal中的接口无需创建实现类,
			//直接定义接口就可以代理直接使用该类,对于实际项目的开发很有用
			private Map<Object,Object> map = null;
			
			public static  Object newInstance(Class[] interfaces) {
				return Proxy.newProxyInstance(MyInterfaceView.class.getClassLoader(), interfaces, new MyInterfaceView());
			}
			
			private MyInterfaceView() {
				this.map = new HashMap<Object,Object>();
			}
			
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				
				String methodName = method.getName();
				if(methodName.startsWith("get")) {
					String name = methodName.substring(methodName.indexOf("get")+3);
					return map.get(name);
				}else if(methodName.startsWith("set")) {
					String name = methodName.substring(methodName.indexOf("set")+3);
					map.put(name, args[0]);
					return null;
				}
				
				return null;
			}
			
}

测试反射

package Java反射;

import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import Java反射.Animal.interface1;

/**
 * Java的反射机制
 * @author HP
 *
 */
public class Reflect {
	public void reflect() {
		System.out.println("---------通过反射获取类名---------");
		System.out.println();
		//第一种方法获取class对象,new产生一个Animal对象和一个Class对象
		Animal animal = new Animal();
		//对象名获取类的Class对象
		Class anclass = animal.getClass();
		//输出类名
		System.out.println("对象名获取类名:"+anclass.getName());
		
		System.out.println();
		//第二种方式获取class对象,类名.class
		Class anclass2 = Animal.class;
		System.out.println("类名.class  获取类名:"+anclass2.getName());
		
		
		//第三种方法获取Class对象,常用这种方法
		//******************************
		//注意在运行期间一个类只有一个class对象产生
		//******************************
		try {
			// "包名+类名"
			Class getclass = Class.forName("Java反射.Animal");
			System.out.println("包名+类名   获取类名:"+getclass.getName());
			
			System.out.println();
			System.out.println("---------通过反射获取构造方法并使用---------");
			System.out.println();
			
			System.out.println("获取该类的所有公有构造方法");
			//getclass.getConstructor(parameterTypes),其中parameterTypes可以设定多个或者没有参数
			Constructor[] conArray = getclass.getConstructors();
			
			//利用forech遍历输出
			System.out.println("共有   "+conArray.length+"  种公有构造方法");
			for(Constructor c : conArray) {
				System.out.println(c);
			}
			
			System.out.println();
			System.out.println("获取该类的所有构造方法");
			conArray = getclass.getDeclaredConstructors();
			System.out.println("共有   "+conArray.length+"  种构造方法");
			for(Constructor c : conArray) {
				System.out.println(c);
			}
			
			
			System.out.println();
			System.out.println("获取该类的公有无参构造方法");
			//()中填写的是参数的类型,返回描述无参构造函数的类对象
			Constructor con = getclass.getConstructor();
			System.out.println("返回的类对象  :"+con);
			
			//调用构造方法
			//这里使用newInstance方法来创建该构造方法的声明类的新实例对象
			Object obj = con.newInstance();
//			System.out.println("返回的对象"+obj);
//			Animal an = (Animal)obj;
//			System.out.println("返回的对象"+an);
			
			System.out.println();
			System.out.println("获取该类的私有构造方法并调用");
			con = getclass.getDeclaredConstructor(String.class);
			System.out.println("得到的私有构造方法  :"+con);
			
			//调用构造方法
			con.setAccessible(true);//暴力访问(忽略访问修饰符)
			obj = con.newInstance("10009");
			
			System.out.println();
			System.out.println("---------通过反射获取成员变量并调用---------");
			System.out.println();
			
			//获取字段
			System.out.println("获取所有公有的字段");
			Field[] fieldArray = getclass.getFields();
			//遍历输出
			for(Field f:fieldArray) {
				System.out.println(f);
			}
			
			System.out.println();
			System.out.println("获取所有字段");
			fieldArray = getclass.getDeclaredFields();
			//遍历输出
			for(Field f:fieldArray) {
				System.out.println(f);
			}
			
			System.out.println();
			System.out.println("获取公有字段并调用");
			Field f = getclass.getField("age");
			System.out.println(f);
			
			//获取一个对象  Animal对象
			Object obj1 = getclass.getConstructor().newInstance();
			//为字段赋值
			f.set(obj1, 3);
			Animal animal1 = (Animal)obj1;
			System.out.println("验证age的设置  :"+animal1.age);
			
			System.out.println();
			System.out.println("获取私有字段并调用");
			f = getclass.getDeclaredField("name");
			System.out.println(f);
			f.setAccessible(true);//暴力反射,解除私有限定
			//为私有字段赋值
			f.set(obj1, "elephant");
			System.out.println("验证私有name属性的设置  :"+animal1);
			
			System.out.println();
			System.out.println("---------通过反射获取成员方法并调用---------");
			System.out.println();
			
			//这里的方法还包含了Object父类继承而来的方法
			System.out.println("获取所有的公有方法");
			Method[] methodArray = getclass.getMethods();
			System.out.println("共有"+methodArray.length+"种公有方法");
			//遍历输出
			for(Method m : methodArray) {
				System.out.println(m);
			}
			
			System.out.println();
			System.out.println("获取所有的方法");
			methodArray = getclass.getDeclaredMethods();
			System.out.println("共有"+methodArray.length+"种方法");
			//遍历输出
			for(Method m : methodArray) {
				System.out.println(m);
			}
			
			System.out.println();
			System.out.println("获取公有的有参方法method2");
			//这里需要将方法中的Integer类型改为int类型才可以识别该方法,或者多多尝试运行几次
			Method m1 = getclass.getMethod("method2", int.class) ;
			System.out.println(m1);
			//实例化一个Animal对象
			Object obj2 = getclass.getConstructor().newInstance();
			m1.invoke(obj2, 34);
			
			System.out.println();
			System.out.println("获取私有的有参方法method3");
			//这里需要将方法中的Integer类型改为int类型才可以识别该方法,或者多多尝试几次
			Method m2 = getclass.getDeclaredMethod("method3", int.class, String.class);
			System.out.println(m2);
			m2.setAccessible(true);//解除私有限定
			//调用有参私有方法
			Object result = m2.invoke(obj2, 21,"tiger");
			
			System.out.println();
			System.out.println("---------通过反射获取main方法并调用---------");
			System.out.println();
			
			//获取Animal的main方法
			Method methodMain = getclass.getMethod("main", String[].class);
			
			//调用main方法
			//参数1:对象类型,因为方法是静态的,所以为null
			//参数2:String数组(jdk1.5之后是可变参数,)
			//注意需要将new String[]{"Hello ","World!"}进行强制转换
			methodMain.invoke(null, (Object)new String[]{"Hello ","World!"});
			
//			System.out.println();
//			System.out.println("---------通过反射运行配置文件内容---------");
//			System.out.println();
//			
//			Class animalclass = Class.forName("Java反射.Animal");
//			//获取method1方法
//			Method m = animalclass.getMethod(getValue("method1"));
//			//调用method2方法
//			m.invoke(animalclass.getConstructor().newInstance());
			
			System.out.println();
			System.out.println("---------通过反射越过泛型检查---------");
			System.out.println();
			
			//例如:有一个String泛型的集合,怎么向这个集合添加一个Integer类型的值
			ArrayList<String> strlist = new ArrayList<>();
			strlist.add("Hello ");
			strlist.add("World!");
			
			//获取ArrayListde Class对象,反相调用add()方法,添加数据
			//得到strlist对象
			Class listclass = strlist.getClass();
			//获取add方法
			Method addMethod = listclass.getMethod("add", Object.class);
			//调用该add方法
			addMethod.invoke(strlist, 100);
			
			//遍历输出集合strlist
			for(Object obj5 : strlist) {
				System.out.println(obj5);
			}
			
			System.out.println();
			System.out.println("---------通过反射获取当前类的父类---------");
			System.out.println();
			
			Class superclass = getclass.getSuperclass();
			System.out.println(superclass);
			
			System.out.println();
			System.out.println("---------通过反射实现接口---------");
			System.out.println();
			
			//第三步
			interface1 interface_1 = (interface1)MyInterfaceView.newInstance(new Class[] {interface1.class});
			interface_1.setName("MyInterfaceShowName");
			System.out.println("Interface name  :" + interface_1.getName());
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	
		
		
	
	
	
//	public static String getValue(String key) throws IOException{
//		//获取配置文件的对象
//		Properties pro = new Properties();
//		//获取输入流
//		FileReader in = new FileReader("C:\\Users\\HP\\Desktop\\资料\\密钥文章.txt");
//		//将流加载到配置文件对象中
//		in.close();
//		//返回根据key对象获取的value值
//		return pro.getProperty(key);
//		
//	}
	
	public static void main(String[] args) {
		Reflect rl = new Reflect();
		rl.reflect();
		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值