天天看点

【反射学习总结(下)】

通过对反射(上)总结:

我们知道:反射就是:把各个java类中的成分全部映射到相应的java类中来。

下面我们来总结一下反射出来的一些基本的JAVA类:

主要有以下几个方面的内容:

《一、Method类》java类中的基本方法,映射到一个java类是:Method类

《二、Constructor类》java类中的构造方法,映射到一个java类是:Constructor类

《三、Field类》java类中的成员变量,映射到一个java类是:Field类

《四、》怎样用反射的机制去在java文件中调用main方法:该main方法映射出来是一个Method吗?

下面是具体的分析以及代码的演示:

《五、》对数组类型进行反射;

《一、Method类》java类中的基本方法,映射到一个java类是:Method类

<span style="font-size:18px;">/*
	这个实例是通过反射思想达到调用类中的函数方法
	函数方法类:Method
*/
import java.lang.reflect.*;
class TestMethod
{
	private String name;
	private int age;
	private String sex;
	TestMethod(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
	
	TestMethod(String name,int age,String sex)
	{
		this(name,age);
		this.sex=sex;
	}

	public void comparaAge(TestMethod tm)
	{
		if (this.age==tm.age)
		{
			System.out.println(this.name+"和"+tm.name+"是同龄人");
		}else
		{
			System.out.println(this.name+"和"+tm.name+"不是同龄人");
		}
	}

	public void setName(String name)
	{
		this.name=name;
	}
	public String getName()
	{
		return name;
	}
	public void setAge(int age)
	{
		this.age=age;
	}
	public int getAge()
	{
		return age;
	}

	public void setSex(String sex)
	{
		this.sex=sex;
	}
	public String getSex()
	{
		return sex;
	}

}
class MethodDemo5 
{
	public static void main(String[] args) throws Exception
	{
		TestMethod tm1=new TestMethod("wang",28);
		TestMethod tm2=new TestMethod("lulu",26);

		Method[] methods=tm1.getClass().getDeclaredMethods();
		for (Method method : methods)
		{
			System.out.println(method);
		}
		
		//通过反射做出:tm1.comparaAge(tm2);
		Method comparaAge=tm1.getClass().getMethod("comparaAge",TestMethod.class);
		comparaAge.invoke(tm1,tm2);

		//通过反射获取到构造方法,在用反射的方式调用其构造函数
		//实现:new TestMethod("wang",30,"男");
		
		//下面是实现:TestMethod tm_now=new TestMethod("wang",30,"男");
		Class[] clss=new Class[]{String.class,int.class,String.class};

		Constructor con=tm1.getClass().getDeclaredConstructor(clss);
		System.out.println(":"+con);
		//创建一个新的构造函数实例
		TestMethod tm_now=(TestMethod)con.newInstance("wang",30,"男");
		System.out.println(tm_now.getSex());

		//这仅仅是得到所有声明的构造方法,因为可能有多个构造函数的情况,所以用遍历的思想
		//展示:
		Constructor[] cons=tm1.getClass().getDeclaredConstructors();
		for (Constructor con : cons )
		{
			System.out.println(con);
		}
	}
}</span>
           

《二、Constructor类》java类中的构造方法,映射到一个java类是:Constructor类

实例分析:

<span style="font-size:18px;">/*
演示:通过反射的思想得到指定类中带参数的构造方法去创建新的指定对象
用反射的思想去完成str的对象创建
String str=new String(new StringBuffer("abc"));
构造方法的类:Constructor
重点:
1.获取构造函数类对象,很关键(编译时段)
2.得到类构造函数是,还得把参数从新传入(运行时段)
*/
import java.lang.reflect.*;
class ReflectDemo03 
{
	public static void main(String[] args) throws Exception
	{
		//这是用反射的机制去是做通过得到类的实例之后,再调用其方法
		//下面是通过实例获取了String类中带StringBuffer类型参数的构造方法
		Constructor cons=String.class.getConstructor(StringBuffer.class);
		//创建一个string的实例对象(通过该构造方法对象new出一个具体的实例来)
		String str=(String)cons.newInstance(new StringBuffer("abc"));

		//上述两句相当于String str=new String(new StringBuffer("abc"));
		System.out.println(str); //abc
	}
}</span>
           

《三、Field类》java类中的成员变量,映射到一个java类是:Field类:

实例分析:

<span style="font-size:18px;">/*
需求:改变类中的所有String类型的成员变量字段值
将其值中的所有的a改成b

思路:
1.先获取到该类所有的成员变量类型;用Field数组存储
2.再通过遍历组数拿到每一个成员变量类型;
3.如果成员变量类型是String.class,则获得该类型上的字段值;
4.用replace方法进行字段值的改变;
5.将新的字段值重新设定到当前的成员变量类型中去
*/
import java.lang.reflect.*;
class StringText
{
	public String name1;
	public int age;
	public String name2;

