黑马程序员_反射

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ---------------------


透彻分析反射的基础_Class类


    java程序中各个java类同属于一类事物,描述这类事物的java类名就是Class。
    Class类代表java类,它的各个实例对象对应各个类在内存中的字节码
    一个类被加载器加载到内存中,占用一片存储空间,这个空间里的内容就是类的字节码

    Person p1 = new Person();

    Class cls1 = Person.class;//字节码

    得到字节码对应的实例对象(Class类型)
        类名.Class    //Person.class
        对象.getClass();    //p1.getClass();
        Class.forName("类名")    //Class.forName("java.lang.String")
        
    九个预定义Class实例对象(八个基本数据类型和void)
        int.class == Integer.TYPE
    数组类型的Class实例对象
        Class.isArray();

    只要是在源程序中出现的类型,都有各自的Class实例对象,例如int[],void ...

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


构造方法的反射应用


Constructor类代表某个类中的一个构造方法

得到某个类所有构造方法
    Constructor[] constructor = Class.forName("java.lang.String").getConstructor;
得到某一个构造方法
    Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
    获得方法时要用到的类型

创建实例对象
    通常方式: String str = new String(new StringBuffer("abc"));
    反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));
    调用获得的方法时要用到上面相同类型的实例对象

Class.newInstance()方法
    例子: String obj = (String)Class.forName("java.lang.String").newInstance();
    该方法内部先得到默认构造方法,然后用该构造方法创建实例对象。
    该方法内部的具体代码是怎样写的?用到了缓存机制来保存默认的构造方法的实例对象。


成员变量的反射


ReflectPoint

public class ReflectPoint {

	private int x;
	public int y;
	
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
}


ReflectTest

public class ReflectTest {

	public static void main(String[] args) throws Exception {

		String str1 = "abc";
		
		Class cls1 = str1.getClass();
		Class cls2 = String.class;
		Class cls3 = Class.forName("java.lang.String");
		
		System.out.println(cls1);
		
		System.out.println(cls1==cls2);
		System.out.println(cls2==cls3);
		
		System.out.println(cls1.isPrimitive());//判断是否是基本类型
		System.out.println(int.class.isPrimitive());
		System.out.println(int.class == Integer.class);
		System.out.println(int.class == Integer.TYPE);
		System.out.println(int[].class.isPrimitive());
		System.out.println(int[].class.isArray());
		
		//构造方法的反射应用
		Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
		String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));
		System.out.println(str2.charAt(2));
		
		//成员变量的反射
		ReflectPoint pt1 = new ReflectPoint(3,5);
		Field fieldY = pt1.getClass().getField("y");
		//fieldY的值不是对象身上的变量,而是类上的,要用它去取某个对象上对应的值
		System.out.println(fieldY.get(pt1));
		Field fieldX = pt1.getClass().getDeclaredField("x");
									//x私有,要获取需要用 getDeclaredField
		fieldX.setAccessible(true);//x私有,要使用需要用这句代码
		System.out.println(fieldX.get(pt1));
	}
}

成员变量的综合案例


将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的b改成a。


ReflectPoint2

public class ReflectPoint2 {

	private int x;
	public int y;
	
	public String str1 = "ball";
	public String str2 = "basketball";
	public String str3 = "itcast";
	
	public ReflectPoint2(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	
	public String toString()
	{
		return str1 + ":" +str2 + ":" +str3;
	}
}


ReflectTest2

public class ReflectTest2 {

	public static void main(String[] args) throws Exception {
	
		ReflectPoint2 pt1 = new ReflectPoint2(3,5);
		
		changeStringValue(pt1);
		System.out.println(pt1);
	}
	
	private static void changeStringValue(Object obj) throws Exception
	{
		Field[] fields = obj.getClass().getFields();
		for(Field field : fields)
		{
			if(field.getType() == String.class)
			{
				String oldValue = (String)field.get(obj);
				String newValue = oldValue.replace('b', 'a');
				field.set(obj, newValue);
			}
		}
	}
}


成员方法的反射


Method类代表某个类中的一个成员方法

得到类中的某一个方法
    Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法
    通常方式:  System.out.println(str.charAt(1));
    反射方法:  System.out.println(charAt.invoke(str,1));

如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法
第一个参数是具体调用该方法的对象,第二个参数是执行该方法的具体参数。

对接收数组参数的成员方法进行反射

写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。
public class ReflectTest3 {

	public static void main(String[] args) throws Exception {

		String str1 = "abc";
		
		Method methodCharAt = String.class.getMethod("charAt", int.class);
		System.out.println(methodCharAt.invoke(str1, 1));
		System.out.println(methodCharAt.invoke(str1, new Object[]{2}));
		
		//对接收数组参数的成员方法进行反射
		String startingClassName = args[0];
		Method mainMethod 
			= Class.forName(startingClassName).getMethod("main", String[].class);
		mainMethod.invoke(null, (Object)new String[]{"aaa","bbb","ccc"});
	}
}

class TestArguments{
	public static void main(String[] args)
	{
		for(String arg : args)
		{
			System.out.println(arg);
		}
	}
}


数组与Object的关系及其反射类型


具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用,非基本类型的一维数组,既可以当作Object类型使用又可以当作Object[]类型使用


Arrays.asList()方法处理int[]和string[]时的差异




数组的反射应用


public class ReflectTest4 {

	public static void main(String[] args) {

		String[] str = new String[]{"a","b","c"};
		Object obj = str;
		printObject(obj);
		printObject("xyz");
	}

	private static void printObject(Object obj) {
		
		Class clazz = obj.getClass();
		if(clazz.isArray())
		{
			int len = Array.getLength(obj);
			for(int i = 0; i < len; i++)
			{
				System.out.println(Array.get(obj, i));
			}
		}
		else
		{
			System.out.println(obj);
		}
	}
}





-----------------------ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值