JAVA 反射机制

     反射机制是java中底层的动态工作机制,是java的核心特性。
     静态:经过java编译器的处理以后就固定下来执行顺序,也就是在编译的过程中就已经确定了的,称为静态
     动态:java程序在运行期间,才能确定的处理顺序,称为动态
发射API的作用:
    1 动态加载类
    2 动态获取类的信息(类型,属性,方法,构造器等)
    3 动态创建对象
    4 动态访问属性
    5 动态访问方法
  动态的加载类并且获取类的信息:
    在运行期间动态的加载给定的类到内存方法区。
    在动态加载类时要使用类全限定名(类全限定名:包名.类名),我们使用Class类中的一个静态方法动态加载给定的类,这个方法是forName(类全限定名),这个方法的返回值是Class类型的对象,可以通过这个对象访问方法区中类的信息。
    Class 在Java中代表类型,任何类型都是Class类型的对象,Class类型的对象在java运行期间是唯一的,并且按需加载。
    将一个类加载到内存中,我们把它看做一个对象,那么这个对象就是属于Class类型的对象。
    这里我们先写一个普通类Student.Java 用于测试java反射机制。
public class Student {
	public String name;
	public String gender;
	public int age;

	public Student() {
		name = "Tom";
		gender = "f";
		age = 45;
	}

	public Student(String name, String gender, int age) {
		this.name = name;
		this.gender = gender;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return name+","+gender+","+age;
	}
}
 


 

@Test
	public void testClassLoader(){
		try {
			Class cls=Class.forName("com.xu.test.Student");
			//获取类名
			String classType=cls.getName();
			System.out.println(classType);//result:com.xu.test.Student
			//动态获取类中的属性的声明,Field是反射包中的类型,代表属性的信息
			Field[] fields=cls.getDeclaredFields();
			for(Field field:fields){
				/*result:
				 * class java.lang.reflect.Field name
				 * class java.lang.reflect.Field gender
				 * class java.lang.reflect.Field age
				 */
				System.out.println(field.getClass()+" "+field.getName());
			}
			//动态获取声明方法中的信息
			//Method类型的对象描述了方法的信息
			Method []methods=cls.getDeclaredMethods();
			for(Method method:methods){
				//获取方法参数列表
				//Class就是代表类型的,类型列表就是Class类型的数组
				Class [] param=method.getParameterTypes();
				/*
				 * result:
				 * class java.lang.String getName([])
				 * void setName([class java.lang.String])
				 * class java.lang.String getGender([])
				 * void setGender([class java.lang.String])
				 * int getAge([])
				 * void setAge([int])
				 */
				System.out.println(method.getReturnType()+" "+method.getName()+"("+Arrays.toString(param)+")");
			}
			//动态获取构造方法的信息
			Constructor []constructors=cls.getDeclaredConstructors();
			for(Constructor constructor:constructors){
				Class [] param=constructor.getParameterTypes();
				/*
				 * result:
				 * com.xu.test.Student []
				 * com.xu.test.Student [class java.lang.String, class java.lang.String, int]
				 */
				System.out.println(constructor.getName()+" "+Arrays.toString(param));
			}
		} catch (ClassNotFoundException e) {
			//如果没有找该类的话就抛出此异常
			e.printStackTrace();
		}
	}

 

/**
	 * 有三种获取类型Class的方式:
	 *    1 Class.forName(类全限定名)动态根据类名获取类型
	 *    2 类型.class静态已知类型情况下获取类型,用于已知类型获取类的信息
	 *    3 对象.getClass()获取对象的类型
	 */
