标签:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
public class ClassDemo1 { public static void main(String[] args) { try { Entity foo1 = new Entity(); // 获得Class对象的两种方式: Class c1 = Entity.class; Class c2 = foo1.getClass(); Class c3 = Class.forName("com.thr.reflect.Entity"); // 不管c1还是c2,都代表了Entity的class的对象 System.out.println(c1 == c2); // c3也是Entity的class对象 System.out.println(c1 == c3); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } class Entity { }三种方式获取的Class对象是一致的。
通过Class对象我们还可以创建类:
Entity en = (Entity) c1.newInstance();
通过获取的这个对象就可以像用new创建出来的对象一样使用Entity内部的方法等。
首先创建一个接口:
public interface Singable { void sing(); }然后写两个实现类:
public class Bird implements Singable { @Override public void sing() { System.out.println("Bird sing..."); } }
public class Cat implements Singable { @Override public void sing() { System.out.println("Cat sing..."); } }
最后再主程序中动态加载类:
public class World { public static void main(String[] args) { try { Class c = Class.forName(args[0]); Singable singable = (Singable) c.newInstance(); singable.sing(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
运行时要传入类的全名参数。
首先来看基本数据类型的Class对象:
public class ClassDemo2 { public static void main(String[] args) { Class[] cs = new Class[] { int.class, String.class, double.class, Double.class, void.class, Class.class }; for (Class c : cs) { System.out.println(c.getName()); System.out.println(c.getSimpleName()); } } }我们编写一个获取类的方法的工具方法:
public static void printClassMethods(Object obj) { // 首先获取Class对象 Class c = obj.getClass(); // 获取类的名称 System.out.println("类的名称是:" + c.getName()); // 获取类的方法,一个Method的对象就是一个成员方法,通过getMethods()获取的是所有public的方法,包括从父类继承而来的 // getDeclaredMethods()获取的是所有该类自己生命的方法,不问访问权限 Method[] ms = c.getMethods(); for (Method m : ms) { // 获取返回值类型 Class returnType = m.getReturnType(); System.out.print(returnType.getName() + " "); // 获取方法名 System.out.print(m.getName() + "("); // 获取参数类型 Class[] paramTypes = m.getParameterTypes(); for (Class type : paramTypes) { System.out.print(type.getName() + ","); } System.out.println(")"); } }使用它:
public static void main(String[] args) { String s = new String(); ClassUtil.printClassMethods(s); Integer i = 1; ClassUtil.printClassMethods(i); }
获取成员变量信息:
public static void printClassFields(Object obj) { // 首先获取Class对象 Class c = obj.getClass(); // 使用getFields()获取的是所有public的成员变量信息,使用getDeclaredFields获取的是该类自己声明的成员变量信息,不问访问权限 Field[] fs = c.getDeclaredFields(); for (Field f : fs) { // 获取成员变量的类型 Class fieldType = f.getType(); String typeName = fieldType.getName(); // 获取成员变量的名字 String filedName = f.getName(); System.out.println(typeName + " " + filedName); } }获取构造方法信息:
public static void printClassConstructor(Object obj) { // 首先获取Class对象 Class c = obj.getClass(); Constructor[] cons = c.getDeclaredConstructors(); for (Constructor con : cons) { // 获取方法名 System.out.print(con.getName() + "("); // 获取参数类型 Class[] paramTypes = con.getParameterTypes(); for (Class type : paramTypes) { System.out.print(type.getName() + ","); } System.out.println(")"); } }
所有的方法对象都有一个invoke方法我们调用method.invoke(对象, 参数列表)就可以执行方法:
public class MethodDemo1 { public static void main(String[] args) { try { // 获取print(int, int)方法 A a = new A(); Class c = a.getClass(); Method m1 = c.getMethod("print", int.class, int.class); // 执行方法,使用o来接受返回值 // 如果有返回值,那么Object就是返回值的类型;没有返回值就返回null Object o1 = m1.invoke(a, 10, 10); // 获取print(String, String)方法 Method m2 = c.getMethod("print", new Class[] { String.class, String.class }); Object o2 = m2.invoke(a, "s1", "s2"); // 获取print()方法 Method m3 = c.getMethod("print"); Object o3 = m3.invoke(a); System.out.println(o1); System.out.println(o2); System.out.println(o3); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } class A { public void print() { System.out.println("hello"); } public int print(int a, int b) { System.out.println(a + b); return a + b; } public String print(String a, String b) { System.out.println(a.toUpperCase() + "," + b.toLowerCase()); return a + b; } }
public static void main(String[] args) { List list1 = new ArrayList(); List<String> list2 = new ArrayList<String>(); Class c1 = list1.getClass(); Class c2 = list2.getClass(); System.out.println(c1 == c2); // 反射的操作都是编译之后的操作 // c1==c2是true说明编译之后集合的泛型是去泛型化的 // Java中集合的泛型是防止错误输入的,只在编译阶段有效,绕过编译就无效了 // 我们可以通过方法的反射来绕过编译 Method m; try { m = c1.getMethod("add", Object.class); m.invoke(list1, 100); System.out.println(list1.size()); System.out.println(list1); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }通过这个例子可以看到通过Java的反射机制可以绕过编译,是在运行时刻执行的,自然就可以绕过集合的泛型。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/scarthr/article/details/47122111