反射


反射

反射是程序在运行时能够获取自身的信息。


优点

运行时确定类型,绑定对象。动态编译最大发挥java的灵活性,体现多态应用,降低程序耦合性。

缺点

反射其实就是一种解释操作,这种操作慢于直接执行相同操作。


class

class代表java类,就相当于person代表人。

类被加载到内存中,这片内存空间就是类的字节码,不同的类字节码是不同的,一个类在内存中只有一份字节码。


获取字节码的三种方式

public class GetClass {
	public static void main(String[] args)throws Exception{
		Class c1=String.class;                          //调用某个类的class属性获取Class对象
		Class c2=Class.forName("java.lang.String");     //使用Class类的forName(String className)静态方法
		Class c3=new String().getClass();				//用某个对象的getClass()方法,该方法属于Object类
	}
}

预定义Class对象

基本java类型:int,short,long,byte,char,boolean,double,float和关键字void通过class属性也能表示为class对象。

IsPrimitive判断对象是否是基本类型。

IsArry判断对象是否是数组。


public class ClassDemo {
	public static void main(String[] args)
	{
		Class i1=int.class;
		Class i2=Integer.class;
		Class i3=Integer.TYPE;     //包装类都有一个常量TYPE,用来表示其基本数据类型的字节码
		System.out.println(i1);
		System.out.println(i2);
		System.out.println(i3);
		System.out.println(i1==i2);
		System.out.println(i2==i3);  //证明TYPE值是int
		
		Class i4=String[].class;
		Class i5=int[].class;
		/*System.out.println(i4==i5);
		 * 会报错,因为int[]里面的是不是一个对象,String[]里是对象*/
		Class i6=Integer[].class;
		System.out.println(i4==i6);
		//这样就可以,因为Integer[]里放的是对象所以可以String[]里面的对象比赛
		
		System.out.println(i1.isPrimitive());
		//判断i1是否是基本类型
		System.out.println(i4.isArray());
		//判断i4是否是数组类型
	}
}



用Class类获取类的信息

package JustTest;
class Fu{}
interface A{}
interface B{}
class Zi extends Fu implements A,B
{
	public class imclass{}
	//定义一个内部类
	public interface iminterface{}
	//定义一个内部接口
}


public class ClassDemo {
	public static void main(String[] args)
	{
		Class c=Zi.class;
		
		System.out.println(c);
		//得到字节码
		System.out.println(c.getPackage());
		//得到包名
		System.out.println(c.getName());
		//得到全限定名
		System.out.println(c.getSimpleName());
		//得到类名
		System.out.println(c.getSuperclass());
		//得到父类
		System.out.println(c.getSuperclass().getSimpleName());
		//得到父类名
		
		Class[] c2=c.getInterfaces();
		//因为接口可以有很多个,所以用一数组装结果
		for(Class c1:c2)//高级for循环迭代
		{
			System.out.println(c1);
		}
		
		Class[] c3=c.getClasses();
		//得到内部类和内部接口
		for(Class c4:c3)
		{
			System.out.println(c4);
		}
		
		System.out.println(c.getModifiers());
		//得到修饰符,如果返回1,则该类修饰符为public
		
	}
}



Class得到类构造方法(Constructor)、方法(Method)、字段(Field)



得到构造方法和newInstance创建对象

用newInstance方法创建该class对象的实例,此类必须有无参的构造方法

如果构造方法被私有,在创建之前申请访问,也就是将AccessibleObject对象的setAccessible方法设为true



package JustTest;
import java.lang.reflect.*;
public class GetConStructor  {
	public static void main(String[] args)throws Exception
	{
		Class c=String.class;
		Constructor[] con=c.getConstructors();
		////前面的修饰符必须是public才可以在这个方法下获取到
		for(Constructor cons:con)
		{
			System.out.println(cons);
		}
		
		Constructor con2=c.getConstructor(String.class);
		
		//得到指定的构造函数,此函数必需是pulibc。
		//参数是构造方法中的形参
		String str=(String)con2.newInstance("abc");
		//newInstance方法形参是Object,返回的也是Object,所以"abc"传到里面会向上转型
		//赋值时必须向下转型
		
		System.out.println(str);
		
		Constructor[] c2=c.getDeclaredConstructors();
		//暴力反射,不管是否是public 
		for(Constructor con3:c2)
		{
			System.out.println("暴力反射..."+con3);
		}
		
	}
}

步骤

1:获取该类的字节码

2:用Class对象getConstructor()方法获取指定的构造方法

3:申请访问(如果构造方法为public可不用)

4:调用Constructor的newInstance方法创建对象




得到方法和反射调用方法

获得Method对象后,可以用Method中的invoke方法来执行指向的方法

invoke(Object obj,Object...args)obj表示方法的对象,args是方法的参数,如果方法是静态的那么第一个参数写null,形参亦此

package JustTest;
import java.lang.reflect.*;
public class GetMethod {
	public static void main(String[] args)throws Exception
	{
		String str="abcdefg";
		Class c=String.class;
		
		Method[] m=c.getMethods();
		//得到所有方法,包括父类的,但必须是被public修饰过的
		
		for(Method ms:m)
		{
			System.out.println("getMethods.."+ms);
		}
		Method m1=c.getMethod("replace", char.class,char.class);
		//第一个参数是将要获取方法名,第二个参数是可变参数,是该方法的形参字节码
		//该方法的作用是将字符串中的字符替换掉
		str=(String)m1.invoke(str, 'a','b');
		//invoke返回一个Object,要向下转型
		//将a替换成b
		System.out.println(str);
		
		m=c.getDeclaredMethods();
		for(Method ms:m)
		{
			System.out.println("暴力获取..."+ms);
		}
		
				
	}
}



得到字段和反射下修改字段

package JustTest;
import java.lang.reflect.*;
class Person
{
	public String name;
	public int age;
	private char sex;
	Person(String name,int age,char sex)
	{
		this.name=name;
		this.age=age;
		this.sex=sex;
	}
}
public class GetField {
	public static void main(String[] args)throws Exception
	{
		Person p=new Person("张三",18,'m');
		Class c=Person.class;
		
		Field[] fs=c.getFields();
		//得到所有字段
		for(Field f1:fs)
		{
			System.out.println("getFields..."+f1);
		}
		
		Field f=c.getField("name");
		//得到Person中的name字段
		System.out.println(f.get(p));
		//将p对象中的name字段值打印出来
		f.set(p,"李四");
		//将p对象中的name改成"李四"
		
		
		Field f1=c.getDeclaredField("sex");
		//强行指向sex字段
		f1.setAccessible(true);
		//设置访问权限
		f1.set(p,'w');
		//将私有化的sex修改
		
		System.out.println(f1.getChar(p));
		
		
		
		
	}
}



posted @ 2014-07-09 02:25  lisisong  阅读(162)  评论(0编辑  收藏  举报