java 反射复习

引言

       反射使得我们可以编写动态操纵java代码的程序,它允许我们在运行时发现和使用类型信息。

使用反射,我们可以:

1.      在运行中分析类的能力。

2.      在运行中查看对象,例如:可以编写一个toString()方法供不同类型的对象使用。

3.      实现数组的操作代码。

4.      利用Method对象,它很像C++中的指针。

 

 

Class对象

每个类都有一个class对象,每当编写并且编译了一个类,就会产生一个class对象(更确切地说,它被保存到.class文件中)

Class API

public T newInstance()

             throws InstantiationException,

                    IllegalAccessException

创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。

 

public static Class<?> forName(String className)

                       throws ClassNotFoundException

返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:

 Class.forName(className, true, currentLoader)

 

其中 currentLoader表示当前类的定义类加载器。

 

 

 

 

Java 提供了两种方法来生成Class对象的引用:

1.      Class.forName(…)

2.      Chinese.class:这样做不仅更简单,而且更安全,因为在编译期间就会得到检查。

例子:

package com.lemon.reflection;

public class ClassTest {

	public static void main(String[] args) {
		try {
			//Chinese c=(Chinese) Class.forName("com.lemon.reflection.Chinese").newInstance();
			Chinese c=Chinese.class.newInstance();
			System.out.println("class name:"+c.getClass().getName());
			System.out.println("simple name:"+c.getClass().getSimpleName());
			System.out.println("full name:"+c.getClass().getCanonicalName());
			Class<?> superClass=c.getClass().getSuperclass();
			System.out.println("直接父类:"+superClass.getCanonicalName());
			System.out.println("祖宗类:"+superClass.getClass().getSuperclass());
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
}

输出:

classname:com.lemon.reflection.Chinese

simple name:Chinese

fullname:com.lemon.reflection.Chinese

直接父类:com.lemon.reflection.Person

祖宗类:class java.lang.Object

利用反射分析类

 

在java 反射API中,有三个重要的类:

1.      java.lang.reflect.Field:提供了有关类,接口的单个字段的信息,以及对它的动态访问权限。

 

2.      java.lang.reflect.Method:提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。


3.      java.lang.reflect.Constructor:

 

Field API

public int getModifiers()

以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符。应该使用 Modifier 类对这些修饰符进行解码。

 
public Class<?> getType()

返回一个Class 对象,它标识了此 Field 对象所表示字段的声明类型。

 

public Field[] getFields()

                 throws SecurityException

返回一个包含某些 Field 对象的数组,这些对象反映此Class 对象所表示的类或接口的所有可访问公共字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果类或接口没有可访问的公共字段,或者表示一个数组类、一个基本类型或 void,则此方法返回长度为 0 的数组。

特别地,如果该 Class 对象表示一个类,则此方法返回该类及其所有超类的公共字段。如果该 Class 对象表示一个接口,则此方法返回该接口及其所有超接口的公共字段。

 

public Field[] getDeclaredFields()

                         throws SecurityException

返回 Field 对象的一个数组,这些对象反映此Class 对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何字段,或者此Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。

 

例子:

package com.lemon.reflection;

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

public class FieldTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Class<Integer> integer=Integer.class;
		
		Field[] fs=integer.getDeclaredFields();
		
		for(Field field:fs){
			System.out.println(Modifier.toString(field.getModifiers())
					+" "+field.getType()+" "+field.getName());
		}
	}

}


 

输出:

public static final intMIN_VALUE

public static final intMAX_VALUE

public static final classjava.lang.Class TYPE

