Java基础之反射机制

Java反射机制

反射机制是什么

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

反射机制能做什么

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

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

反射机制的相关API

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

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类对象

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());}
}

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

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}
}

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

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

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());elseSystem.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;}@Overridepublic String toString() {return "User [age=" + age + ", name=" + name + "]";}
}

获取某个类的全部属性

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() + ";");}}
}

获取某个类的全部方法

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();}}
}

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

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);}
}

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

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));}
}

反射机制的动态代理

// 获取类加载器的方法
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);}
}

反射机制的应用实例

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

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));}
}

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

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));}
}

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

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();}
}

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

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反射机制详解

转载于:https://www.cnblogs.com/sun-haiyu/p/7026945.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#逻辑运算符及解析

文章目录博主写作不容易&#xff0c;孩子需要您鼓励 万水千山总是情 , 先点个赞行不行 逻辑运算符用于连接一个或多个条件&#xff0c;判断这些条件是否成立。 &#xff23;&#xff03;的逻辑运算符可以分为两类&#xff1a; “&#xff06;” “&#xff5c;” “&…

通过ProGet搭建一个内部的Nuget服务器

.NET Core项目完全使用Nuget 管理组件之间的依赖关系&#xff0c;Nuget已经成为.NET 生态系统中不可或缺的一个组件&#xff0c;从项目角度&#xff0c;将项目中各种组件的引用统统交给NuGet&#xff0c;添加组件/删除组件/以及更新组件即可一键完成&#xff0c;大大提升工作效…

unity官方教程-TANKS(一)

unity官方教程TANKS&#xff0c;难度系数中阶。跟着官方教程学习Unity&#xff0c;通过本教程你可以学会使用Unity开发游戏的基本流程。 一、环境 Unity 版本 > 5.2Asset Store 里面搜索 Tanks!Tutorial ,下载导入 二、项目设置 为了便于开发&#xff0c;很多时候我们选用的…

Play框架的用户验证。

最近刚刚参与一个基于Play框架的管理平台的升级工作&#xff0c;其中涉及到了用户的验证工作。第一次接触play框架&#xff0c;直接看已有代码&#xff0c;有点晕。因此&#xff0c;自己实现了一个简单的用户验证功能。 首先&#xff0c;新建一个User类&#xff0c;包含两个属性…

C#条件运算符if-else的简化格式

文章目录博主写作不容易&#xff0c;孩子需要您鼓励 万水千山总是情 , 先点个赞行不行 条件运算符&#xff08;&#xff1f;&#xff1a;&#xff09;是&#xff49;&#xff46;……&#xff45;&#xff4c;&#xff53;&#xff45;的简化形式 其使用格式为&#xff1a…

码率控制方式选择

