Java反射机制详解


1反射机制是什么

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

2反射机制能做什么

反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;
  • 生成动态代理。

3反射机制的相关API

通过一个对象获得完整的包名和类名

Java | 复制

package` `net.xsoftlab.baike;``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``TestReflect testReflect = ``new` `TestReflect();``    ``System.out.println(testReflect.getClass().getName());``    ``// 结果 net.xsoftlab.baike.TestReflect``  ``}``}

实例化Class类对象

Java | 复制

package` `net.xsoftlab.baike;``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``Class<?> class1 = ``null``;``    ``Class<?> class2 = ``null``;``    ``Class<?> class3 = ``null``;``    ``// 一般采用这种形式``    ``class1 = Class.forName(``"net.xsoftlab.baike.TestReflect"``);``    ``class2 = ``new` `TestReflect().getClass();``    ``class3 = TestReflect.``class``;``    ``System.out.println(``"类名称  "` `+ class1.getName());``    ``System.out.println(``"类名称  "` `+ class2.getName());``    ``System.out.println(``"类名称  "` `+ class3.getName());``  ``}``}

获取一个对象的父类与实现的接口

Java | 复制

package` `net.xsoftlab.baike;``import` `java.io.Serializable;``public` `class` `TestReflect ``implements` `Serializable {``  ``private` `static` `final` `long` `serialVersionUID = -2862585049955236662L;``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``Class<?> clazz = Class.forName(``"net.xsoftlab.baike.TestReflect"``);``    ``// 取得父类``    ``Class<?> parentClass = clazz.getSuperclass();``    ``System.out.println(``"clazz的父类为:"` `+ parentClass.getName());``    ``// clazz的父类为: java.lang.Object``    ``// 获取所有的接口``    ``Class<?> intes[] = clazz.getInterfaces();``    ``System.out.println(``"clazz实现的接口有:"``);``    ``for` `(``int` `i = ``0``; i < intes.length; i++) {``      ``System.out.println((i + ``1``) + ``":"` `+ intes[i].getName());``    ``}``    ``// clazz实现的接口有:``    ``// 1:java.io.Serializable``  ``}``}

获取某个类中的全部构造函数 - 详见下例

通过反射机制实例化一个类的对象

Java | 复制

package` `net.xsoftlab.baike;``import` `java.lang.reflect.Constructor;``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``Class<?> class1 = ``null``;``    ``class1 = Class.forName(``"net.xsoftlab.baike.User"``);``    ``// 第一种方法,实例化默认构造方法,调用set赋值``    ``User user = (User) class1.newInstance();``    ``user.setAge(``20``);``    ``user.setName(``"Rollen"``);``    ``System.out.println(user);``    ``// 结果 User [age=20, name=Rollen]``    ``// 第二种方法 取得全部的构造函数 使用构造函数赋值``    ``Constructor<?> cons[] = class1.getConstructors();``    ``// 查看每个构造方法需要的参数``    ``for` `(``int` `i = ``0``; i < cons.length; i++) {``      ``Class<?> clazzs[] = cons[i].getParameterTypes();``      ``System.out.print(``"cons["` `+ i + ``"] ("``);``      ``for` `(``int` `j = ``0``; j < clazzs.length; j++) {``        ``if` `(j == clazzs.length - ``1``)``          ``System.out.print(clazzs[j].getName());``        ``else``          ``System.out.print(clazzs[j].getName() + ``","``);``      ``}``      ``System.out.println(``")"``);``    ``}``    ``// 结果``    ``// cons[0] (java.lang.String)``    ``// cons[1] (int,java.lang.String)``    ``// cons[2] ()``    ``user = (User) cons[``0``].newInstance(``"Rollen"``);``    ``System.out.println(user);``    ``// 结果 User [age=0, name=Rollen]``    ``user = (User) cons[``1``].newInstance(``20``, ``"Rollen"``);``    ``System.out.println(user);``    ``// 结果 User [age=20, name=Rollen]``  ``}``}``class` `User {``  ``private` `int` `age;``  ``private` `String name;``  ``public` `User() {``    ``super``();``  ``}``  ``public` `User(String name) {``    ``super``();``    ``this``.name = name;``  ``}``  ``public` `User(``int` `age, String name) {``    ``super``();``    ``this``.age = age;``    ``this``.name = name;``  ``}``  ``public` `int` `getAge() {``    ``return` `age;``  ``}``  ``public` `void` `setAge(``int` `age) {``    ``this``.age = age;``  ``}``  ``public` `String getName() {``    ``return` `name;``  ``}``  ``public` `void` `setName(String name) {``    ``this``.name = name;``  ``}``  ``@Override``  ``public` `String toString() {``    ``return` `"User [age="` `+ age + ``", name="` `+ name + ``"]"``;``  ``}``}

获取某个类的全部属性

Java | 复制

package` `net.xsoftlab.baike;``import` `java.io.Serializable;``import` `java.lang.reflect.Field;``import` `java.lang.reflect.Modifier;``public` `class` `TestReflect ``implements` `Serializable {``  ``private` `static` `final` `long` `serialVersionUID = -2862585049955236662L;``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``Class<?> clazz = Class.forName(``"net.xsoftlab.baike.TestReflect"``);``    ``System.out.println(``"===============本类属性==============="``);``    ``// 取得本类的全部属性``    ``Field[] field = clazz.getDeclaredFields();``    ``for` `(``int` `i = ``0``; i < field.length; i++) {``      ``// 权限修饰符``      ``int` `mo = field[i].getModifiers();``      ``String priv = Modifier.toString(mo);``      ``// 属性类型``      ``Class<?> type = field[i].getType();``      ``System.out.println(priv + ``" "` `+ type.getName() + ``" "` `+ field[i].getName() + ``";"``);``    ``}``    ` `    ``System.out.println(``"==========实现的接口或者父类的属性=========="``);``    ``// 取得实现的接口或者父类的属性``    ``Field[] filed1 = clazz.getFields();``    ``for` `(``int` `j = ``0``; j < filed1.length; j++) {``      ``// 权限修饰符``      ``int` `mo = filed1[j].getModifiers();``      ``String priv = Modifier.toString(mo);``      ``// 属性类型``      ``Class<?> type = filed1[j].getType();``      ``System.out.println(priv + ``" "` `+ type.getName() + ``" "` `+ filed1[j].getName() + ``";"``);``    ``}``  ``}``}

获取某个类的全部方法

Java | 复制

package` `net.xsoftlab.baike;``import` `java.io.Serializable;``import` `java.lang.reflect.Method;``import` `java.lang.reflect.Modifier;``public` `class` `TestReflect ``implements` `Serializable {``  ``private` `static` `final` `long` `serialVersionUID = -2862585049955236662L;``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``Class<?> clazz = Class.forName(``"net.xsoftlab.baike.TestReflect"``);``    ``Method method[] = clazz.getMethods();``    ``for` `(``int` `i = ``0``; i < method.length; ++i) {``      ``Class<?> returnType = method[i].getReturnType();``      ``Class<?> para[] = method[i].getParameterTypes();``      ``int` `temp = method[i].getModifiers();``      ``System.out.print(Modifier.toString(temp) + ``" "``);``      ``System.out.print(returnType.getName() + ``" "``);``      ``System.out.print(method[i].getName() + ``" "``);``      ``System.out.print(``"("``);``      ``for` `(``int` `j = ``0``; j < para.length; ++j) {``        ``System.out.print(para[j].getName() + ``" "` `+ ``"arg"` `+ j);``        ``if` `(j < para.length - ``1``) {``          ``System.out.print(``","``);``        ``}``      ``}``      ``Class<?> exce[] = method[i].getExceptionTypes();``      ``if` `(exce.length > ``0``) {``        ``System.out.print(``") throws "``);``        ``for` `(``int` `k = ``0``; k < exce.length; ++k) {``          ``System.out.print(exce[k].getName() + ``" "``);``          ``if` `(k < exce.length - ``1``) {``            ``System.out.print(``","``);``          ``}``        ``}``      ``} ``else` `{``        ``System.out.print(``")"``);``      ``}``      ``System.out.println();``    ``}``  ``}``}

通过反射机制调用某个类的方法

Java | 复制

package` `net.xsoftlab.baike;``import` `java.lang.reflect.Method;``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``Class<?> clazz = Class.forName(``"net.xsoftlab.baike.TestReflect"``);``    ``// 调用TestReflect类中的reflect1方法``    ``Method method = clazz.getMethod(``"reflect1"``);``    ``method.invoke(clazz.newInstance());``    ``// Java 反射机制 - 调用某个类的方法1.``    ``// 调用TestReflect的reflect2方法``    ``method = clazz.getMethod(``"reflect2"``, ``int``.``class``, String.``class``);``    ``method.invoke(clazz.newInstance(), ``20``, ``"张三"``);``    ``// Java 反射机制 - 调用某个类的方法2.``    ``// age -> 20. name -> 张三``  ``}``  ``public` `void` `reflect1() {``    ``System.out.println(``"Java 反射机制 - 调用某个类的方法1."``);``  ``}``  ``public` `void` `reflect2(``int` `age, String name) {``    ``System.out.println(``"Java 反射机制 - 调用某个类的方法2."``);``    ``System.out.println(``"age -> "` `+ age + ``". name -> "` `+ name);``  ``}``}

通过反射机制操作某个类的属性

Java | 复制

package` `net.xsoftlab.baike;``import` `java.lang.reflect.Field;``public` `class` `TestReflect {``  ``private` `String proprety = ``null``;``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``Class<?> clazz = Class.forName(``"net.xsoftlab.baike.TestReflect"``);``    ``Object obj = clazz.newInstance();``    ``// 可以直接对 private 的属性赋值``    ``Field field = clazz.getDeclaredField(``"proprety"``);``    ``field.setAccessible(``true``);``    ``field.set(obj, ``"Java反射机制"``);``    ``System.out.println(field.get(obj));``  ``}``}

反射机制的动态代理

Java | 复制

// 获取类加载器的方法``TestReflect testReflect = ``new` `TestReflect();``    ``System.out.println(``"类加载器 "` `+ testReflect.getClass().getClassLoader().getClass().getName());``package` `net.xsoftlab.baike;``import` `java.lang.reflect.InvocationHandler;``import` `java.lang.reflect.Method;``import` `java.lang.reflect.Proxy;``//定义项目接口``interface` `Subject {``  ``public` `String say(String name, ``int` `age);``}``// 定义真实项目``class` `RealSubject ``implements` `Subject {``  ``public` `String say(String name, ``int` `age) {``    ``return` `name + ``" "` `+ age;``  ``}``}``class` `MyInvocationHandler ``implements` `InvocationHandler {``  ``private` `Object obj = ``null``;``  ``public` `Object bind(Object obj) {``    ``this``.obj = obj;``    ``return` `Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), ``this``);``  ``}``  ``public` `Object invoke(Object proxy, Method method, Object[] args) ``throws` `Throwable {``    ``Object temp = method.invoke(``this``.obj, args);``    ``return` `temp;``  ``}``}``/**`` ``* 在java中有三种类类加载器。`` ``* `` ``* 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。`` ``* `` ``* 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类`` ``* `` ``* 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。`` ``* `` ``* 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。`` ``* `` ``* @author xsoftlab.net`` ``* `` ``*/``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``MyInvocationHandler demo = ``new` `MyInvocationHandler();``    ``Subject sub = (Subject) demo.bind(``new` `RealSubject());``    ``String info = sub.say(``"Rollen"``, ``20``);``    ``System.out.println(info);``  ``}``}

4反射机制的应用实例

在泛型为Integer的ArrayList中存放一个String类型的对象。

Java | 复制

package` `net.xsoftlab.baike;``import` `java.lang.reflect.Method;``import` `java.util.ArrayList;``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``ArrayList<Integer> list = ``new` `ArrayList<Integer>();``    ``Method method = list.getClass().getMethod(``"add"``, Object.``class``);``    ``method.invoke(list, ``"Java反射机制实例。"``);``    ``System.out.println(list.get(``0``));``  ``}``}

