Java反射技术

       乌拉拉,今天我们来讲一个高大上的东西,反射。想必很多人都听说过了,今天我们就慢慢的来讲解其用法。

      首先是反射的定义:(网上抄的)

      在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法
             Java反射机制主要提供了以下功能:
              * 1.在运行时判断任意一个对象所属的类。
              * 2.在运行时构造任意一个类的对象。
              * 3.在运行时判断任意一个类所具有的成员变量和方法。
              * 4.在运行时调用任意一个对象的方法。 

    Java Reflection API简介

    在JDK中,主要由以下类来实现Java反射机制,这些类(除了第一个)都位于java.lang.reflect包中
  Class类:代表一个类,位于java.lang包下。
  Field类:代表类的成员变量(成员变量也称为类的属性)。
  Method类:代表类的方法。
  Constructor类:代表类的构造方法。
  Array类:提供了动态创建数组,以及访问数组的元素的静态方法。(这个方法的放射今天不提,这个复杂)

  Class对象

    要想使用反射,首先需要获得待操作的类所对应的Class对象,我们都知道所有代码都最后被变成.class的文件,我们也是从这个class文件开始着手去方向去获取我们想要的东西。
    首先我们要去获取我们的class对象,这里有3中法方法。


        一:使用Class的静态方法来获取
            相信用过JDBC的人都知道,要想用JDBC首先要注册我们的驱动,也就是
                Class.forName("com.mysql.jdbc.Driver");

        二:.class直接获取我们的class
           eg:  String.class  这样就获得了String的Class

        三:getClass()方法获得,这个是建立在你已经得到这个对象的实例来获取
            eg:   A a = new A();
                     Class<?> c = a.getClass();
               这样我们也可以获得A的Class对象.



     下面就以几个例子用反射分别获取我们的构造函数,成员变量,方法。
   


    获取构造函数:

             一:获取公有的构造函数(public)
               

         //定义我们要反射的类
class AA{
	private int a;
	private int b;
	public AA() {	System.out.println("放射获取成功");}
}
public class Refelect {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		//用第二种方法获取来获取
		Class<?> c = AA.class;//这里可以写成Class c = AA.class;  因为他底层代码返回的是Class<?> 其实一样,最后有泛型擦除的效果,所以没事,但是还是标准的写比较好
		
		AA aa = (AA) c.newInstance();
		
	}
}
         这里是可以直接调用newInsatace(),来构造默认的构造函数下面演示标准做法。

         这样我们就获得了我们的构造函数,但是这个构造函数是个公有的。完全没体现出反射的作用.下面我把构造函数定义成私有的,那么用常规的方法是无法获取到的。这就体现出反射的厉害了,但是用上面的代码还是不能获取到的。接着看;
         
    

         二:获取私有的构造函数(private)
class AA{
	private int a;
	private int b;
	private AA() {	System.out.println("放射获取成功");}
}
         这样就棘手了,但是无妨.

        
  
public class Refelect {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		
		Class<?> c = AA.class;
	//	AA aa = (AA) c.newInstance();
		
		/**
		 * 反射来获取构造函数(指定的构造函数)getDeclaredConstructor(param);
		 * 返回为所有构造函数仅本Class
		 * 参数含义就是对应构造函数的形参
		 * c.getConstructor(parameterTypes)
		 * 得到是包括父类的public的构造函数
		 * 
		 */
		Constructor<?>  constructor = c.getDeclaredConstructor(new Class[] {});
		//修改得到的构造函数的方法权限
		constructor.setAccessible(true);
		//通过构造函数来实例化AA
		AA aa = (AA) constructor.newInstance();
	}
}
      这样我们也能获取到AA这个对象。
    

    获取成员变量:

         一样的也分公有和私有,这里直接讲私有的获取方法.
    
class AA{
	private int a;
	private int b;
	private AA() {	
		System.out.println("放射获取成功");
	}
}
public class Refelect {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
		
		Class<?> c = AA.class;
	//	AA aa = (AA) c.newInstance();
		
		/**
		 * 反射来获取构造函数(指定的构造函数)getDeclaredConstructor(param);
		 * 返回为所有构造函数仅本Class
		 * 参数含义就是对应构造函数的形参
		 * c.getConstructor(parameterTypes)
		 * 得到是包括父类的public的构造函数
		 * 
		 */
		Constructor<?>  constructor = c.getDeclaredConstructor(new Class[] {});
		//修改得到的构造函数的方法权限
		constructor.setAccessible(true);
		//通过构造函数来实例化AA
		AA aa = (AA) constructor.newInstance();
		//得到我们指定的变量,里面有好多方法,也可以返回集合
		Field field = c.getDeclaredField("a");
		//修改属性
		field.setAccessible(true);
		//设置值
		field.set(aa,3);
		//打印
		System.out.println("a = "+field.get(aa));
	}
}
  结果:
    反射获取成功
    a = 3

   获取方法并调用:

       这次我们以公有的方法来获取并且调用。
       
class AA{
	private int a;
	private int b;
	private AA() {	
		System.out.println("反射获取成功");
	}
	public AA(int a,int b) {
		this.a=a;
		this.b=b;
	}
	public void add(int a,int b) {
		System.out.println("a+b="+(a+b));
	}
}


public class Refelect {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
		
		Class<?> c = AA.class;
	//	AA aa = (AA) c.newInstance();
		
		/**
		 * 反射来获取构造函数(指定的构造函数)getDeclaredConstructor(param);
		 * 返回为所有构造函数仅本Class
		 * 参数含义就是对应构造函数的形参
		 * c.getConstructor(parameterTypes)
		 * 得到是包括父类的public的构造函数
		 * 
		 */
		Constructor<?>  constructor = c.getDeclaredConstructor(new Class[] {});
		//修改得到的构造函数的方法权限
		constructor.setAccessible(true);
		//通过构造函数来实例化AA
		AA aa = (AA) constructor.newInstance();
		//得到我们指定的变量,里面有好多方法,也可以返回集合
		Field field = c.getDeclaredField("a");
		//修改属性
		field.setAccessible(true);
		//设置值
		field.set(aa,3);
		//打印
		System.out.println("a = "+field.get(aa));
		
		/**
		 * 同上面一样c.getDeclaredMethod(name, parameterTypes)
		 * 返回的是所有本类的方法
		 * 参数一  调用的方法名
		 * 参数二  形参列表,要一一对应
		 */
		//得到我们的方法
		
		
		Method method = c.getDeclaredMethod("add", new Class [] {int.class,int.class});
		/**
		 * 调用我们的方法 method.invoke(obj, args)
		 * 参数- 为反射获取得到的实例,参数二 你要传递的参数
		 */
		method.invoke(aa, new Object[] {1,2});
	}
}


     这样就可以获取并且调用我们的方法了,class类里面还有一大堆方法这里列出来,

       getType(): 获取属性声明时类型对象(返回class对象)

       getGenericType() : 返回属性声的Type类型

       getName() : 获取属性声明时名字

       getAnnotations() : 获得这个属性上所有的注释

       getModifiers() : 获取属性的修饰

       isEnumConstant() : 判断这个属性是否是枚举类

       isSynthetic() : 判断这个属性是否是 复合类

      等等....

    这里下去可以自己试一下.


  

  反射能干嘛:

      可能听上面的东西,到头来还没弄明白反射用来干嘛的。
     其实反射用处很多,开发Android的人一定会被一些SDK给烦恼住,因为有的地方标注了hide标签


  eg: 
UsageStats 包底下封装了我们app状态的一些方法,但是这些方法google不对外公开,他带了hide标签,这样我们学了反射我们也可以通过反射来获取。
Jdk也有一些被私有的构造函数.我们都无法正常获取他。
 
  
最后支持原创,转载请注明转载出处
   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值