黑马程序员_Java高新技术:反射


------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 


反射



反射技术:把Java类中的各种成分映射成相应的java类
具体实现:
其实就是动态加载一个指定的类(该类可以从配置文件获取),并获取该类中的所有的内容。而且将字节码文件封装成对象,
并将字节码文件中的内容都封装成对象,这样便于操作这些成员。简单说:反射技术可以对一个类进行解剖。


反射的好处:大大的增强了程序的扩展性。


反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。
-------------------------------------------------------------------


获得Class对象的三种方式:


//前两种方式不利于程序的扩展,因为都需要在程序使用具体的类来完成。


1:通过每个对象都具备的方法getClass来获取。弊端:必须要创建该类对象,才可以调用getClass方法。


Person p = new Person();
Class clazz = p.getClass;


2:每一个数据类型(基本数据类型和引用数据类型)都有一个静态的属性class。弊端:必须要先明确该类。
Class clazz = Person.class;
3:使用的Class类中的方法,静态的forName方法。 //这种方式的扩展性最强,只要将类名的字符串传入即可。
// 根据给定的类名来获得用于类加载
String classname = "Person"; // 来自配置文件
Class clazz = Class.forName(classname); // 此对象代表Person.class


-------------------------------------------------------------------


创建指定类对象的两种方式(其实就是对象在进行实例化时的初始化方式):
1,调用空参数的构造函数:使用了Class类中的newInstance()方法。
2,调用带参数的构造函数:
(1)、获取指定参数列表的构造函数对象
(2)、通过该构造函数的对象的newInstance(实际参数) 进行对象的初始化。
一般情况下,被反射的类,内部通常都会提供一个公有的空参数的构造函数。


public class Person {


	/**
	 * @param args
	 */
	private String name;
	private int age;
	Person()
	{
		super();
		System.out.println("Person run");
	}
	Person(String name ,int age)
	{
		this.age = age;
		this.name = name;
	}
	public static void staticShow()
	{
		System.out.println("static show run");
	}
	public void show(String name ,int age)
	{
		System.out.println("show run"+name+"--"+age);
	}
	public String toString()
	{
		return age+"--"+name;
	}
	public static void main(String[] args) {
		


	}


}
import java.lang.reflect.Constructor;


public class Reflect_GetConstructor {


	/**
	 * 通过指定的构造函数初始化对象
	 * 1、获取文件字节码对象
	 * 2、再获取给定的构造函数
	 * 3、通过构造函数初始化对象
	 * 
	 */
	public static void main(String[] args) throws Exception {
		
		String className = "Person";
		Class clazz = Class.forName(className);


		//该实例化对象的方法调用就是指定类中的空参数构造函数,给创建对象进行初始化.
		Constructor constructor = clazz.newInstance();		


		//获取指定的构造器。获取Person类中两个参数String,int的构造函数的形参。
		Constructor constructor = clazz.getConstructor(String.class,int.class);


		//有了构造器对象后,通过构造器对象来初始化该类对象。
		conn.newInstance("wangwu",21);
		
		
	}


}


-------------------------------------------------------------------
import java.lang.reflect.Method;

public class Reflect_GetMethod {


	/**
	 * 获取方法。
	 * 
	 */
	public static void main(String[] args) throws Exception {
		
		getMethodDemo();//非静态方法的调用
		getMethodDemo2();//静态方法的调用
	}


	public static void getMethodDemo2() throws Exception {
		
		String className = "Person";
		Class clazz = Class.forName(className);
		
		String methodName = "staticShow";
		
		//无参数,所以为null
		Method method = clazz.getMethod(methodName,null);
		
		//该方法是静态的,可以用类名调用,所以为空。
		method.invoke(null,null);
	}


	public static void getMethodDemo() throws Exception {
		
		String className = "Person";
		Class clazz = Class.forName(className);
		
		String methodName = "show";
		Method method = clazz.getMethod(methodName,String.class,int.class);
		
		Object obj = clazz.newInstance();
		
		method.invoke(obj, "wangwu",20);
		
		
	}


}


-------------------------------------------------------------------
获取类中所有构造器:
	String className = "Person";
	Class clazz = Class.forName(className);


	Constructor[] constructors = clazz.getConstructors();//只包含公共的构造函数
	//constructors = clazz.getDeclaredConstructors();包含私有的构造函数
	for(Constructor con : constructors)
	{
		System.out.println(con);
	}

