java反射基本理论和实例

1、先看一下反射的概念:java

              主要是指程序能够访问,检测和修改它自己状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。数据库

             反射是java中一种强大的工具,可以使咱们很方便的建立灵活的代码,这些代码能够再运行时装配,无需在组件之间进行源代码连接。可是反射使用不当会成本很高!数组

2、反射机制的做用:安全

              1,反编译:.class-->.javaapp

              2,经过反射机制访问java对象的属性,方法,构造方法等;工具

3、在这里先看一下sun为咱们提供了那些反射机制中的类:性能

               java.lang.Class;                学习

              java.lang.reflect.Constructor; java.lang.reflect.Field;        this

              java.lang.reflect.Method;spa

              java.lang.reflect.Modifier;

4、具体功能实现:

                一、反射机制获取类有三种方法,咱们来获取Employee类型

//第一种方式:  
Classc1 = Class.forName("Employee");  

//第二种方式:  
//java中每一个类型都有class 属性.  
Classc2 = Employee.class;  
   
//第三种方式:  
//java语言中任何一个java对象都有getClass 方法  
Employeee = new Employee();  
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)


    二、建立对象:获取类之后咱们来建立它的对象,利用newInstance:     

Class c =Class.forName("Employee");  
//建立此Class 对象所表示的类的一个新实例  
Objecto = c.newInstance(); //调用了Employee的无参数构造方法.

    3,获取属性:分为全部的属性和指定的属性:

          a,先看获取全部的属性的写法:

            

//获取整个类  
Class c = Class.forName("java.lang.Integer");  
//获取全部的属性?  
//定义可变长的字符串,用来存储属性  
StringBuffer sb = new StringBuffer();  
//经过追加的方法,将每一个属性拼接到此字符串中  
//最外边的public定义  
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");  
//里边的每个属性  
for(Field field:fs){  
      sb.append("\t");//空格  
      sb.append(Modifier.toString(field.getModifiers())+" ");//得到属性的修饰符,例如public,static等等
      sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字  
      sb.append(field.getName()+";\n");//属性的名字+回车  
}  
sb.append("}");       
System.out.println(sb);

       b,获取特定的属性,对比着传统的方法来学习:

public static void main(String[] args) throws Exception{  
    /* 
    User u = new User(); 
    u.age = 12; //set 
    System.out.println(u.age); //get 
    */  
              
    //获取类  
    Class c = Class.forName("User");  
    //获取id属性  
    Field idF = c.getDeclaredField("id");  
    //实例化这个类赋给o  
    Object o = c.newInstance();  
    //打破封装  
    idF.setAccessible(true); //使用反射机制能够打破封装性,致使了java对象的属性不安全。  
    //给o对象的id属性赋值"110"  
    idF.set(o, "110"); //set  
    //get  
    System.out.println(idF.get(o));  
}

  4,获取方法,和构造方法,再也不详细描述,只来看一下关键字:

getDeclaredMethods() 获取全部的方法
getReturnType() 得到方法的返回类型
getParameterTypes() 得到方法的传入参数类型
getDeclaredMethod("方法名",参数类型.class,……) 得到特定的方法
getDeclaredConstructors() 获取全部的构造方法
getDeclaredConstructor(参数类型.class,……) 获取特定的构造方法
getSuperclass() 获取某类的父类
getInterfaces() 获取某类实现的接口




 这样咱们就能够得到类的各类内容,进行了反编译。对于JAVA这种先编译再运行的语言来讲,反射机制可使代码更加灵活,更加容易实现面向对象。

五,反射加配置文件,使咱们的程序更加灵活:

assembly.load("当前程序集的名称").CreateInstance("当前命名空间名称".要实例化的类名);

这样的好处是很容易的方便咱们变换数据库,例如咱们将系统的数据库从SQL Server升级到Oracle,那么咱们写两份D层,在配置文件的内容改一下,或者加条件选择一下便可,带来了很大的方便。           

         固然了,JAVA中其实也是同样,只不过这里的配置文件为.properties,称做属性文件。经过反射读取里边的内容。这样代码是固定的,可是配置文件的内容咱们能够改,这样使咱们的代码灵活了不少!

    综上为,JAVA反射的再次学习,灵活的运用它,可以使咱们的代码更加灵活,可是它也有它的缺点,就是运用它会使咱们的软件的性能下降,复杂度增长,因此还要咱们慎重的使用它。

下面是引用的一篇文章:

Java反射在咱们Java学习的过程当中是很是重要的知识点。可能有些同窗认为这个学习起来不容易理解,其实就我我的而言仍是比较简单,学习起来也比较容易理解。下面我给你们总结一下Java反射学习的要点,同时给出几个比较好的例子。
  一、Java反射的概念
  反射含义:能够获取正在运行的Java对象。
  二、Java反射的功能
  1)能够判断运行时对象所属的类
  2)能够判断运行时对象所具备的成员变量和方法
  3)经过反射甚至能够调用到private的方法
  4)生成动态代理
  三、实现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
  示例:此程序例子告诉你们如何操做Class/Field/Constructor/Method等与Java反射相关的类