通过反射取得并修改数组的信息

Java | 复制

package` `net.xsoftlab.baike;``import` `java.lang.reflect.Array;``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``int``[] temp = { ``1``, ``2``, ``3``, ``4``, ``5` `};``    ``Class<?> demo = temp.getClass().getComponentType();``    ``System.out.println(``"数组类型: "` `+ demo.getName());``    ``System.out.println(``"数组长度 "` `+ Array.getLength(temp));``    ``System.out.println(``"数组的第一个元素: "` `+ Array.get(temp, ``0``));``    ``Array.set(temp, ``0``, ``100``);``    ``System.out.println(``"修改之后数组第一个元素为: "` `+ Array.get(temp, ``0``));``  ``}``}

通过反射机制修改数组的大小

Java | 复制

package` `net.xsoftlab.baike;``import` `java.lang.reflect.Array;``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``int``[] temp = { ``1``, ``2``, ``3``, ``4``, ``5``, ``6``, ``7``, ``8``, ``9` `};``    ``int``[] newTemp = (``int``[]) arrayInc(temp, ``15``);``    ``print(newTemp);``    ``String[] atr = { ``"a"``, ``"b"``, ``"c"` `};``    ``String[] str1 = (String[]) arrayInc(atr, ``8``);``    ``print(str1);``  ``}``  ``// 修改数组大小``  ``public` `static` `Object arrayInc(Object obj, ``int` `len) {``    ``Class<?> arr = obj.getClass().getComponentType();``    ``Object newArr = Array.newInstance(arr, len);``    ``int` `co = Array.getLength(obj);``    ``System.arraycopy(obj, ``0``, newArr, ``0``, co);``    ``return` `newArr;``  ``}``  ``// 打印``  ``public` `static` `void` `print(Object obj) {``    ``Class<?> c = obj.getClass();``    ``if` `(!c.isArray()) {``      ``return``;``    ``}``    ``System.out.println(``"数组长度为: "` `+ Array.getLength(obj));``    ``for` `(``int` `i = ``0``; i < Array.getLength(obj); i++) {``      ``System.out.print(Array.get(obj, i) + ``" "``);``    ``}``    ``System.out.println();``  ``}``}

