zoukankan      html  css  js  c++  java
  • Java反射机制学习

    什么是反射

    在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    反射有什么用

    1,在运行时判断任意一个对象所属的类;

    2,在运行时构造任意一个类的对象;

    3,在运行时判断任意一个类所具有的成员变量和方法;

    4,在运行时调用任意一个对象的方法;

    5,生成动态代理。

    实现Java反射的类

    1)Class:它表示正在运行的Java应用程序中的类和接口
    2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限
    3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限
    4)Method:提供关于类或接口中某个方法信息

    注意:Class类是Java反射中最重要的一个功能类,所有获取对象的信息(包括:方法/属性/构造方法/访问权限)都需要它来实现

    编写Java反射程序的步骤:

    1)必须首先获取一个类的Class对象
    例如:
      Class c1 = Test.class;
      Class c2 = Class.forName(“com.reflection.Test”);
      Class c3 = new Test().getClass();

    2)然后分别调用Class对象中的方法来获取一个类的属性/方法/构造方法的结构 注意:如果要能够正常的获取类中方法/属性/构造方法应该重点掌握如下的反射类

      Field
      Constructor
      Method

    在此给出一个总结性的例子:

    package com.gbx;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    interface IBase{
    	void show();
    }
    class Base{
    	
    }
    class Person extends Base implements IBase{
    	private int id;
    	public String name;
    	protected int[] ages;
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public Person() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	public Person(int id, String name, int[] ages) {
    		super();
    		this.id = id;
    		this.name = name;
    		this.ages = ages;
    	}
    	@Override
    	public void show() {
    		System.out.println("人物信息为:" +id + " " + name + " " + ages);
    	}
    }
    public class Test {
    	
    	/*
    	 * 动态获取指定类的各种信息
    	 * 1,在运行时判断任意一个对象所属的类;
    	 * 2,在运行时构造任意一个类的对象;
    	 * 3,在运行时判断任意一个类所具有的成员变量和方法;
    	 * 4,在运行时调用任意一个对象的方法;
    	 */
    	public static void test1() throws ClassNotFoundException{
    		Class c1 = Class.forName("com.gbx.Person");
    		Class c2 = Person.class;
    		Class c3 = new Person().getClass();
    		
    		/*
    		 * 获取类所在包名, 通过输出可以看到, 这三种方式得到的Class是一样的
    		 */
    		String packe1 = c1.getPackage().toString();
    		String packe2 = c2.getPackage().toString();
    		String packe3 = c3.getPackage().toString();
    		System.out.println(" packe1 = " + packe1 + "
     packe2 = " + packe2 + "
     packe3 = " + packe3);
    		System.out.println("c1 == c2 : " + (c1 == c2) + "c2 == c3" + (c2 == c3));
    		
    		/*
    		 * 获得类的访问修饰符
    		 */
    		int mod = c1.getModifiers();
    		//可以输出看看
    		//System.out.println(Modifier.toString(0) + " : " + Modifier.toString(1) + " : " +Modifier.toString(2) + " : " + Modifier.toString(3) + ":" + Modifier.toString(4));
    		System.out.println(Modifier.toString(mod));
    		
    		/*
    		 * 获取制定类的完全限定名字
    		 */
    		String calssName = c1.getName();
    		System.out.println("calssName = " + calssName);
    		
    		/*
    		 * 获取指定类的父类
    		 */
    		Class superCalss = c1.getSuperclass();
    		System.out.println("superClassName = " + superCalss.getName());
    		
    		/*
    		 * 获取指定类的实现的接口
    		 */
    		Class[] interfaces = c1.getInterfaces();
    		for (Class inf : interfaces) {
    			System.out.println("interface name : " + inf.getName());
    		}
    		
    		//一下三部分的获取对于我们来说至关重要。。分别是:构造函数, 成员变量, 成员方法
    		
    		/*
    		 * 获取指定类的构造函数  涉及的类:Constructor
    		 */
    		Constructor[] constructors = c1.getConstructors();
    		System.out.println("构造方法有:");
    		for (Constructor c : constructors) {
    			//访问修饰符
    			mod = c.getModifiers();
    			String modfier = Modifier.toString(mod);
    			//构造函数名字
    			String name = c.getName();
    			System.out.print(modfier + " " + name + "(");
    			//参数列表
    			Class[] paramTypes = c.getParameterTypes();
    			for (int i  = 0; i < paramTypes.length; ++i) {
    				if (i > 0) {
    					System.out.print(",");
    				}
    				if (paramTypes[i].isArray()) {
    					System.out.print(paramTypes[i].getComponentType().getName() + " [] ");
    				} else {
    					System.out.print(paramTypes[i].getName());
    				}
    			}
    			System.out.println(")");
    		}
    		
    		/*
    		 * 获取指定类的成员变量 涉及到的类 Field
    		 */
    		Field[] fields = c1.getDeclaredFields();
    		System.out.println("声明的成员变量有:");
    		for (Field field : fields) {
    			mod = field.getModifiers();
    			String modifier = Modifier.toString(mod);
    			System.out.print(modifier + " ");
    					
    			Class type = field.getType();
    			if (type.isArray()) {
    				System.out.print(type.getComponentType().getName() + " ");
    			} else {
    				System.out.print(type.getName() + " ");
    			}
    			String name = field.getName();
    			System.out.println(name);
    		}
    		
    		/*
    		 * 获取指定类的成员方法 涉及的类Method
    		 */
    		Method[] methods = c1.getDeclaredMethods();
    		System.out.println("成员方法有:");
    		
    		for (Method method :methods) {
    			mod = method.getModifiers();
    			String modifer = Modifier.toString(mod);
    			System.out.print(modifer + " ");
    			
    			Class returnType = method.getReturnType();
    			if (returnType.isArray()) {
    				System.out.print(returnType.getComponentType().getName() + " ");
    			} else {
    				System.out.print(returnType.getName() + " ");
    			}
    			String name = method.getName();
    			System.out.print(name + " ( ");
    			Class[] paramTypes = method.getParameterTypes();
    			for (int i = 0; i < paramTypes.length; ++i) {
    				if (i > 0){
    					System.out.println(",");
    				}
    				if (paramTypes[i].isArray()) {
    					System.out.print(paramTypes[i].getComponentType().getName());
    				} else {
    					System.out.print(paramTypes[i].getName());
    				}
    			}
    			System.out.println(" )");
    		}
    	}
    	/*
    	 * 生成动态代理。
    	 */
    	public static void test2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
    		Class c1 = Class.forName("com.gbx.Person");
    		Person p = (Person)c1.newInstance();
    		System.out.println("id  = " + p.getId());
    		System.out.println("name = " + p.getName());
    		
    		Method method = c1.getDeclaredMethod("setName", String.class);
    		method.setAccessible(true); //通过这一步设置我们甚至可以访问private的成员
    		method.invoke(p, "小明");
    		System.out.println("id  = " + p.getId());
    		System.out.println("name = " + p.getName());
    		
    		
    		
    	}
    	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
    		test1();
    		test2();
    	}
    }
    
    输出:
     packe1 = package com.gbx
     packe2 = package com.gbx
     packe3 = package com.gbx
    c1 == c2 : truec2 == c3true
    
    calssName = com.gbx.Person
    superClassName = com.gbx.Base
    interface name : com.gbx.IBase
    构造方法有:
    public com.gbx.Person(int,java.lang.String,int [] )
    public com.gbx.Person()
    声明的成员变量有:
    private int id
    public java.lang.String name
    protected int ages
    成员方法有:
    public void setId ( int )
    public void show (  )
    public java.lang.String getName (  )
    public int getId (  )
    public void setName ( java.lang.String )
    id  = 0
    name = null
    id  = 0
    name = 小明
    

      

    反射调用参数维数组的方法:

    public class DemoTest {
    	/*
    	 * 利用反射对参数是数组的方法的调用。
    	 * 由于JDK5之前没有可变参数, 我们如果实现参数任意的话,就需要使用object[]来实现
    	 * JDK5出现之后我们有了可变参数的就很方便了,但是为了兼容之前的代码,我们的可变参数接受数组,
    	 * 然后将数组中的变量一个一个的放入对应的对应的变量。
    	 * 如果方法参数是数组,例如public void show(String[] res)
    	 * method.invoke(1,2);第二个参数接受的是的可变参数,我们传入一个数组的话,他会将数组中的第一
    	 * 个值作为res的。后边的继续作为下一个参数。所以不会找到
    	 */
    	@Test
    	public void test() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    		Class clazz =  Class.forName("com.cn.gbx.Person");
    		Method method = clazz.getMethod("main",String[].class);
    		method.invoke(null, new Object[]{new String[]{"a", "b"}});// 第一种解决方案
    	}
    	
    	@Test
    	public void test2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    		Person p = new Person();
    		Class<?> clazz =  Class.forName("com.cn.gbx.Person");
    		Method method = clazz.getMethod("show", String[].class);
    		method.invoke(p, (Object)new String[]{"aa","bb"}); //第二种解决方案
    		
    	}
    }
    
    
    package com.cn.gbx;
    
    public class Person {
    	
    	public static void main(String[] args) {
    		System.out.println("main invoke ...");
    	}
    	
    	public void show(String[] res) {
    		System.out.println("string[] res");
    		for (String s : res) {
    			System.out.println(s);
    		}
    	}
    }
    

      

  • 相关阅读:
    eclipse工具
    Tag
    JSP模版
    Eclipse断点调试
    JavaBean
    验证码设计
    在IE中提示404错误
    序列化与反序列化
    文件编码问题
    强类型,弱类型和推断类型
  • 原文地址:https://www.cnblogs.com/E-star/p/3435984.html
Copyright © 2011-2022 走看看