package com.reflection;

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;

public class TestReflection {
	private String username;
	private String password;
	private int[] age;

	public TestReflection(String username, String password, int[] age) {
		super();
		this.username = username;
		this.password = password;
		this.age = age;
	}

	public TestReflection() {
		username = "李白";
		password = "123";
		age = new int[]{10,11,12};
	}


	public void setUserName(String username) {
		this.username = username;
	}

	private void setPassWord(String password) {
		this.password = password;
	}
	
	

	public static void test01() throws ClassNotFoundException {
		//使用三种方法均可以经过反射来获取类对象Class
		Class c1 = TestReflection.class;
		Class c2 = Class.forName("com.reflection.TestReflection");
		Class c3 = new TestReflection().getClass();
		// 获取指定的包名
		String package01 = c1.getPackage().getName();
		String package02 = c2.getPackage().getName();
		String package03 = c3.getPackage().getName();
		System.out.println("package01 = " + package01);
		System.out.println("package02 = " + package02);
		System.out.println("package03 = " + package03);
		// 获取类的修饰符
		int mod = c1.getModifiers();
		String modifier = Modifier.toString(mod);
		System.out.println("modifier = " + modifier);
		// 获取指定类的彻底限定名
		String className = c1.getName();
		System.out.println("className = " + className);
		// 获取指定类的父类
		Class superClazz = c1.getSuperclass();
		String superClazzName = superClazz.getName();
		System.out.println("superClazzName = " + superClazzName);
		// 获取实现的接口
		Class[] interfaces = c1.getInterfaces();
		for (Class t : interfaces) {
		    System.out.println("interfacesName = " + t.getName());
		}
		// 获取指定类的成员变量
		Field[] fields = c1.getDeclaredFields();
		for (Field field : fields) {
		    modifier = Modifier.toString(field.getModifiers()); // 获取每一个字段的访问修饰符
		    Class type = field.getType(); // 获取字段的数据类型所对应的Class对象
		    String name = field.getName(); // 获取字段名
		    if (type.isArray()) { // 若是是数组类型则须要特别处理		       
		        Class tt = type.getComponentType(); //getComponentType()方法返回一个Class对象,表示数组的成员类型。若是该类不表示数组类,方法返回null.而后经过getName方法获取数组元素类型
			String arrType = type.getComponentType().getName() + "[]";//arrType 为 int[]
		        System.out.println("" + modifier + " " + arrType + " " + name + ";");
		    } else {
			System.out.println("" + modifier + " " + type + " " + name + ";");
			}
		}
		// 获取类的构造方法
		Constructor[] constructors = c1.getDeclaredConstructors();
		for (Constructor constructor : constructors) {
		    String name = constructor.getName(); // 构造方法名
		    modifier = Modifier.toString(constructor.getModifiers()); // 获取访问修饰符
		    System.out.println("" + modifier + " " + name + "(");
		    Class[] paramTypes = constructor.getParameterTypes(); // 获取构造方法中的参数
		    for (int i = 0; i < paramTypes.length; i++) {
			if (i > 0) {
			    System.out.print(",");
			}
			if (paramTypes[i].isArray()) {
			    System.out.println(paramTypes[i].getComponentType().getName() + "[]");
			} else {
			    System.out.print(paramTypes[i].getName());
			}
		    }
		    System.out.println(");");
		}
		// 获取成员方法
		Method[] methods = c1.getDeclaredMethods();
		for (Method method : methods) {
		modifier = Modifier.toString(method.getModifiers());
		Class returnType = method.getReturnType(); // 获取方法的返回类型
		if (returnType.isArray()) {
		    String arrType = returnType.getComponentType().getName() + "[]";
		    System.out.print("" + modifier + " " + arrType + " " + method.getName() + "(");
		} else {
		    System.out.print("" + modifier + " " + returnType.getName() + " " + method.getName() + "(");
		}
			Class[] paramTypes = method.getParameterTypes();
			for (int i = 0; i < paramTypes.length; i++) {
				if (i > 0) {
					System.out.print(",");
				}
				if (paramTypes[i].isArray()) {
					System.out.println(paramTypes[i].getComponentType()
							.getName() + "[]");
				} else {
					System.out.print(paramTypes[i].getName());
				}
			}
			System.out.println(");");
		}
	}