将反射机制应用于工厂模式

Java | 复制

package` `net.xsoftlab.baike;``interface` `fruit {``  ``public` `abstract` `void` `eat();``}``class` `Apple ``implements` `fruit {``  ``public` `void` `eat() {``    ``System.out.println(``"Apple"``);``  ``}``}``class` `Orange ``implements` `fruit {``  ``public` `void` `eat() {``    ``System.out.println(``"Orange"``);``  ``}``}``class` `Factory {``  ``public` `static` `fruit getInstance(String ClassName) {``    ``fruit f = ``null``;``    ``try` `{``      ``f = (fruit) Class.forName(ClassName).newInstance();``    ``} ``catch` `(Exception e) {``      ``e.printStackTrace();``    ``}``    ``return` `f;``  ``}``}``/**`` ``* 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。`` ``* Java 工厂模式可以参考`` ``* http://baike.xsoftlab.net/view/java-factory-pattern`` ``* `` ``* 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。`` ``* `` ``* 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。`` ``* `` ``* java 读取 properties 配置文件 的方法可以参考`` ``* http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file`` ``* `` ``* @author xsoftlab.net`` ``*/``public` `class` `TestReflect {``  ``public` `static` `void` `main(String[] args) ``throws` `Exception {``    ``fruit f = Factory.getInstance(``"net.xsoftlab.baike.Apple"``);``    ``if` `(f != ``null``) {``      ``f.eat();``    ``}``  ``}``}

Java反射机制详解内容介绍到这里,更多java学习请关注编程字典java教程和问答部分,谢谢大家对编程字典的支持。


原文链接:https://www.cnblogs.com/lzq198754/p/5780331.html