static final class [C digits

static final class [C DigitTens

static final class [C DigitOnes

static final class [I sizeTable

private static classjava.lang.String integerCacheHighPropValue

private final int value

public static final int SIZE

private static final longserialVersionUID


Method API

 

 

public Class<?>[] getParameterTypes()

按照声明顺序返回 Class 对象的数组,这些对象描述了此Method 对象所表示的方法的形参类型。如果底层方法不带参数,则返回长度为0 的数组。

 

 

public Object invoke(Object obj,

                    Object... args)

             throws IllegalAccessException,

                    IllegalArgumentException,

                    InvocationTargetException

对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。

如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。

如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。

 

除此之外,其他与Field类似。

例如:

package com.lemon.reflection;

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

public class MethodTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Class<Integer> integer=Integer.class;
		Method[] ms=integer.getDeclaredMethods();
		for(Method method:ms){
			StringBuffer methodShow=new StringBuffer(Modifier.toString(method.getModifiers())
					+" "+method.getReturnType()+" "+method.getName()+"(");
			Class<?>[] parameters=method.getParameterTypes();
			String parameterType="";
			for(Class<?> p:parameters){
				parameterType=p.getName();
			}
			System.out.println(methodShow.append(parameterType+")"));
		}
	}

}

输出:

public static intnumberOfLeadingZeros(int)

public static intnumberOfTrailingZeros(int)

public static int bitCount(int)

public booleanequals(java.lang.Object)

public static classjava.lang.String toString(int)

public static classjava.lang.String toString(int)

public class java.lang.StringtoString()

public int hashCode()

public static intreverseBytes(int)

public intcompareTo(java.lang.Integer)

public volatile intcompareTo(java.lang.Object)

public static classjava.lang.String toHexString(int)

public static classjava.lang.Integer decode(java.lang.String)

static void getChars([C)

public static classjava.lang.Integer valueOf(java.lang.String)

public static classjava.lang.Integer valueOf(int)

public static classjava.lang.Integer valueOf(int)

static class java.lang.Stringaccess$000()

static voidgetAndRemoveCacheProperties()

public static int reverse(int)

public byte byteValue()

public double doubleValue()

public float floatValue()

public int intValue()

public long longValue()

public short shortValue()

publicstatic int parseInt(int)

public static intparseInt(java.lang.String)

public static classjava.lang.Integer getInteger(java.lang.Integer)

public static classjava.lang.Integer getInteger(java.lang.String)

public static classjava.lang.Integer getInteger(int)

public static inthighestOneBit(int)

public static intlowestOneBit(int)

public static introtateLeft(int)

public static introtateRight(int)

public static int signum(int)

static int stringSize(int)

public static classjava.lang.String toBinaryString(int)

public static classjava.lang.String toOctalString(int)

private static classjava.lang.String toUnsignedString(int)

 

反射在很多地方都有应用,比方说,Struts2 框架中就是利用反射:将页面提交过来的数据set到实体对象中。

例:

package com.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class BeanReflectionUtil {

	
	/**
	 * this method will set the value of field which come from client
	 * @param bean javaBean
	 * @param mapFromRequest from HttpRequset
	 * @throws Exception
	 */
	public static void setFieldValue(Object bean,Map<?,?> mapFromRequest) throws Exception{
		if(bean==null||mapFromRequest==null){
			return ;
		}else{
			Class<?> c=bean.getClass();
			Field[] fs=c.getDeclaredFields();
			if(fs!=null){
				for(Field f:fs){
					String fieldSetMethodName=buildSetMethodNameByFieldName(f.getName());
					if(fieldSetMethodName!=null){
						Method method=c.getMethod(fieldSetMethodName, f.getType());
						Set<?> set=mapFromRequest.keySet();
						Iterator<?> it=set.iterator();
						while(it.hasNext()){
							String key=(String) it.next();
							if(key.equals(f.getName())){
								Object[] objects=(Object[]) mapFromRequest.get(key);
								method.invoke(bean, objects[0]);								
							}
						}
					}
				}
			}
		}
	}
	
    public static String buildSetMethodNameByFieldName(String fieldName) {  
        if (null == fieldName || "".equals(fieldName)) {  
            return null;  
        }  
        return "set" + fieldName.substring(0, 1).toUpperCase()  
                + fieldName.substring(1);  
    }  
}


setFieldValue方法接受两个参数,最后一个可能是HttpServlet.getParemeterMap()对象。

Constructor API

与上述相似,不再赘述。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值