	StringText(String name1,int age,String name2)
	{
		this.name1=name1;
		this.age=age;
		this.name2=name2;
	}

	public String toString()
	{
		return name1+": "+age+": "+name2;
	}
}

class RepleceStringDemo4 
{
	public static void main(String[] args) throws Exception
	{
		//初始化
		StringText st=new StringText("niuren",60,"nihao");
		
		//调用能改变成员变量值的自定义反射方法
		changeStringValue(st);

		//自动打印出自定义的toString方法
		System.out.println(st);
	}

	//这里通过反射的机制去改变其字段的具体值的方法:
	public static void changeStringValue(Object obj) throws Exception
	{
		//1:获取类中所有成员变量类型,用Field数组存储
		Field[] fields=obj.getClass().getFields();
		//2:遍历出每一中成员变量类型
		for (Field field : fields)
		{
			//3:只找到属于String类型的成员变量,进行修改操作
			if (field.getType() == String.class)
			{
				String old_str=(String)field.get(obj);
				//4:用replace方法进行字段值的改变;
				String new_str=old_str.replace('a','b');
				//5:将新的字段值重新设定到当前的成员变量类型中去
				field.set(obj,new_str);
			}
		}
	}

	//运行结果:niuren: 60: nihbo
}</span>
           

《四、》怎样用反射的机制去在java文件中调用main方法:该main方法映射出来是一个Method吗?

/*
	这个例子是:通过反射的思想去调用main方法
*/
import java.util.*;
import java.lang.reflect.*;
class Test
{
	public static void main(String[] args)
	{
		/*main函数中的主体内容*/
		for (String arg: args )
		{
			System.out.println(arg);
		}
	}
}

class ReflectMainDemo6 
{
	public static void main(String[] args) throws Exception 
	{
		//常规调用方式:
		//Test.main(new String[]{"123","wang","你好"});
		String str=args[0];
		Method main_method=Class.forName(str).getMethod("main",String[].class);
		main_method.invoke(null,(Object)new String[]{"123","wang","你好"});

		/*在DOS中运行的时候:
		  先是编译通过之后,用:java ReflectMainDemo6 Test
		  这里的Test是作为字符串传递的,相当于在代码中Class.forName(str)的位置,该字符串
		  其实就是被调用的类,如果有包的话,Test前面加上“包名称.”就是OK了
		 */

		/*注意invoke中(null,String数组):
		明白null的含义和当传入String数组时报错的原因:
		1.上述中,因为是调用静态的main函数,所以直接用null,
		但是传递参数的时候
		2.传递一个String类型的数组原理上对的,但是jdk1.5为了和jdk1.4相和谐,会自动
		把数组拆开,把其三个内容都作为参数传递,这样的话就悲催了,会报错!
		因为只要一个参数传入,却传入了3个,所以必须对String数组进行封包操作,让JVM去
		自动拆开是就是一个数组参数,这样就OK了
		所以可以写成:main_method.invoke(null,new String[]{new String[]{"123","wang","你好"}});
		或者是告诉jvm我传入的就是一个参数:main_method.invoke(null,(Object)new String[]{"123","wang","你好"});
		*/
	}
}
           
<pre name="code" class="java" style="line-height: 26px;"><span style="background-color: rgb(255, 255, 255); font-family: Arial;">《五、》对数组类型进行反射;</span>
           
<span style="font-size:18px;">/*
	对数组类型进行反射
*/
import java.lang.reflect.*;
class ReflectArrayDemo6 
{
	public static void main(String[] args) throws Exception
	{
		int[] int_Arr=new int[]{234,45,68,90};
		String string_Arr="wangwang,lulu,jiejie";

		showReflectArray(int_Arr);
		showReflectArray(string_Arr);
	}

	public static void showReflectArray(Object obj) throws Exception
	{
		Class cls=obj.getClass();//获取当前对象的
		//判断是不是数组类型,才进行操作
		if (cls.isArray())
		{
			int length=Array.getLength(obj); //通过反射机制获取到其数组内容中的元素个数
			
			//遍历数组中的内容
			for (int i=0;i<length;i++ )
			{
				System.out.println(Array.get(obj,i));
			}
		}else
		{
			System.out.println(obj);
		}
		
		/*打印的结果
		234
		45
		68
		90
		wangwang,lulu,jiejie
		*/
	}
}
</span>
           

上述这些被反射出来的类都是最常用的类!具体的学习,主要还是要多多使用jdk帮助文档,这样才能更好的掌握其基本反射特点!

继续阅读