Java反射介绍
发布时间:2021-11-12 18:08:59 所属栏目:教程 来源:互联网
导读:反射是指程序在运行时能够获取自身的信息. Java的反射机制将类和方法封装为对象, 允许程序动态的创建对象或调用方法. 获得Class对象 java.lang.Class是反射机制的核心封装类, 通常有三种方法可以获得类的Class对象. 为了便于说明创建一个Item类: class Item
反射是指程序在运行时能够获取自身的信息. Java的反射机制将类和方法封装为对象, 允许程序动态的创建对象或调用方法. 获得Class对象 java.lang.Class是反射机制的核心封装类, 通常有三种方法可以获得类的Class对象. 为了便于说明创建一个Item类: class Item { publicstaticvoidmain(String[] args) { Item item = new Item(); } } Class.forName("Item"): 根据目标类的名称获得Class对象的静态方法. Item.class: 通过静态属性获得Class对象 item.getClass(): 通过实例方法获得Class对象 通过Class对象可以访问类的元信息: String getName(): 获得包含包名在内的完整类名 String getSimpleName(): 获得不含包名的简单类名 Package getPackage(): 获得包的封装对象 Class getSuperclass(): 获得父类的Class对象 Class[] getInterfaces(): 获得所有实现接口的Class对象 获得构造器 通过Class对象调用默认构造器进行实例化: public class Main { publicstaticvoidmain(String[] args) throws InstantiationException, IllegalAccessException { Class clazz = MyClass.class; MyClass obj = (MyClass) clazz.newInstance(); System.out.println(obj.i); } } 不过这样只能调用默认构造器, 若要使用其它构造器实例化则需要先获得构造器对象: Constructor clazz.getConstructor(Class[]): 根据参数获得public构造器对象. Constructor clazz.getDeclaredConstructor(Class[]): 根据参数获得构造器对象, 包括public, default, protected, private. 也可以通过Class对象获得构造器的列表: Constructor[] clazz.getConstructors(): 获得所有public构造器对象. Constructor[] clazz.getDeclaredConstructors(): 获得所有构造器对象, 包括public, default, protected, private. Constructor.newInstance()方法可以用于实例化类. 示例: Constructor constructor = MyClass.class.getConstructor(String.class); MyClass obj = (MyClass)constructor.newInstance("abc"); 获得方法 可以同通过Class对象获得Method对象访问类的方法: public class Item { publicvoidtest(String string) { System.out.println(string); } publicstaticvoidmain(String[] args) throws Exception { Item item = new Item(); Method method = Item.class.getMethod("test", String.class); method.invoke(item, "Hello World"); } } getMethod()第一个参数为方法的名称, 后面的可变参数表示目标方法的参数表. 两者共同标记类中的一个方法. invoke()方法第一个参数为调用方法的实例, 后面为方法的实参表. 访问无参数的方法也很简单: public class Item { publicvoidtest() { System.out.println("Hello World"); } publicstaticvoidmain(String[] args) throws Exception { Item item = new Item(); Method method = Item.class.getMethod("test", null); method.invoke(item); } } 有两个方法用于获得方法: Method getMethod(name, clazz...): 根据名称和参数表获得public方法, 包括继承自父类的方法. Method getDeclaredMethod(name, clazz...): 根据名称和参数表获得方法, 包括继承自父类的方法. 包括public, default, protected, private. 类似地, 有两个方法用于获得方法列表: Method[] getMethods(): 获得所有public方法 Method[] getDeclaredMethods(): 获得所有方法 int Method.getModifiers()用于获得public, static等修饰符. 修饰符由标志位(BitSet)标示, 被转换成int返回. 可以使用java.lang.reflect.Modifier检查标志符类型: Modifier.isAbstract(int modifiers); Modifier.isFinal(int modifiers); Modifier.isInterface(int modifiers); Modifier.isNative(int modifiers); Modifier.isPrivate(int modifiers); Modifier.isProtected(int modifiers); Modifier.isPublic(int modifiers); Modifier.isStatic(int modifiers); Modifier.isStrict(int modifiers); Modifier.isSynchronized(int modifiers); Modifier.isTransient(int modifiers); Modifier.isVolatile(int modifiers); 直接调用私有方法Method对象的invoke方法时会抛��IllegalAccessException异常, 需要先调用method.setAccessible(true): class Item { privatevoidtest(String string) { System.out.println(string); } } public class Main { publicstaticvoidmain(String[] args) throws Exception { Item item = new Item(); Method method = Item.class.getDeclaredMethod("test", String.class); method.setAccessible(true); // 未加此行会抛出IllegalAccessException method.invoke(item, "Hello World"); } } 获得域 访问域与访问方法非常类似: Field getField(name): 根据名称获得域, 包括继承自父类的方法. Field getDeclaredField(name): 根据名称获得域, 包括继承自父类的域. 包括public, default, protected, private. Field[] getFields(): 获得所有public域 Field[] getDeclaredFields(): 获得所有域 访问私有域同样需要setAccessible(true). Field对象可以访问或修改域: class Item { private String msg; } public class Main { publicstaticvoidmain(String[] args) throws Exception { Item item = new Item(); Field field = Item.class.getDeclaredField("msg"); field.setAccessible(true); field.set(item, "Hello World"); System.out.println((String)field.get(item)); } } 反射与泛型 Java的反射机制允许在运行时获得泛型参数, 需要获得泛型参数的场景有: 获得泛型域的类型, 以进行访问或设置 获得泛型方法(构造器)的参数类型, 以进行调用 获得泛型方法的返回值类型 java.lang.reflect.Type接口用于描述泛型参数, Type接口的唯一实现是Class类. 获得域的类型: public class Item { public List<String> list; publicstaticvoidmain(String[] args) throws Exception { Field field = Item.class.getField("list"); Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) type; Type[] typeArgs = paramType.getActualTypeArguments(); for(Type typeArg : typeArgs){ Class typeArgClass = (Class) typeArg; System.out.println(typeArgClass); } } } } 获得泛型方法参数类型: public class Item { public List<String> list; public List<String> getList() { return list; } publicstaticvoidmain(String[] args) throws Exception { Method method = Item.class.getMethod("getList", null); Type type = method.getGenericReturnType(); if (type instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) type; Type[] typeArgs = paramType.getActualTypeArguments(); for(Type typeArg : typeArgs){ Class typeArgClass = (Class) typeArg; System.out.println(typeArgClass); } } } } 获得泛型方法的返回值类型: public class Item { public List<String> list; public List<String> getList() { return list; } publicstaticvoidmain(String[] args) throws Exception { Method method = Item.class.getMethod("getList", null); Type type = method.getGenericReturnType(); if (type instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) type; Type[] typeArgs = paramType.getActualTypeArguments(); for(Type typeArg : typeArgs){ Class typeArgClass = (Class) typeArg; System.out.println(typeArgClass); } } } } ![]() (编辑:我爱制作网_潮州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |