java反射

反射的入口:java.lang.Class

日常开发中的对象,分为两种,基本类型和引用类型									
基本类型,(固定的 8 种) 									
	整数:byte, short, int, long								
	小数:float, double								
	字符:char								
	布尔值:boolean								
引用类型 									
	所有的引用类型都继承自 java.lang.Object								
	类,枚举,数组,接口都是引用类型								
	java.io.Serializable 接口,基本类型的包装类(比如 java.lang.Double)也是引用类型	

获取Class 3中方法

1.Object.getClass() 方法
   如果我们已经拿到了一个对象,可以很方便地使用它的 getClass 方法获得一个 Class 对象(当然这仅限于引用类型的对象):

 Class<?> c = "shixinzhang.top".getClass();		

返回的对象 c 是 String 类型。
2. .class 语法
   如果我们当前没有某个类的对象,无法使用 getClass() 方法,那还可以使用另外一种方法获取 Class:在要获得的类名后加上 .class ,比如这样:

 Class<?>  c = String.class;		

这种方式不仅能用于引用类型,基本类型也可以。
3.Class.forName() //一般调用内部类
   如果我们有一个类的完整路径,就可以使用 Class.forName(“类完整的路径”) 来得到相应的 Class,这个方法只能用于引用类型,比如:

 Class<?> clazz =Class.forName("com.baiduq$MyBTAddPhoneListener");	

例:

//第一种方式获取Class对象  
Student stu1 = new Student();       //这一new 产生一个Student对象,一个Class对象。
Class<?> stuClass = stu1.getClass();//获取Class对象

//第二种方式获取Class对象
 Class<?>  stuClass2 = Student.class;
 System.out.println(stuClass == stuClass2);//第一种方式获取的Class对象和第二种方式获取的是同一个

//第三种方式获取Class对象
  try {
	 Class<?> stuClass3 = Class.forName("com.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
	 System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
 } catch (ClassNotFoundException e) {
	 e.printStackTrace();
}

类的实例化:

    XXX.class.newInstance()
例:

  String str = String.class.newInstance()	

Constructor

1.获取所有public构造方法

  public Constructor []  getConstructors() 		

2.获取所以构造方法,不区分访问修饰符

  public Constructor []  getDeclaredConstructors()	

3.获取指定构造方法

  public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

Field 成员变量的介绍

   每个成员变量有类型和值。 java.lang.reflect.Field 为我们提供了获取当前对象的成员变量的类型,和重新设值的
1.获取变量名字

     Field.getName():返回这个变量的名称	

2.获取变量的类型

	Field.getType():返回这个变量的类型										
	Field.getGenericType():如果当前属性有签名属性类型就返回,否则就返回 Field.getType()	

3.获取成员变量的修饰符

	Field.getModifiers() 方法获取当前成员变量的修饰符										
											
	成员变量可以被以下修饰符修饰:										
	访问权限控制符:public, protected, private										
	限制只能有一个实例的:static										
	不允许修改的:final										
	不会被序列化:transient										
	线程共享数据的一致性:volatile	

4.获取和修改成员变量的值
获取变量:

	public Field   getField(String name)	 获取公共字段,包含父类		
	public Field[] getFields()			     获取所有公共字段,包含父类														
	public Field   getDeclaredField(String name) //常用										
	               可以获取publicprotected 、缺省 、private 修饰的字段,但该字段必须在当前类或接口中 存在 声明,父类继承的字段无法获取														
	public Field[]  getDeclaredFields()		 返回一个Field[]数组 公共、保护、默认(包级私有)和私有字段,但不包括继承的字段。								  										

修改变量:

	field.setAccessible(true)										
	field.setAccessible(false)										
	Field.set(Object obj, Object value) 				//将value对象设置到obj里面						
	注:										
	常见错误 1 :无法转换类型导致的 java.lang.IllegalArgumentException										
	f.set(ft, new Integer(43));										
	常见错误 2:反射非 public 的变量导致的 NoSuchFieldException										
	常见错误 3 :修改 final类型的变量导致的 IllegalAccessException		

Method反射

继承的方法(包括重载、重写和隐藏的)会被编译器强制执行,这些方法都无法反射。因此,反射一个类的方法时不考虑父类的方法,只考虑当前类的方法。 每个方法都由 修饰符、返回值、参数、注解和抛出的异常组成 java.lang.reflect.Method 方法为我们提供了获取上述部分的 API

1.获取成员方法的函数

	Method getMethod(String name, Class… parameterTypes)										
				公共成员方法,parameterType参数							
	Method[] getMethods()										
				 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 							
	Method getDeclaredMethod(String name, Class… parameterTypes)								常用		
				返回一个 Method 对象,名字指定为name,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 							
	Method[] getDeclaredMethods()										
				返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 		

2.调用成员方法

	先设置override属性为true:method.setAccessible()来改变										
	如果设置为true,则表示可以忽略访问权限的限制,直接调用										
	method.invoke(Object obj,Object... objects)					//调用第一个是对象		
	
注意:如果调用的是静态方法则 method.invoke(null) 里面可以传递一个null

3.无参数成员方法调用

	private void setButtonListener()																
	Method method = mockBtAddPhone.getClass().getDeclaredMethod("setButtonListener", null);										
	method.setAccessible(true);      //用完设置为false										
	Object result = method.invoke(mockBtAddPhone,null);										
	method.setAccessible(false);    //用完设置为false	

4.有一个参数的成员方法调用

	private void setButtonListener(int i)																	
	Method method = mockBtAddPhone.getClass().getDeclaredMethod("setButtonListener", int.class);										
	method.setAccessible(true);										
	Object result = method.invoke(mockBtAddPhone,1);//第二个参数是,正式代码接口的参数										
	method.setAccessible(false); // 用完设置为false		

5.有多个参数的成员方法调用

public void BTAdapterOnConnectionChangedUpdate(byte index, long devAdress, String devName, int func, byte result) {																				
	Class[] argTypes1=new Class[5];										
	argTypes1[0]=byte.class;										
	argTypes1[1]=long.class;										
	argTypes1[2]=String.class;										
	argTypes1[3]=int.class;										
	argTypes1[4]=byte.class;																			
	Method method1 = MyBTAddPhoneListenerClazz.getDeclaredMethod("BTAdapterOnConnectionChangedUpdate", argTypes1);//传递的argTypes1是正式代码接口的参数表										
	method1.setAccessible(true);										
	Object result1 = method1.invoke(obj,new Object[]{(byte)0,1,null,1,(byte)0});										
	method.setAccessible(false); // 用完设置为false			

6.invoke返回值判断

如果是string类型返回函数										
	Class<?>  clazz =  InvokeObj.class;										
	Method method4 = clazz.getMethod("StringShow", String.class);										
	String result = (String) method4.invoke(clazz.newInstance(), "Thinking in java");										
	Assert.assertEquals("Thinking in java",result);										
											
如果是void函数,返回为空										
	Assert.assertEquals(null,result);																		
	public Object invoke(Object obj,Object... args)																			
	对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。										
	如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。																			
	如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。 																			
	如果底层方法是静态的,并且尚未初始化声明此方法的类,则会将其初始化。																			
	如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素不 被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null										
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值