java中反射(Reflect)的常见应用场景
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中反射(Reflect)的常见应用场景相关的知识,希望对你有一定的参考价值。
简介:
总结于imooc课程: http://www.imooc.com/learn/199
本文通过几个简单的例子,介绍Class类的使用,方法和成员变量的反射,以及通过反射了解集合泛型的本质等知识。
1.Class类的使用
/** * 使用java.lang.Class类动态加载一个类,编译时不对类是否存在以及对错进行检查,运行时检查 */ public class OfficeBetter { public static void main(String[] args) { args = new String[1]; Scanner input = new Scanner(System.in); args[0] = input.next(); try { Class<?> c = Class.forName("动态加载."+args[0]); IOfficeStart officeStart = (IOfficeStart)c.newInstance(); officeStart.start(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } finally{ input.close(); } } } //office功能接口 public interface IOfficeStart { void start(); } //实现1 public class Word implements IOfficeStart{ @Override public void start() { System.out.println("Word...start..."); } } //实现2 public class Excel implements IOfficeStart{ @Override public void start() { System.out.println("Excel...start..."); } }
2.通过对象或类名获取类的信息
/** * 通过类对象来获取该类的所有方法、构造函数、变量 */ public class ClassUtil { public static void main(String[] args) { Class c1 = int.class; Class c2 = void.class; System.out.println(c1.getName()); System.out.println(c2.getName()); ClassUtil.printClassMethods(new Double(1.0d)); ClassUtil.printClassFields(new Integer(1)); ClassUtil.printClassConstructors(new String()); } /** * 打印obj对象所在类的所有方法 * @param obj */ public static void printClassMethods(Object obj){ //首先获取类的类类型 Class c = obj.getClass(); System.out.println(c.getName() + "类所有的方法:"); //getMethods返回所有public方法,包括继承的方法 //getDeclaredMethods()返回所有的方法,不包括继承的方法 Method []ms = c.getMethods(); //遍历集合打印每个方法,包括方法返回值,方法名,方法参数 for (int i = 0; i < ms.length; i++) { Method m = ms[i]; //返回类型 System.out.print(m.getReturnType().getSimpleName() + " "); //方法名 System.out.print(m.getName() + " ("); //参数集合 Class []args = m.getParameterTypes(); for (Class class1 : args) { System.out.print(class1.getSimpleName() +","); } System.out.println(")"); } System.out.println("\n\n"); } /** * 打印obj对象所在类的所有构造函数 */ public static void printClassConstructors(Object obj){ Class c = obj.getClass(); System.out.println(c.getName() + "类的所有构造函数:"); Constructor []cs = c.getDeclaredConstructors(); for (int i = 0; i < cs.length; i++) { System.out.print(cs[i].getName() + " ("); Class []paras = cs[i].getParameterTypes(); for (Class class1 : paras) { System.out.print(class1.getName() + ","); } System.out.println(")"); } System.out.println("\n\n"); } /** * 打印obj对象所在类的所有变量 */ public static void printClassFields(Object obj){ Class c = obj.getClass(); System.out.println(c.getName() + "类的所有成员变量:"); Field[] fields = c.getFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; System.out.println(field.getType().getName() + " " + field.getName()); } System.out.println("\n\n"); } }
3.通过对象获取到所在类的某个方法后,通过反射的方式调用该方法
import java.lang.reflect.Method; public class Main { public static void main(String[] args){ A a = new A(); //下面通过对象a来反射调用方法 Class<? extends A> c = a.getClass(); try { //Method m1 = c.getMethod("print1", new Class[]{String.class,String.class}); Method m1 = c.getMethod("print1", String.class,String.class); //Method m2 = c.getMethod("print2",new Class[]{}); Method m2 = c.getDeclaredMethod("print2"); m1.invoke(a,"HELLO","world"); m2.invoke(a); } catch (Exception e) { e.printStackTrace(); } } } class A{ public void print1(String a,String b){ System.out.println(a.toLowerCase() +" "+ b.toUpperCase()); } public void print2(){ System.out.println("hello world"); } }
4.通过反射理解泛型(不能算是应用场景)
import java.lang.reflect.Method; import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList list1 = new ArrayList(); ArrayList<String> list2 = new ArrayList<String>(); list2.add("hello");//ok //list2.add(1111);//false System.out.println(list1.getClass() == list2.getClass());//输出true //因为带泛型和不带泛型通过反射得到类类型都发现是==的 //所以推测泛型的实质是在编译之前起到提醒的作用,在编译之后是没有泛型的 //通过反射验证 try { Method m = list1.getClass().getMethod("add", Object.class); m.invoke(list2, 1111); System.out.println(list2);//测试是否add进去1111 // for (String string : list2) { // System.out.print(string); // }此时不能这么遍历 for (Object obj : list2) { System.out.print(obj + " "); }//发现可以add } catch (Exception e) { // TODO: handle exception } } }
以上是关于java中反射(Reflect)的常见应用场景的主要内容,如果未能解决你的问题,请参考以下文章