反射
1,反编译:.class-->.java
2,通过反射机制访问java对象的属性,方法,构造方法等;
反射的概念:
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
1,反射机制获取类有三种方法,我们来获取Employee类型
//第一种方式: Classc1 = Class.forName("Employee"); //第二种方式: //java中每个类型都有class 属性. Classc2 = Employee.class; //第三种方式: //java语言中任何一个java对象都有getClass 方法 Employeee = new Employee(); Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
2,创建对象:获取类以后我们来创建它的对象,利用newInstance:
Class c =Class.forName("Employee"); //创建此Class 对象所表示的类的一个新实例 Objecto = c.newInstance(); //调用了Employee的无参数构造方法.
3,获取属性:分为所有的属性和指定的属性:
a,先看获取所有的属性的写法:
//获取整个类 Class c = Class.forName("java.lang.Integer"); //获取所有的属性? Field[] fs = c.getDeclaredFields(); //定义可变长的字符串,用来存储属性 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{ <span style="white-space:pre"> </span>//以前的方式: /* 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这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; /** * @author sky */ public class ReflectTester { public static void main(String args[]) throws Exception { ReflectTester ref = new ReflectTester(); ref.getConstructor(); } public void getConstructor() throws Exception { Class c = null; c = Class.forName("java.lang.Long"); Class cs[] = {java.lang.String.class}; System.out.println("\n-------------------------------\n"); Constructor cst1 = c.getConstructor(cs); System.out.println("1、通过参数获取指定Class对象的构造方法:"); System.out.println(cst1.toString()); Constructor cst2 = c.getDeclaredConstructor(cs); System.out.println("2、通过参数获取指定Class对象所表示的类或接口的构造方法:"); System.out.println(cst2.toString()); Constructor cst3 = c.getEnclosingConstructor(); System.out.println("3、获取本地或匿名类Constructor 对象,它表示基础类的立即封闭构造方法。"); if (cst3 != null) System.out.println(cst3.toString()); else System.out.println("-- 没有获取到任何构造方法!"); Constructor[] csts = c.getConstructors(); System.out.println("4、获取指定Class对象的所有构造方法:"); for (int i = 0; i < csts.length; i++) { System.out.println(csts[i].toString()); } System.out.println("\n-------------------------------\n"); Type types1[] = c.getGenericInterfaces(); System.out.println("1、返回直接实现的接口:"); for (int i = 0; i < types1.length; i++) { System.out.println(types1[i].toString()); } Type type1 = c.getGenericSuperclass(); System.out.println("2、返回直接超类:"); System.out.println(type1.toString()); Class[] cis = c.getClasses(); System.out.println("3、返回超类和所有实现的接口:"); for (int i = 0; i < cis.length; i++) { System.out.println(cis[i].toString()); } Class cs1[] = c.getInterfaces(); System.out.println("4、实现的接口"); for (int i = 0; i < cs1.length; i++) { System.out.println(cs1[i].toString()); } System.out.println("\n-------------------------------\n"); Field fs1[] = c.getFields(); System.out.println("1、类或接口的所有可访问公共字段:"); for (int i = 0; i < fs1.length; i++) { System.out.println(fs1[i].toString()); } Field f1 = c.getField("MIN_VALUE"); System.out.println("2、类或接口的指定已声明指定公共成员字段:"); System.out.println(f1.toString()); Field fs2[] = c.getDeclaredFields(); System.out.println("3、类或接口所声明的所有字段:"); for (int i = 0; i < fs2.length; i++) { System.out.println(fs2[i].toString()); } Field f2 = c.getDeclaredField("serialVersionUID"); System.out.println("4、类或接口的指定已声明指定字段:"); System.out.println(f2.toString()); System.out.println("\n-------------------------------\n"); Method m1[] = c.getMethods(); System.out.println("1、返回类所有的公共成员方法:"); for (int i = 0; i < m1.length; i++) { System.out.println(m1[i].toString()); } Method m2 = c.getMethod("longValue", new Class[]{}); System.out.println("2、返回指定公共成员方法:"); System.out.println(m2.toString()); } }
public class ReflectTester { public Object copy(Object object) throws Exception { // 获得对象的类型 Class<?> classType = object.getClass(); System.out.println("Class:" + classType.getName()); // 通过默认构造方法创建一个新的对象 Object objectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{}); // 获得对象的所有属性 Field fields[] = classType.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; String fieldName = field.getName(); String firstLetter = fieldName.substring(0, 1).toUpperCase(); // 获得和属性对应的getXXX()方法的名字 String getMethodName = "get" + firstLetter + fieldName.substring(1); // 获得和属性对应的setXXX()方法的名字 String setMethodName = "set" + firstLetter + fieldName.substring(1); // 获得和属性对应的getXXX()方法 Method getMethod = classType.getMethod(getMethodName, new Class[]{}); // 获得和属性对应的setXXX()方法 Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()}); // 调用原对象的getXXX()方法 Object value = getMethod.invoke(object, new Object[]{}); System.out.println(fieldName + ":" + value); // 调用拷贝对象的setXXX()方法 setMethod.invoke(objectCopy, new Object[]{value}); } return objectCopy; } public static void main(String[] args) throws Exception { Customer customer = new Customer("Tom", 21); customer.setId(new Long(1)); Customer customerCopy = (Customer) new ReflectTester().copy(customer); System.out.println("Copy information:" + customerCopy.getId() + " " + customerCopy.getName() + " " + customerCopy.getAge()); } } class Customer { private Long id; private String name; private int age; public Customer() { } public Customer(String name, int age) { this.name = name; this.age = age; } //get、set 略 }
import java.lang.reflect.Method; /** * @author sky */ public class InvokeTester { public int add(int param1, int param2) { return param1 + param2; } public String echo(String msg) { return "echo: " + msg; } public static void main(String[] args) throws Exception { Class<?> classType = InvokeTester.class; Object invokeTester = classType.newInstance(); // Object invokeTester = classType.getConstructor(new // Class[]{}).newInstance(new Object[]{}); //获取InvokeTester类的add()方法 Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class}); //调用invokeTester对象上的add()方法 Object result = addMethod.invoke(invokeTester, new Object[]{new Integer(100), new Integer(200)}); System.out.println((Integer) result); //获取InvokeTester类的echo()方法 Method echoMethod = classType.getMethod("echo", new Class[]{String.class}); //调用invokeTester对象的echo()方法 result = echoMethod.invoke(invokeTester, new Object[]{"Hello"}); System.out.println((String) result); } }
import java.lang.reflect.Array; /** * @author sky */ public class ArrayTest { public static void main(String args[]) { int[] dims = new int[]{5, 10, 15}; //创建一个具有指定的组件类型和维度的新数组。 Object array = Array.newInstance(Integer.TYPE, dims); Object arrayObj = Array.get(array, 3); Class<?> cls = arrayObj.getClass().getComponentType(); System.out.println(cls); arrayObj = Array.get(arrayObj, 5); Array.setInt(arrayObj, 10, 37); int arrayCast[][][] = (int[][][]) array; System.out.println(arrayCast[3][5][10]); } }
import java.lang.reflect.Field; /** * @author sky */ public class RefFiled { public double x; public Double y; public static void main(String args[]) throws NoSuchFieldException, IllegalAccessException { Class c = RefFiled.class; Field xf = c.getField("x"); Field yf = c.getField("y"); RefFiled obj = new RefFiled(); System.out.println("变更前x=" + xf.get(obj)); //变更成员x值 xf.set(obj, 1.1); System.out.println("变更后x=" + xf.get(obj)); System.out.println("变更前y=" + yf.get(obj)); //变更成员y值 yf.set(obj, 2.1); System.out.println("变更后y=" + yf.get(obj)); } }