反射和内省

------- android培训 、java培训、期待与您交流! ----------

反射
反射就是把Java类中的各种成分映射成相应的java类。

例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
  1、反射主要用于工具的开发。所有的重要Java技术底层都会用到反射。反射是一个底层技术。
     是在运行时动态分析或使用一个类的工具(是一个能够分析类能力的程序)
  2、反射使我们能够在运行时决定对象的生成和对象的调用。
        在反射中凡是有类型的东西,全部用类对象来表示。
   java.lang.reflect .Field       对象,描述属性信息。
  java.lang.reflect .Constructor 描述构造方法信息。
  java.lang.reflect .Method      描述方法信息。

获得类对象的3种方式:

 1,Class clazz= String.class; //通过类名获得类对象 .
 2, Class clazz = s.getClass(); //类对象.getClass()通过对象获得类对象
 3,Class clazz= Class.forName(“Java.lang.String”)//通过Class.forName(“类的全名”)来获得类对象; 这会强行加载类到内存里,前两种不加载 注:第三种方式是最常用最灵活的方式。第三种方式又叫强制类加载。
Constructor代表某个类中的构造方法
//获取字节码文件

Class clazz=Class.forName("com.itheima.Person");

//该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
Person obj = (Person)clazz.newInstance();
//得到某个类所有的构造方法
Constructor [] constructors= Class.forName("com.itheima.Person").getConstructors();
//得到某一个带参数的构造方法
Constructor constructor = clazz.getConstructor(String.class);
//通过构造创建对象.
Person p = (Person) constructor.newInstance("zhangan");
//getConstructor只能获得public类型的构造函数,如果想好的private的构造函数需要用getDeclaredConstructor()私有的只有内部可以访问,但是反射可以setAccessible(true)暴力反射
Constructor constructor = clazz.getDeclaredConstructor(String.class);
  //打开访问权限
  constructor.setAccessible(true);
  //再调用newInstance来初始化即可。
Person p = (Person)constructor.newInstance("lisi")
Method类:代表某个类中的一个方法
//clazz通过getMethod获取获取它的一个方法,第一个参数是方法名,第二个参数是参数类型的字节码 
	Method method = clazz.getMethod("show", int.class);
// 通过invoke方法调用某个对像的具体方法,第一个参数是指:调用对像,第二个参娄是指这个方法的参数
	method.invoke(p,22);
//调用私有方法
  	Method m = cls.getDeclaredMethod("show",int.class);
  //打开权限
 	 m.setAccessible(true);
 	 m.invoke(p,22);