同码率下的图像质量或同图像质量下的码率。 AVCodecContext /** * the average bitrate * - encoding: Set by user; unused for constant quantizer encoding. * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the strea…

Fortran执行语句中的“双冒号” ::

双冒号“::”&#xff0c;通常出现于Fortran在变量声明中&#xff0c;但是在特殊情况下&#xff0c;也会出现于数组中。例如&#xff1a; ... real,target,dimension(10):: a real,pointer,dimension(:):: pa,pb integer:: n3 ... pa > a(n::1) pb > a(n:10:1) ... 咋一看…

VS配置本地IIS以域名访问

1.IIS下配置自己的网站&#xff0c;添加主机名 2.修改hosts文件&#xff08;C://Windows/System32/drivers/etc&#xff09; 3.VS中配置项目Web服务器&#xff08;选择外部主机&#xff09; 转载于:https://www.cnblogs.com/zuimeideshi520/p/7028544.html

try、catch、finally 和 throw-C#异常处理

文章目录博主写作不容易&#xff0c;孩子需要您鼓励 万水千山总是情 , 先点个赞行不行 异常是在程序执行期间出现的问题。C# 中的异常是对程序运行时出现的特殊情况的一种响应&#xff0c;比如尝试除以零。 异常提供了一种把程序控制权从某个部分转移到另一个部分的方式。…

Spark RDD/Core 编程 API入门系列 之rdd实战(rdd基本操作实战及transformation和action流程图)(源码)(三)...

本博文的主要内容是&#xff1a; 1、rdd基本操作实战 2、transformation和action流程图 3、典型的transformation和action RDD有3种操作&#xff1a; 1、 Trandformation 对数据状态的转换&#xff0c;即所谓算子的转换 2、 Action 触发作业&#xff0c;即所谓得结果…

用GDB调试程序

GDB概述GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许&#xff0c;各位比较喜欢那种图形界面方式的&#xff0c;像VC、BCB等IDE的调试&#xff0c;但如果你是在 UNIX平台下做软件&#xff0c;你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所…

灯塔的出现给那些有想法,有能力而又缺乏资金的社区人士提供了一条途径

2019独角兽企业重金招聘Python工程师标准>>> 在上个月&#xff0c;BCH社区传出基于比特币现金的众筹平台Lighthouse&#xff08;灯塔&#xff09;正在复活的消息&#xff0c;并且有网友在论坛上贴出了部分网站图片。当消息被证实为真&#xff0c;官网和项目的审核细…

PID 算法理解

PID 算法 使用环境&#xff1a;受到外界的影响不能按照理想状态发展。如小车的速度不稳定的调节&#xff0c;尽快达到目标速度。 条件&#xff1a;闭环系统->有反馈 要求&#xff1a;快准狠 分类&#xff1a;位置式、增量式 增量式 输入&#xff1a;前次速度、前前次速度、前…

C#字符串的基本操作

文章目录简介字符串判断是否相等语法实例字符串比较大小语法实例判断字符串变量是否包含指定字符或字符串语法实例查找字符串变量中指定字符或字符串出现的位置语法实例取子串语法实例插入子串语法实例删除子串语法实例替换子串语法实例去除字符串空格语法实例博主写作不容易&a…

C++利用SOCKET传送文件

C利用SOCKET传送文件 /*server.h*/ #pragma comment(lib, "WS2_32") #include <WinSock2.h> #include <iostream> //#include <stdio.h> #include <assert.h> #ifndef COMMONDEF_H #define COMMONDEF_H #define MAX_PACKET_SIZE 10240 …

三种方式在CentOS 7搭建KVM虚拟化平台

KVM 全称是基于内核的虚拟机&#xff08;Kernel-based Virtual Machine&#xff09;&#xff0c;它是一个 Linux的一个内核模块&#xff0c;该内核模块使得 Linux变成了一个Hypervisor&#xff1a;它由 Quramnet开发&#xff0c;该公司于 2008年被 Red Hat 收购 KVM的整体结构&…

(五)EasyUI使用——datagrid数据表格

DataGrid以表格形式展示数据&#xff0c;并提供了丰富的选择、排序、分组和编辑数据的功能支持。DataGrid的设计用于缩短开发时间&#xff0c;并且使开发人员不需要具备特定的知识。它是轻量级的且功能丰富。单元格合并、多列标题、冻结列和页脚只是其中的一小部分功能。具体功…

拾取模型的原理及其在THREE.JS中的代码实现

1. Three.js中的拾取 1.1. 从模型转到屏幕上的过程说开 由于图形显示的基本单位是三角形&#xff0c;那就先从一个三角形从世界坐标转到屏幕坐标说起&#xff0c;例如三角形abc 乘以模型视图矩阵就进入了视点坐标系&#xff0c;其实就是相机所在的坐标系&#xff0c;如下图&am…

StringBuilder-C#字符串对象

博主写作不容易&#xff0c;孩子需要您鼓励 万水千山总是情 , 先点个赞行不行 在C# 中&#xff0c;string是引用类型&#xff0c;每次改变string类对象的值&#xff0c;即修改字符串变量对应的字符串&#xff0c;都需要在内存中为新的字符串重新分配空间。在默写特定的情况…