//	@Test
	public void testClass(){
		try {
			Class cls=Class.forName("com.xu.test.Student");
			Class cls1=Student.class;
			System.out.println(cls==cls1);//result:true 说明两个对象是一个对象
			Class classType=int.class;
			System.out.println(classType);//int
			Student s=new Student();
			cls=s.getClass();
			System.out.println(cls);//class com.xu.test.Student
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}


/**
	 * 有三种获取类型Class的方式:
	 *    1 Class.forName(类全限定名)动态根据类名获取类型
	 *    2 类型.class静态已知类型情况下获取类型,用于已知类型获取类的信息
	 *    3 对象.getClass()获取对象的类型
	 */
//	@Test
	public void testClass(){
		try {
			Class cls=Class.forName("com.xu.test.Student");
			Class cls1=Student.class;
			System.out.println(cls==cls1);//result:true 说明两个对象是一个对象
			Class classType=int.class;
			System.out.println(classType);//int
			Student s=new Student();
			cls=s.getClass();
			System.out.println(cls);//class com.xu.test.Student
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

 Class类型经常用于加载包中资源
    包中资源:将软件需要用到的只读资源 图片 文件 音乐,经常被打包到包中
    Java提供了2种包中资源的读取方式:
        1  使用Class类上定义的方法getResource(包路径)是非静态方法必须使用对象调用。

        bin
      |--se
         |-- reflect
         |     |-- demo.txt
         |     |-- TestCase.class
         |-- net
               |-- img.png
       
        包路径:绝对路径,从包的根开始/se/reflect/demo.txt
                相对路径: demo.txt 表示此文件与当前Class类型在一个包中
         (注:此处的路径是以java的包为路径,不是操作系统文件路径!) 
         getResource(路径)返回值是URL类型的对象 ,在URL类型中有openStream()方法,可以返回流对象inputStream。getResourceAsStream()是 getResource与openStream的合体。

@Test
	public void testgetResource() throws IOException{
		Class cls=this.getClass();
		URL txt=cls.getResource("demo.txt");
		InputStream in=txt.openStream();
		in.close();
		ClassLoader loader = cls.getClassLoader();
		URL img = loader.getResource("se/net/img.png");
		in= img.openStream();
		System.out.println(in);
		in.close();
	}

 2  ClassLoader是Java类的加载器,将一个类读取到方法区中,就是ClassLoader的功劳。ClassLoader中也定义了getResource(路径)方法用于加载资源,路径也是包路径,是一种绝对路径但是不能写“/” 如:se/reflect/demo.txt

    动态创建对象:
       1 使用无参数构造器创建对象,Class类提供的便捷方法newInstance方法。如果没有无参构造器抛出异常。
       2 使用有参数构造器创建对象
           先找到构造器,再调用构造器,并且传递参数调用构造器创建对象

@Test
	public void testConstructor(){
		
		try {
			Class cls=Class.forName("com.xu.test.Student");
			Object obj=cls.newInstance();
			System.out.println(obj);
			 
			//事先知道构造器的参数列表
//			Class [] types={String.class,String.class,int.class};
//			Object[] params={"Jerry","f",23};
			//获得指定参数列表的构造器
//			Constructor constructor=cls.getConstructor(types);
			Constructor constructor=cls.getConstructor(String.class,String.class,int.class);
			//执行构造方法
//			obj=constructor.newInstance(params);
			obj=constructor.newInstance("Jerry","f",23);
			System.out.println(obj);
			
		} catch (InstantiationException e) {
			//没有无参构造器异常
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			//没有访问权限异常
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			//没有找到类异常
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			//参数错误异常
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			//方法执行异常,获取真正抛出异常的原因
			Throwable x=e.getCause();
			x.printStackTrace();
//			e.printStackTrace();
		}
	}
	
	//动态访问对象的属性
//	@Test
	public void testField(){
		
		try {
			String fieldName="name";
			Class cls = Class.forName("com.xu.test.Student");
			Object obj=cls.newInstance();
			//反射API在类上找到属性信息
			Field field=cls.getField(fieldName);
			//在对象上获得属性的值
			Object name=field.get(obj);
			System.out.println(name);
			field.set(obj, "Jerry");
			name=field.get(obj);
			System.out.println(name);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	@Test
	public void testMethod(){
		try {
			Class cls=Class.forName("com.xu.test.Student");
			//从类中获取方法的信息
			Method method=cls.getMethod("getGender");
			Object obj=cls.newInstance();
			//在对象上执行方法,obj在执行方法期间传递给了this变量
			System.out.println(method.invoke(obj));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException 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();
		}
	}




 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值