zoukankan      html  css  js  c++  java
  • JAVA反射实践

     Java反射机制在我的理解当中就是下面几点:

        1. 对一个给定的类名(以字符串形式提供)能动态构建一个对象实例

        2. 对于任意一个类,都能够知道这个类的所有属性和方法

        3. 对于任意一个对象,都能够调用它的任意一个方法和属性;
     
    这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制,这种反射机制在Java当中给我们带来了极大的方便,被大量地应用于JavaBean中
     
    在Java的反射中我们主要用到以下几个类,下面将逐个说明
    1. java.lang.Class;                

    2. java.lang.reflect.Constructor; 

    3. java.lang.reflect.Field;        

    4. java.lang.reflect.Method;

    5. java.lang.reflect.Modifier;

    1.java.lang.Class类:用于保存每个对象所属类的相关信息,在Java中,Object类中的getClass()方法将会返回一个Class类型的实例,(注意:记住这是一个类,和关键字class完全是两码事)
    2.java.lang.reflect.Constructor:提供关于类的单个构造方法的信息以及对它的访问权限。
    3.java.lang.reflect.Field:提供有关类或接口的单个字段的信息,以及对它的动态访问权限
    4.java.lang.reflect.Method:提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
    5.java.lang.reflect.Modifier:提供了类、类的成员、static方法、常量的修饰符。
     
    public class Person {
    	// Field
    	private String person_name;
    	protected int person_age;
    	public boolean person_sex;
    
    	// Construct
    	public Person() {
    		super();
    	}
    
    	public Person(String name, int age, boolean sex) {
    		super();
    		this.setPerson_name(name);
    		this.person_age = age;
    		this.person_sex = sex;
    	}
    
    	// Method
    	public void AddAge(int year) {
    		this.person_age += this.person_age + year;
    	}
    
    	public String getPerson_name() {
    		return person_name;
    	}
    
    	public void setPerson_name(String person_name) {
    		this.person_name = person_name;
    	}
    }
    
     
    public class Employee extends Person{
    	private double saray;
    	protected String gangwei;
    	
    	public Employee() {
    		super();
    	}
    
    
    	public Employee(double saray, String gangwei) {
    		super();
    		this.saray = saray;
    		this.gangwei = gangwei;
    	}
    	
    	public double getSaray() {
    		return saray;
    	}
    
    
    	public void setSaray(double saray) {
    		this.saray = saray;
    	}
    
    
    	public String getGangwei() {
    		return gangwei;
    	}
    
    
    	public void setGangwei(String gangwei) {
    		this.gangwei = gangwei;
    	}
    
    
    	public void addSaray(double money){
    		this.saray+=money;
    	}
    	
    }
    



     
    以下按照我们常用的方法介绍下使用方法:

    1.根据类名构造一个实例

    		// 根据类名获取Class对象
    		Class c = Class.forName("Employee");
    		System.out.println(c.getName()); // 此处打印:Employee
    		// 获取父类Class对象
    		Class cp = c.getSuperclass();
    		System.out.println(cp.getName());// 此处打印:Person
    		// 获取类的访问修饰符
    		String modifiers = Modifier.toString(c.getModifiers());
    		System.out.println(modifiers); // 此处打印:public
    		// 实例化
    		Object obj = c.newInstance(); //通过无参的构造函数进行实例化




     
     
    2.获取类的Field,主要有以下四个方法
     

    Class c = Class.forName("Employee");

    •  c.getField(name) ; 
    •  c.getFields() 
    •  c.getDeclaredFields()
    •  c.getDeclaredField(name)
    getField()方法返回这个类或其超类的公有字段(不包括private和protect修饰的字段)
    getDeclaredField方法返回这个类的全部字段(包括private和protect修饰的字段)
     
     
    <span style="white-space:pre">		</span>/*
    		 * 获取类Employee的所有Field
    		 * 
    		 * c.getField(name) c.getFields() c.getDeclaredFields()
    		 * c.getDeclaredField(name)
    		 */
    		Field[] fields = c.getDeclaredFields();
    		for (Field f : fields) {
    			// 获取该Field的类型
    			Class type = f.getType();
    			// 获取该Field的名称
    			String name = f.getName();
    			// 获取该Field的访问修饰符
    			String sFieldModifiers = Modifier.toString(f.getModifiers());
    			System.out.println(sFieldModifiers + " " + type.getName() + " " + name + ";");
    		}


    
    
    
    

     

    3.获取类的构造函数
    同Field一样,获取构造函数也有4个方法
    • * c.getDeclaredConstructors() 
    • * c.getConstructors()
    • * c.getDeclaredConstructor(parameterTypes)
    • * c.getDeclaredConstructor(parameterTypes)
     
    <span style="white-space:pre">		</span>/*
    		 * 获取类的构造函数 
    		 * c.getDeclaredConstructors() 
    		 * c.getConstructors()
    		 * c.getDeclaredConstructor(parameterTypes)
    		 * c.getDeclaredConstructor(parameterTypes)
    		 */
    		Constructor[] constructors = c.getDeclaredConstructors();
    		for (Constructor cr : constructors) {
    			// 构造函数名称
    			String name = cr.getName();
    			// 构造函数修饰符
    			String sConstructorModifiers = Modifier.toString(cr.getModifiers());
    			// 构造函数参数
    			Class[] paramTypes = cr.getParameterTypes();
    			String sParam = "";
    			for (int j = 0; j < paramTypes.length; j++) {
    				if (j > 0)
    					sParam += ", ";
    				sParam += paramTypes[j].getName();
    			}
    			System.out.println(sConstructorModifiers + " " + name + "(" + sParam + ");");
    		}


    4.获取类的Method
    同Field一样,有4个获取方法的方法,另外多了一个方法,用于获取返回类型
     
    <span style="white-space:pre">		Method[] methods = c.getDeclaredMethods();
    <span style="white-space:pre">		</span>for (Method m : methods) {
    <span style="white-space:pre">			</span>// 方法返回类型
    <span style="white-space:pre">			</span>Class returnType = m.getReturnType();
    <span style="white-space:pre">			</span>String sReturnType = returnType.toString();
    <span style="white-space:pre">			</span>// 方法名称
    <span style="white-space:pre">			</span>String name = m.getName();
    <span style="white-space:pre">			</span>// 方法修饰符
    <span style="white-space:pre">			</span>String sMethodModifiers = Modifier.toString(m.getModifiers());
    <span style="white-space:pre">			</span>// 方法参数
    <span style="white-space:pre">			</span>Class[] paramTypes = m.getParameterTypes();
    <span style="white-space:pre">			</span>String sParam = "";
    <span style="white-space:pre">			</span>for (int j = 0; j < paramTypes.length; j++) {
    <span style="white-space:pre">				</span>if (j > 0)
    <span style="white-space:pre">					</span>sParam += ", ";
    <span style="white-space:pre">				</span>sParam += paramTypes[j].getName();
    <span style="white-space:pre">			</span>}
    <span style="white-space:pre">			</span>System.out.println(sMethodModifiers + " " + sReturnType + " " + name + "(" + sParam + ");");
    <span style="white-space:pre">		</span>}</span>

    5.利用反射动态给对象属性赋值,比如我们需要从配置文件中读取某个员工的信息,并赋值给某个对象,我们可以这样写:
    <span style="white-space:pre">		</span>/*
    <span style="white-space:pre">		</span> * 动态给类的属性赋值
    <span style="white-space:pre">		</span> */
    <span style="white-space:pre">		</span>Class c2 = Class.forName("Employee");
    <span style="white-space:pre">		</span>Object e = c2.newInstance();
    <span style="white-space:pre">		</span>Field f = c2.getDeclaredField("saray");
    <span style="white-space:pre">		</span>// 因为属性saray是private的,所有需要调用setAccessible方法才能给该属性赋值,否则报错
    <span style="white-space:pre">		</span>f.setAccessible(true);
    <span style="white-space:pre">		</span>f.set(e, 10000);
    <span style="white-space:pre">		</span>Field f2 = c2.getDeclaredField("gangwei");
    <span style="white-space:pre">		</span>f2.set(e, "高级软件工程师");
    <span style="white-space:pre">		</span>System.out.println(((Employee) e).getGangwei() + " " + ((Employee) e).getSaray());
    <span style="white-space:pre">		</span>// 取值
    <span style="white-space:pre">		</span>Field f3 = c2.getDeclaredField("saray");
    <span style="white-space:pre">		</span>Field f4 = c2.getDeclaredField("gangwei");
    <span style="white-space:pre">		</span>f3.setAccessible(true);
    <span style="white-space:pre">		</span>System.out.println(f3.get(e));
    <span style="white-space:pre">		</span>System.out.println(f4.get(e));
    输出结果如下:
    高级软件工程师 10000.0
    10000.0
    高级软件工程师
     
    6.利用反射动态地调用对象的方法,比如Employee类中有个addsaray的方法,我们看下要怎么调用:
    		Class c3 = Class.forName("Employee");
    		Object e3 = c3.newInstance();
    		Field fSaray = c3.getDeclaredField("saray");
    		fSaray.setAccessible(true);
    		fSaray.set(e3, 10000);
    		System.out.println(fSaray.get(e3)); //输出10000
    		// 获取Method
    		Method m = c3.getDeclaredMethod("addSaray", double.class);
    		/*
    		 * Method m = c3.getDeclaredMethod("addSaray"); Method m2 =
    		 * c3.getDeclaredMethod("addSaray", double.class);
    		 * 如果有多个重名的方法,要添加参数让编译器知道应该调用哪个方法,这里只有一个参数,所以上面两种写法都可以
    		 */
    		// 调用方法
    		m.invoke(e3, 5000);
    		System.out.println(fSaray.get(e3)); //输出15000,因此证明方法调用成功
    输出结果如下:
    10000.0
    15000.0
  • 相关阅读:
    zech的神秘题库(武汉理工夜莺杯)
    回归第六题
    同余方程
    牛牛选路径(牛客)
    回归第三题
    区间dp复习提高专题
    乘法逆元(线性递推)
    回归第八题
    JAVA启动参数大全之二:非标准参数(转)
    (转)Spring Security 3.1 自定义实例之登陆
  • 原文地址:https://www.cnblogs.com/s502/p/5631634.html
Copyright © 2011-2022 走看看