获取类中所有的方法:	
	Class clazz = Class.forName("Person");
	Method[] methods = clazz.getMethods();//获取的是该类中的公有方法和父类中的公有方法。
	//methods = clazz.getDeclaredMethods();获取本类中的方法,包含私有方法。
	for(Method method : methods)
	{
		System.out.println(method);
	}
	


-------------------------------------------------------------------
运行私有方法。
public static void method_3() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
//想要获取私有方法。必须用getDeclearMethod();
Method method = clazz.getDeclaredMethod("method", null);
// 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。
method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。
}


-------------------------------------------------------------------
import java.lang.reflect.Field;




public class Reflect_GetField {


	/**
	 * 获取字段。
		getXXX:获取的都是类中公共的成员。
		getDeclaredXXX:获取本类已定义的成员。
	 
	 */
	public static void main(String[] args) throws Exception {
		
		getFieldDemo();
	}


	public static void getFieldDemo() throws Exception {
		
		String className = "Person";
		Class clazz = Class.forName(className);
		
		//获取字段
		String fieldName = "age";
		//Field field = clazz.getField(fieldName);	NoSuchFieldException,因为age是私有的,该方法获取的是公共字段。
		
		//getDeclaredField()能访问私有的成员。
		Field field = clazz.getDeclaredField(fieldName);
		
		//对其进行值得设定,必须先有对象。
		Object obj = clazz.newInstance();
		
		//通过查找父类AccessiableObject的方法。setAccessiable(true);
		field.setAccessible(true);//取消权限检查,暴力访问。
		
		field.set(obj, 30);//IllegalAccessException字段是私有的。
		
	}


}


-----------------------------------------------------------------------
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;




public class FieldDemo {


	/**
	 *将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"。
	 * 思路:
	 * 1、对象类型不明确,需要用到反射。
	 * 2、
	 * 步骤:
	 * 1、通过forName方法获取该对象的字节码对象。
	 * 2、用Field[]存储getFields()方法获得的该字节码对象中的所有类型的字段。	
	 * 3、对获取到的所有字段进行迭代操作,用field.getType()==String.class判断该字段是否为String类型
	 * 4、get()
	 * 5、set()
	 */
	public static void main(String[] args) throws Exception {
		
		//changeStringVaule();
		
		
		//getMethod();
		getMainMethod();
	}


	//调用任意对象main方法
	public static void getMainMethod() throws Exception {
		
		String className = "test";
		Class clazz = Class.forName(className);
		//Object obj = clazz.newInstance();
		Method method = clazz.getMethod("main", String[].class);
		
		
		//method.invoke(null,new Object[]{new String[]{"111"}});
		method.invoke(null,(Object)new String[]{"111"});
	}


	public static void getMethod() throws Exception {
		//Method method = String.class.getMethod("charAt", int.class);
		String className = "test";
		Class clazz = Class.forName(className);
		Object obj = clazz.newInstance();
		Method method = clazz.getMethod("show",null);
		
		method.invoke(obj);
	}


	public static void changeStringVaule() throws Exception {
		//给我一个类名
		String className = "test";
		//通过该类名,获取该类名的字节码对象,并对该字节码对象进行初始化。
		Class clazz = Class.forName(className);
		//获取该字节码对象对应的实例,这句话相当于 test t1 = new test(); 
		Object obj = clazz.newInstance();
				
		//获取字节码对象的所有字段。
		Field[] fields = clazz.getFields();
		//对字节码对象中的字段进行迭代。
		for (Field field : fields) {


			//if(field.getType().equals(String.class))
			if(field.getType()==String.class)			
			{
				//返回指定对象上此 Field 表示的字段的值。获取的是obj这个对象的String类型的变量。
				String oldVaule = (String)field.get(obj);
				String newVaule = oldVaule.replace('b', 'a');
				//设置obj这个对象的新字符串。将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
				field.set(obj, newVaule);
				System.out.println(newVaule);
			}
			
		}
		System.out.println(new test());
	}


}

public class test {


	/**
	 * @param args
	 */
	public String str1 = "ball";
	public String str2 = "basktball";
	
	public test(){}
	
	public test(String str1, String str2) {
		super();
		this.str1 = str1;
		this.str2 = str2;
	}


	public static void main(String[] args) {
		// TODO Auto-generated method stub
		show();
	}


	@Override
	public String toString() {
		return str1+"--"+str2;
	}
	public static void show()
	{
		System.out.println("show run");
	}
	
}



------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值