java反射机制

1.定义 

                正常情况是java虚拟机根据类的定义,创造出一个对象。反射则是相反的过程,可以根据一个对象的引用,解析它的定义信息,如方法、属性等,进而可以操作它的属性,调用他的方法,当然也可以创建胡新的对象。


2.反射机制使用核心

        1)获得想要操作类的Class对象

               1>使用Class的静态方法forName,通过类的完整包名+类名获得

               2>使用类的.class属性

               3>调用对象的getClass方法

		Class<?> c1 = null;
		Class<?> c2 = null;
		Class<?> c3 = null;
		try 
		{
			c1 = Class.forName("my.acm.Demo");
		} 
		catch (ClassNotFoundException e) 
		{
			e.printStackTrace();
		}
		
		c2 = Demo.class;
		c3 = new Demo().getClass();
		
		System.out.println(c1.getName());
		System.out.println(c2.getName());
		System.out.println(c3.getName());
                 结果为:

my.acm.Demo
my.acm.Demo
my.acm.Demo

        2)通过获得的Class对象取得操作类的方法
                    1>获得类中所有方法:getMethods()

class Demo
{
	public Demo()
	{
		System.out.println("no param constructor");
	}
	public Demo(String string)
	{
		System.out.println(string);
	}
	public Demo(int i,double d)
	{
		System.out.println(i+" "+d);
	}
	public void test()
	{
		System.out.println("this is a test");
	}
	public void test(String string)
	{
		System.out.println("this is a test: "+ string);
	}
	
	private int age;
	protected String name;
	public long id;
	float score;
}

		Class<?> c3 = new Demo().getClass();
		
		Method[] methods = c3.getMethods();
		for(Method m:methods)
			System.out.println(m);
                       结果为:

public void my.acm.Demo.test()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

                   2>获根据方法名称得类中方法:getMethod( String name, Class<?>... parameterTypes)
                       
			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Method method = demoClazz.getMethod("test");
			System.out.println(method);
                       结果为:

public void my.acm.Demo.test()

                   3>获得所有构造方法: Constructor<?>[] java. lang. Class.getConstructors()
			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Constructor<?>[] cons = demoClazz.getConstructors();
			 
			for(Constructor<?> con:cons)
				 System.out.println(con);
                     结果为:

public my.acm.Demo()
public my.acm.Demo(java.lang.String)
public my.acm.Demo(int,double)
                   

        3)通过获得的Class对象生成具体类对象
                   1>使用无参构造方法生成:

                       1-使用Class对象的   ? java.lang.Class.newInstance()  

			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Demo demo = (Demo) demoClazz.newInstance();
			System.out.println(demo);
                   结果为:

my.acm.Demo@15ff48b
                        2-先获得无参构造方法的Method,再调用该Method对象的   ? java. lang. reflect. Constructor.newInstance( Object... initargs) 
			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Constructor<?>[] cons = demoClazz.getConstructors();
			Demo demo = (Demo) cons[0].newInstance();
			System.out.println(demo);
                  结果为:

my.acm.Demo@f6a746

                    2>使用含参数构造方法生成:此时必须先获得构造方法对象Method,再调用? java.lang.reflect.Constructor.newInstance (Object... initargs) 
			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Constructor<?>[] cons = demoClazz.getConstructors();
			Demo demo1 = (Demo) cons[0].newInstance();
			Demo demo2 = (Demo) cons[1].newInstance("constructor 1");
			Demo demo3 = (Demo) cons[2].newInstance(8,8.8d);
			System.out.println(demo1);
			System.out.println(demo2);
			System.out.println(demo3);
                 结果为:

no param constructor
constructor 1
8 8.8
my.acm.Demo@15ff48b
my.acm.Demo@affc70
my.acm.Demo@1e63e3d

        4)通过获得的Class对象获得对应类中的属性
                    1>获得所有属性:
			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Field[] fields = demoClazz.getDeclaredFields();
			for(Field f:fields)
			{
				int modifyNo = f.getModifiers();
				String modifyName = Modifier.toString(modifyNo);     //0-默认  1-public  2-private  4-protected
				
				Class<?> type = f.getType();
				String fieldName = f.getName();
				
				System.out.println(modifyName+" "+type.getName()+" "+fieldName);
			}
                  结果为:

private int age
protected java.lang.String name
public long id
                  注意: getDeclareFields会获得类中所有属性,包括private、protected、public和默认的,但是getFields只会获得public的属性( 方法同样也是这样


                   2>获得指定属性:Fieldjava.lang.Class.getDeclaredField(String name)(获得任意访问修饰符属性

                                                   Fieldjava.lang.Class.getField(String name) (只能获得public修饰的属性

			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Field f = demoClazz.getField("name");
			
			int modifyNo = f.getModifiers();
			String modifyName = Modifier.toString(modifyNo);
			
			Class<?> type = f.getType();
			String fieldName = f.getName();
			System.out.println(modifyName+" "+type.getName()+" "+fieldName);
                     结果为:

protected java.lang.String name

        5)通过获得的Method对象调用方法
			Class<?> demoClazz = Class.forName("my.acm.Demo");

			 Method method1 = demoClazz.getMethod("test");
			 method1.invoke(demoClazz.newInstance());
			 
			 Method method2 = demoClazz.getMethod("test",String.class);
			 method2.invoke(Demo.class.newInstance(), "mm");
             结果为:

no param constructor
this is a test
no param constructor
this is a test: mm

        6)操作属性
			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Demo demo = (Demo) demoClazz.getConstructor(String.class).newInstance("hello");
			Field f = demoClazz.getDeclaredField("age");
			f.set(demo, 18);
			System.out.println(demo.getName());
                  会跑出异常

java.lang.IllegalAccessException: Class my.acm.Reflect can not access a member of class my.acm.Demo with modifiers "private"
               因为访问的是私有属性,但是没有设置访问权限,所以会抛出这种异常

               解决方案:设置访问权限为true

			Class<?> demoClazz = Class.forName("my.acm.Demo");
			Demo demo = (Demo) demoClazz.getConstructor(String.class).newInstance("hello");
			Field f = demoClazz.getDeclaredField("age");
			f.setAccessible(true);
			f.set(demo, 18);
			System.out.println(demo.getAge());
               结果为:

hello
18


3.反射机制理解

                在ClassLoader加载class文件的时候,加入方法区的所有信息,最后都会形成Class类的实例,代表这个被装载的类。方法区中的所有信息,都是可以通过这个Class类对象反射得到。

               对象是类的实例,同类的各个对象之间,属性相同,方法相同,区别只是属性的值不同。同样的,我们所有的类,都是Class类的实例,都有相同的结构:Field数组、Method数组。而各个类中的属性都保存在Field中,方法都保存在Method数组中。

              Class源码中有这样的声明:

    private native Field[]       getDeclaredFields0(boolean publicOnly);
    private native Method[]      getDeclaredMethods0(boolean publicOnly);
    private native Constructor[] getDeclaredConstructors0(boolean publicOnly);
    private native Class[]       getDeclaredClasses0();
             均为native方法,从JVM中取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值