	public static void test02() throws InstantiationException,
			IllegalAccessException, SecurityException, NoSuchMethodException,
			IllegalArgumentException, InvocationTargetException {
		// 反射调用方法,能够经过Method类的invoke方法实现动态方法的调用
		// public Object invoke(Object obj, Object... args)
		//该方法中有多个参数:method.invoke(o, new Object[] {参数1,参数2...});
		// 第一个参数表明对象
		// 第二个参数表明执行方法上的参数
		// 若反射要调用类的某个私有方法,能够在这个私有方法对应的Mehtod对象上先调用setAccessible(true)
		Class c1 = TestReflection.class;
		TestReflection t1 = (TestReflection) c1.newInstance(); // 利用反射调用无参的构造方法来建立类的对象
		System.out.println("username == " + t1.username);
		System.out.println("password == " + t1.password);
		//得到名称setUserName的方法public void com.reflection.TestReflection.setUserName(java.lang.String),参数为String类型
		Method method = c1.getDeclaredMethod("setUserName", String.class);
		method.invoke(t1, "Java反射的学习");//传入参数为字符串("Java反射的学习"),来调用类中的setUserName方法,此时已经改变实例t1的username的属性值
		System.out.println("username == " + t1.username);
		//调用私有方法private void com.reflection.TestReflection.setPassWord(java.lang.String),参数为String类型
		method = c1.getDeclaredMethod("setPassWord", String.class);
		//设置对私有方法的可操做权限
		method.setAccessible(true);
		method.invoke(t1, "反射执行某个Private修饰的方法");
		System.out.println("password == " + t1.password);
	}

	public static void main(String[] args) throws ClassNotFoundException,
		SecurityException, IllegalArgumentException,
		InstantiationException, IllegalAccessException,
		NoSuchMethodException, InvocationTargetException {
//		test01();
		test02();
	}
}

class  Sum{
     public   static   void  main(String[] args)  {
	      int vec[] = new int[]{1, 5, 3};  // 第一种方法          
	      int vec1[]  = {37,47,23} ;   // 第二种方法  
	      int vec2[] = new int [3];//指定数组的元素个数
	      for(int i=0;i<3;i++){
	    	  vec[i]=i+1;           //第三种方法
	      }
	  }  
}

再给与个实例:

package org.cqut.java.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class CopyObject {

	public Object copyObject(Object object) throws Exception {

		// 1.获取待操做类的一个Class对象
		Class<?> classType = object.getClass();

		// 2.获取待操做类的一个实例
		Constructor<?> constructor = classType
				.getConstructor(new Class<?>[] {});
		Object copyObj = constructor.newInstance(new Object[] {});

		// 3.获取被拷贝类的成员变量
		Field[] fields = classType.getDeclaredFields();

		for (Field field : fields) {
			// 4.遍历数组获取各个成员变量名字
			String name = field.getName();// 获取成员变量名字;

			// 5.操做字符串获取成员变量的set和get方法名字;
			String firstLetter = name.substring(0, 1).toUpperCase();
			String getMethodName = "get" + firstLetter + name.substring(1);
			String setMethodName = "set" + firstLetter + name.substring(1);

			Method getMethod = classType.getMethod(getMethodName,
					new Class<?>[] {});
			Method seMethod = classType.getMethod(setMethodName,
					new Class<?>[] { field.getType() });
			
			/*最开始认为如下两个invoke方法的第一和参数都应该调用copyObj,
			 * 可是最终的结果为输出为默认的空值。
			 * copyObj:程序前面经过Constructor类的newInstance方法
			 * 获取待操做类的一个实例;
			//Object value = getMethod.invoke(copyObj, new Object[] {});
			//seMethod.invoke(copyObj, new Object[] { value });

			/*如今改用以下方式了,输出就正常了
			 * 因此产生疑惑:为何第一个方法调用的object对象而不是copyObj呢?
			 * 
			 */
			Object value = getMethod.invoke(object, new Object[] {});
			seMethod.invoke(copyObj, new Object[] { value });
		}

		return copyObj;
	}

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

		Student student = new Student("Tom", 21);
		student.setId(111030805);
		CopyObject copy = new CopyObject();
		Student student2 = (Student) copy.copyObject(student);
		System.out.println(student2.getId() + " " + student2.getName() + " "
				+ student2.getAge());
	}
}

// 一个被反射的JavaBean
class Student {

	private long id;
	private String name;
	private int age;

	public Student() {

	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

}

    对于利用object给copyObj赋值的invoke的解惑:

Object value = getMethod.invoke(object, new Object[] {});
seMethod.invoke(copyObj, new Object[] { value });

这两句代码的做用以下,

第一句,获取object中的值。
第二句,将该值设置到copyObj中。

这样才能完成赋值。
若是按你所说
//Object value = getMethod.invoke(copyObj, new Object[] {});
            //seMethod.invoke(copyObj, new Object[] { value });

那就是讲从copyObj获取的值,赋值给copyObj,这样作根本毫无心义。


 for (Field field : fields) {
            String name = field.getName();
 
            field.setAccessible(true);
            Object value =  field.get(object);
            field.set(copyObj, value);
}
for循环里这样写,就成功的将object中的值赋值到了copyObj中。
相关文章
相关标签/搜索