JSE深入探究——反射初步

       Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
       反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。 
      一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。

对比提问:
众多的人用一个什么类表示?众多的Java类用一个什么类表示?
人     Person
Java类Class

对比提问:
Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表Java类,它的各个实例对象又分别对应什么呢?
对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等。
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,
所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型是什么呢?

如何得到各个字节码对应的实例对象( Class类型)
三种方式:
1.
类名.class,例如,System.class
2.
对象.getClass(),例如,new Date().getClass()
3.

Class.forName("类名"),例如,Class.forName("java.util.Date");

下面是实例用到的一个类:

public class Person 
{
	private int id;
	private String name;
	public Person(int i,String n)
	{
		id=i;
		name=n;
	}
	@Override
	public String toString() 
	{
		return name+"="+id;
	}
}

下面是演示实例与注释:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ReflectDemo
{

	public static void main(String[] args) 
	throws Exception 
	{
		test4();
		test3();
		ReflectDemo.test2();
		ReflectDemo.test1();
	}
	//在String泛型修饰的集合内放入Integer对象
	public static void test4() throws Exception
	{
		List<String> list=new ArrayList<String>();
		list.add("strlist");
		System.out.println("==============="+list.size());
		Class<Object> cla=(Class<Object>) Class.forName("java.util.List");
		Method met=cla.getMethod("add", Object.class);
		met.invoke(list, new Integer(1));
		System.out.println("==============="+list.size());
		for (int i=0;i<list.size();i++)
		{
			System.out.println(String.valueOf(list.get(i)));
		}
		System.out.println("==============="+list.size());
	}
	//把对象的属性值改变
	public static void test3() throws Exception
	{
		Person per=new Person(112,"aAAGGGasdJHdzdanacca");
		 System.out.println(per);	
		//获取类的字节码对象
		Class cla=Class.forName("ljt.reflect.Person");
		//获取此对象的所有字段
		Field[] fileds=cla.getDeclaredFields();
	    for (Field field : fileds) 
	    {
	    	field.setAccessible(true);
			//如果此字段是String类型的话
	    	if(field.getType()==String.class)
	    	{
	    		//获取此字段的内容
	    		String oldField=(String)field.get(per);
	    		//将字段中的小写字母全部转换为大写字母
	    		char[] oldChar=oldField.toCharArray();
	    		for (int i=0;i<oldChar.length;i++) 
	    		{
					if(oldChar[i]>96)
					{
						oldChar[i]=(char)(oldChar[i]-32);
					}
				}
	    		String newField=new String(oldChar);
	    		//将对象的相应字段值改变
	    		field.set(per, newField);
	    	}
		}
		  System.out.println(per);	
	}
	//反射的三种方式
	public static void test1() 
			throws ClassNotFoundException
	{
		/*
		 * 得到各个字节码对应的实例对象( Class类型)
			三种方式:
			1.
			类名.class,例如,System.class
			2.
			对象.getClass(),例如,new Date().getClass()
			3.
			Class.forName("类名"),例如,Class.forName("java.util.Date");*/
		//类名.class,例如,System.class
		Class<String> c1=String.class;
		//对象.getClass(),例如,new Date().getClass()
		Class<String> c2=(Class<String>)new String().getClass();
		//Class.forName("类名"),例如,Class.forName("java.util.Date")
		Class<String> c3=(Class<String>)Class.forName("java.lang.String");
		System.out.println((c1==c2)+"--"+(c1==c3));
	}
	//利用反射获取构造器
	public static void test2() 
	throws 
	NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
	{
		/*
		 * Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
		 * 方法:
		 *  Constructor<T>   getConstructor(Class<?>... parameterTypes) 
          		返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 
 			Constructor<?>[] getConstructors() 
          		返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 
			
		java.lang.reflect 类 Constructor<T>
		Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
		方法:
		 T  newInstance(Object... initargs) 
          	使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 
		 * */
		Class<String> c1=String.class;
		//获取参数列表为一个String类型的对象的构造方法
		Constructor<String> const1=c1.getConstructor(String.class);
		//通过Constructor的newInstance方法获取String的对象
		String str=const1.newInstance("ijava");
		System.out.println(str);
		//无参构造可以直接使用字节码对象创建该类的实例
		String str2=c1.newInstance();
		str2="ljt";
		System.out.println(str2);
		
	}
}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。