//调用静态方法时,不需要不需要传入实际变量,静态方法可以直接调用。
	Object o=m.invoke(null,"itheima.com";

Field类:类的成员变量
//通过字节码的getField方法来获取一个成员变量对应的对像
 	 Field f = cls.getDeclaredField("age");
  	f.setAccessible(true);
  //第一个参数是指给哪一个对像设置,第二个参数是指设置的值
 	 f.set(p, 23);
  //获取私有变量的值
	System.out.println(f.get(p));
实例:将及字符a 换成b.
 
class Xxx
{
	String name="abc";
	String email="abd";
	int x = 5;
}
func(Object obj)
{
Field [] fields = obj.getClass().getDeclaredFields();
for(Field field : fields)
{
	if(field.getType()==java.lang.String.class)
	{
		field.setAccesible(true);
		String original = (String)field.get(obj);
		field.set(obj,original.replaceAll("b","a");
	}
}
}

jdk1.4 jdk1.5 invoke 方法的区别:
 Jdk1.5 public Object invoke(Object obj,Object ... args )
 Jdk1.4 public Object invoke(Object obj,Object [] args ) ,即按 jdk1.4 的语法,需要将一个数组作为参数传递给 invoke 方法时,数组中的每个元素分别对应被调用方法中的一个参数.
数组的反射:
1,具有相同维数和元素类型的数组属于同一个类型,即具有相同的 Class 实例对象。
2, 代表数组的 Class 实例对象的 getSuperClass () 方法返回的父类为 Object 类对应的 Class
3,基本类型的一维数组可以被当作 Object 类型使用,不能当作 Object[] 类型使用;非基本类型的一维数组,既可以当做 Object 类型使用,又可以当做 Object[] 类型使用。
 内省
       JavaBean 是一种特殊的 Java 类,主要用于传递数据信息,这种 java 类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个 JavaBean 中,这种 JavaBean 的实例对象通常称之为值对象( Value Object ,简称 VO )。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问, JavaBean 的属性是根据其中的 setter getter 方法来确定的.
Sun 公司开发一套专门用于操作 JavaBean 属性的 API.
Java 属性是指必须拥有 setter/getter 方法的字段。
Java.beans. PropertyDescriptor 是操作 JavaBean 属性的类。
反射与内省的区别:
反射可以操作各种不同的 java 类,那么内省只是通过反射操作 JavaBean setter/getter 方法。
public class PropertyDemo {
	public static void main(String[] args) throws Exception {
		 Class<?> cls = Class.forName("com.itheima.Person");
		 Object o = cls.newInstance();
		 
		 //可通过内省进行操作了
		 PropertyDescriptor pd = new PropertyDescriptor("name",cls);
		 Method m = pd.getWriteMethod();
		 m.invoke(o,"Rose");		 
		 //操作一个不存在的属性,则会抛出一个异常
		 PropertyDescriptor pd = new PropertyDescriptor("age",cls);
		 Method m2 = pd.getWriteMethod();//setAge
		 m5.invoke(o,"999");
		 }
BeanutilsApache开发的一套快速操作JavaBean getter/setter方法的API,
l 准备包:
commons- beanutils.jar,commons - logging.jar
l 语法:
•设置:
•BeanUtils.setProperty(Object bean,StringpropertyName,StringpropertyValue);
•获取:
•BeanUtils.getProperty(Object bean,StringPropetyName);
public class BeanUtilsDemo {
	public static void main(String[] args) throws Exception {
		 Class<?> cls = Class.forName("com.itheima.Person");
		 Object o = cls.newInstance();
		
		//主要类:,使用它的静态方法
		BeanUtils.setProperty(o,"name","张三");
		String name = BeanUtils.getProperty(o,"name");
综合案例:
public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		ReflectPoint pt1 = new ReflectPoint(3,5);
		Object retVal = getProperty(pt1);
		System.out.println(retVal);
		
		PropertyDescriptor pd2 = null;
		String propertyName = "y";
		Object value = 7;
		setProperty(pt1, propertyName, value);	
		
		//先通过调用普通java类的方法的方式获得结果,然后在这之前插入BeanUtil的get和set操作,见下面的代码。
		//System.out.println(pt1.getY());
		
		System.out.println(BeanUtils.getProperty(pt1, "y"));
		BeanUtils.setProperty(pt1, "y", "99");

		System.out.println(pt1.getY());
		PropertyUtils.setProperty(pt1, "y", 999);
		System.out.println(PropertyUtils.getProperty(pt1, "y").getClass().getName());	
	}

	private static Object getProperty(ReflectPoint pt1) {
		Object retVal = null;
		PropertyDescriptor pd = null;
		try {
			pd = new PropertyDescriptor("y",pt1.getClass());
			retVal = pd.getReadMethod().invoke(pt1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return retVal;
	}

	private static void setProperty(Object pt1, String propertyName,
			Object value) {
		/*PropertyDescriptor pd2;
		try {
			pd2 = new PropertyDescriptor(propertyName,pt1.getClass());
			pd2.getWriteMethod().invoke(pt1,value);
		} catch (Exception e) {
			e.printStackTrace();
		}*/
		
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
			PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
			for(PropertyDescriptor pd :pds){
				if(pd.getName().equals(propertyName)){
					pd.getWriteMethod().invoke(pt1,value);
					break;
				}
			}
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IntrospectionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}




 


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值