java mongodb 返回所有field_JAVA高级之反射

9c674f18d5fa947bc929da33b33dc5c8.gif更多精彩,请点击上方蓝字关注我们!

18dc0d198b7f5af7b7d5632a08da1af3.png

今天跟大家分享JAVA高级之反射的知识。

一、什么是反射

反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。

  1. 反射机制的功能

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

  • 在运行时判断任意一个对象所属的类。

  • 在运行时构造任意一个类的对象。

  • 在运行时判断任意一个类所具有的成员变量和方法。

  • 在运行时调用任意一个对象的方法。

  • 生成动态代理。

  2. 实现反射机制的类

Java中主要由以下的类来实现Java反射机制(这些类都位于java.lang.reflect包中):
  • Class类:代表一个类。Field类:代表类的成员变量(成员变量也称为类的属性)。

  • Method类:代表类的方法。

  • Constructor类:代表类的构造方法。

  • Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

二、反射的使用

下面分步说明以下如何通过反射获取我们需要的内容。

我们先随意写一个Customer类(就是一个PO类),然后看看如何通过反射对这个类进行操作。

  1. Customer类

public class Customer {    private Long id;    private String name;    private int age;    public Customer() {}    public Customer(String name,int age) {        this.name = name;        this.age = age;    }    public Long getId() {        return id;    }    public void setId(Long id) {        this.id=id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name=name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age=age;    }}

2. ReflectTester类

这个类用来演示Reflection API的基本使用方法。这里自定义的copy方法是用来创建一个和参数objcet同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将其返回。

 import java.lang.reflect.Field;  import java.lang.reflect.Method;  public class ReflectTester {     public Object copy(Object object) throws Exception{          //获得对象的类型          Class classType=object.getClass();          System.out.println("Class:"+classType.getName());         //通过默认构造方法创建一个新的对象         Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});         //获得对象的所有属性         Field fields[]=classType.getDeclaredFields();         for(int i=0; i               Field field=fields[i];               String fieldName=field.getName();               String firstLetter=fieldName.substring(0,1).toUpperCase();               //获得和属性对应的getXXX()方法的名字               String getMethodName="get"+firstLetter+fieldName.substring(1);               //获得和属性对应的setXXX()方法的名字               String setMethodName="set"+firstLetter+fieldName.substring(1);               //获得和属性对应的getXXX()方法              Method getMethod=classType.getMethod(getMethodName,new Class[]{});               //获得和属性对应的setXXX()方法               Method setMethod=classType.getMethod(setMethodName,new Class[]{field.getType()});               //调用原对象的getXXX()方法               Object value=getMethod.invoke(object,new Object[]{});               System.out.println(fieldName+":"+value);               //调用拷贝对象的setXXX()方法              setMethod.invoke(objectCopy,new Object[]{value});        }         return objectCopy;      } }

下面分析一下上述代码。

首先,通过Object类中的getClass()方法获取对象的类型。

Class classType=object.getClass();

而Class类是Reflection API中的核心类,主要方法如下:

  • getName():获得类的完整名字。getFields():获得类的public类型的属性。

  • getDeclaredFields():获得类的所有属性。

  • getMethods():获得类的public类型的方法。

  • getDeclaredMethods():获得类的所有方法。

  • getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。

  • getConstrutors():获得类的public类型的构造方法。

  • getConstrutor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。

  • newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

第二步,通过默认构造方法创建一个新的对象,即先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。

Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
第三步,获得对象的所有属性,即通过Class类的getDeclaredFields()方法返回类的所有属性,包括public、protected、default和private访问级别的属性,
Field fields[]=classType.getDeclaredFields();

第四步,获得每个属性相应的get/set方法,然后执行这些方法,把原来的对象属性拷贝到新的对象中。

这里我们可以写一个InvokeTester的类,然后运用反射机制调用一个InvokeTester对象的add()方法(自定义方法),如add()方法的两个参数为int类型,那么获取表示add()方法的Method对象代码如下:

Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});

上述代码中也有用到Method的invoke方法,其接收参数必须为对象,如果参数为基本数据类型,必须转换为相应的包装类型的对象,如int要转换为Integer。

而invoke方法的返回值总是对象,如果实际被调用的方法的返回类型是基本数据类型,那么invoke方法会将其转换为相应的包装类型的对象,再将其返回。

下面简单测试一下,具体的方法调用如上面提到的add方法,可自行编写(具体实例见下篇):

 public static void main(String[] args) throws Exception {   Customer customer = new Customer();   customer.setId(10L);   customer.setName("adam");   customer.setAge(3);            new ReflectTester().copy(customer); }

   运行结果如下:

6c695108e9dc2dde3f7cdaf15f1b78c2.png

三、具体实例

下面我们尝试着通过反射机制对一个jar包中的类进行分析,把类中所有的属性和方法提取出来,并写入到一个文件里中

目录结构如下:

4ee8926c7171fc2f1b8a2c61dbdeb56d.png

  1. ReflexDemo类

主要代码部分,通过反射获取类、属性及方法。

import java.io.File;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader;import java.util.Enumeration;import java.util.jar.JarEntry;import java.util.jar.JarFile;/** * @ClassName: ReflexDemo * @Description: 通过反射获取类、属性及方法 * @author adamjwh * @date 2018年5月28日 * */public class ReflexDemo {    private static StringBuffer sBuffer;    public static void getJar(String jar) throws Exception {        try {            File file = new File(jar);            URL url = file.toURI().toURL();            URLClassLoader classLoader = new URLClassLoader(new URL[] { url },                    Thread.currentThread().getContextClassLoader());            JarFile jarFile = new JarFile(jar);            Enumeration<JarEntry> enumeration = jarFile.entries();            JarEntry jarEntry;            sBuffer = new StringBuffer();    //存数据            while (enumeration.hasMoreElements()) {                jarEntry = enumeration.nextElement();                if (jarEntry.getName().indexOf("META-INF") < 0) {                    String classFullName = jarEntry.getName();                    if (classFullName.indexOf(".class") < 0) {                        classFullName = classFullName.substring(0, classFullName.length() - 1);                    } else {                        // 去除后缀.class,获得类名                        String className = classFullName.substring(0, classFullName.length() - 6).replace("/", ".");                        Class> myClass = classLoader.loadClass(className);                        sBuffer.append("类名\t:" + className);                        System.out.println("类名\t:" + className);                        // 获得属性名                        Class> clazz = Class.forName(className);                        Field[] fields = clazz.getDeclaredFields();                        for (Field field : fields) {                            sBuffer.append("属性名\t:" + field.getName() + "\n");                            System.out.println("属性名\t:" + field.getName());                            sBuffer.append("-属性类型\t:" + field.getType() + "\n");                            System.out.println("-属性类型\t:" + field.getType());                        }                        // 获得方法名                        Method[] methods = myClass.getMethods();                        for (Method method : methods) {                            if (method.toString().indexOf(className) > 0) {                                sBuffer.append("方法名\t:" + method.toString().substring(method.toString().indexOf(className)) + "\n");                                System.out.println("方法名\t:" + method.toString().substring(method.toString().indexOf(className)));                            }                        }                        sBuffer.append("--------------------------------------------------------------------------------" + "\n");                        System.out.println("--------------------------------------------------------------------------------");                    }                }            }        } catch (Exception e) {            e.printStackTrace();        } finally {            sBuffer.append("End");            System.out.println("End");            WriteFile.write(sBuffer);    //写文件        }    }}
2. WriteFile类

进行写文件操作。

import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;/** * @ClassName: WriteFile * @Description: 写文件操作 * @author adamjwh * @date 2018年5月28日 * */public class WriteFile {    private static String pathname = "src/com/adamjwh/jnp/ex14/out.txt";    public static void write(StringBuffer sBuffer) throws Exception {        File file = new File(pathname);        BufferedWriter bw = new BufferedWriter(new FileWriter(file));        bw.write(sBuffer.toString());        bw.close();    }}
  3. Main类

这里我们需要在项目下新建一个lib文件夹,然后将要解析的jar包放入其中,比如这里我们放入jdk的dt.jar。目录结构如下:

6f9934d90f4a8ba919014a3355688a1d.png

执行程序:

/** * @ClassName: Main * @Description: * @author adamjwh * @date 2018年5月28日 * */public class Main {    private static String jar = "lib/dt.jar";    public static void main(String[] args) throws Exception {        ReflexDemo.getJar(jar);    }}

运行结果如下:  

9f27c01a7653e65bc37bb798a2b5bf09.png

今天就分享这么多,关于JAVA高级之反射,你学会了多少?

图文 / 来源网络

版权归原作者所有,侵联删

d281f2c4f88e75e6938c087b6b7ae410.png

814d0c53a4e60872093e01bbcf74cd8e.pngEND

2622ad5f1b0fcf9d0d5c2e2eb03593c2.png

碧茂课堂精彩课程推荐:

1.Cloudera数据分析课;

2.Spark和Hadoop开发员培训;

3.大数据机器学习之推荐系统;

4.Python数据分析与机器学习实战;

b3270f4cf5af410c9ab612b4b571da09.png

详情请关注我们公众号:碧茂大数据-课程产品-碧茂课堂

现在注册互动得海量学币,大量精品课程免费送!

95ed0658e32f611f4d216aec83bf6d75.png

关注最新行业动态,

加群进行技术交流!

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

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

相关文章

Linux入门笔记——cal、date、free、clear、history、man、whatis、uname

1、cal 显示日历2、date 显示系统当前的日期和时间3、df查看磁盘剩余空间的数量&#xff0c;常用参数 -h &#xff08;human&#xff09;人性化显示内容4、free显示空闲内存的数量&#xff0c;常用参数 -h &#xff08;human&#xff09;人性化显示内容5、clear清除控制终端显示…

Ueditor的配置及使用

Ueditor官网&#xff1a;http://ueditor.baidu.com/website/ &#xff08;项目需要JSP版本&#xff1a;UTF-8版&#xff09; 1.配置 <script type"text/javascript" charset"utf-8">window.UEDITOR_HOME_URL "${ctx}/assets/plugins/uedi…

努比亚z17s刷原生安卓_电脑运行手机APP,不会没关系,我推荐你使用显卡服务器运行安卓模拟器...

很多人都想用电脑端运行手机APP&#xff0c;但是又不知道怎么操作。纵横170yun小编推荐大家使用显卡服务器&#xff0c;在显卡服务器上运行安卓模拟器。让你轻轻松松在电脑端运行手机APP&#xff0c;甚至还可以多开噢 。如果你的电脑没有显卡&#xff0c;也没有关系&#xff0c…

Linux入门笔记——文件操作命令1

pwd Print name of current working directory&#xff08;打印出当前工作目录名&#xff09; cd Change directory&#xff08;更改目录&#xff09;例子&#xff1a;cd 更改工作目录到你的家目录&#xff08;和cd ~命令的运行结果是等同的 &#xff09;cd - 更…

使用JacpFX和JavaFX2构建富客户端

创建快速且可扩展的桌面客户端始终是一个挑战&#xff0c;特别是在处理大量数据和长时间运行的任务时。 尽管Eclipse RCP和Netbeans RCP是已建立的平台&#xff0c;但其想法是建立一个轻量级的框架来异步处理组件&#xff0c;类似于Web组件。 开发人员在线程主题上的工作应较少…

lob移表空间 oracle_Oracle数据库(1)Oracle体系结构概述(一)

Oracle数据库的体系结构主要包括&#xff1a;物理存储结构、逻辑存储结构、内存结构和实例进程结构。了解了Oracle的体系结构&#xff0c;就可以对Oracle数据库有一个整体认识&#xff0c;这样有利于后续Oracle的学习。下面我们分别来了解逻辑存储结构、物理存储结构、内存结构…

java 对象的上转型对象(父类)

Example5_10.java class 类人猿 {void crySpeak(String s) {System.out.println(s); } } class People extends 类人猿 {void computer(int a,int b) { int ca*b;System.out.println(c); }void crySpeak(String s) {System.out.println("***"s"***"); }…

手机mstsc远程工具_远程桌面连接,只需3步,轻松远程操控电脑!

远程桌面的好处远程桌面有很多好处的1.对于运维技术人员来说&#xff0c;可以随时随地管理远程主机&#xff0c;查看系统信息和硬件信息等系统性能诊断&#xff0c;远程应用管理内存、CPU等敏感信息报警提醒&#xff0c;对远程主机的一切尽收眼2.对于客户服务来说&#xff0c;可…

qbytearry有数据上限吗_金仕达大数据开发岗位面试题

金仕达-上海(1)自我介绍(2)在离线数仓&#xff0c;实时数仓中担任的角色是什么&#xff0c;介绍项目&#xff1f;数据量有多大&#xff1f;(3)实时的指标和离线指标怎么消除掉&#xff1f;有没有必要一致&#xff1f;(4)Flink上有多少个指标&#xff0c;一个指标一个jar包吗&am…

BZOJ 1012 单调队列+二分

思路&#xff1a; 维护一个单减的序列 序号是单增的 每回二分查找第一个比询问的大的值 我手懒 用得lower_bound //By SiriusRen #include <cstdio> #include <algorithm> using namespace std; #define int long long int m,mod,top,jy,ans,tot; char ch[3]; st…

Linux入门笔记——cat、sort、uniq、wc、head、tail、tee

cat &#xff0d; 连接文件 cat 命令读取一个或多个文件&#xff0c;然后复制它们到标准输出。你可以使用 cat 来显示 文件而没有分页cat 经常被用来显示简短的文本文件。案例 意义 cat ls-output.txt 读取文件标准输出 cat movie.mpeg.0* > movie.mpeg 连接文件&#x…

fir.im Log Guru 正式开源,快速找到 iOS 应用无法安装的原因

很开心的宣布 Log Guru 正式开源&#xff01; Log Guru&#xff0c;是 fir.im 开发团队创造的小轮子&#xff0c;用在 Mac 电脑上的日志获取&#xff0c;Github 地址&#xff1a;FIRHQ/LogGuru. Log Guru 使用方法 当有测试者反馈应用装不上的时候&#xff0c;将其测试设备连接…

python求解三元一次方程_北师大版八上数学5.2 求解二元一次方程组 知识点微课精讲...

知识点总结代入消元法代入消元法的实质是将二元一次方程组中的某一个方程进行未知数的分离&#xff0c;即将该方程进行变换&#xff0c;完整分离出一个独立的未知数&#xff0c;而这个未知数将用含有另一个未知数的式子来表示。设某二元一次方程组为&#xff1a;将第(1)式进行变…

Java 7:完整的invokedynamic示例

我当前的Java 7系列中的另一个博客条目。 这次&#xff0c;它处理的是invokedynamic&#xff0c;这是JVM上用于方法调用的新字节码指令。 invokedynamic指令允许在呼叫站点和呼叫接收者之间进行动态链接。 这意味着您可以将正在执行方法调用的类链接到在运行时正在接收调用的类…

VC6兼容性及打开文件崩溃问题解决

VC6虽然老&#xff0c;但是一些工程还非得用它打开&#xff0c;没办法…… 今天偶然用到&#xff0c;因为新装了系统&#xff0c;之前的问题又要重新解决一遍 在这记录下解决过程&#xff0c;方便以后查阅&#xff1a; 一.兼容问题&#xff1a; XP以上windows系统打开VC6时可能…

Linux入门笔记——echo

echo Display a line of text(显示一行文本)这个命令的作用相当简单明了。传递到 echo 命令的任一个参数都会在&#xff08;屏幕上&#xff09;显示出来。 小插曲&#xff1a; 每当你输入一个命令&#xff0c;然后按下 enter 键后&#xff0c;bash 会在执行你的命令之前对输入 …

dataframe 空值替换为0_Python数据分析:Pandas之DataFrame

内容目录 DataFrame简介DataFrame创建方式DataFrame索引和切片DataFrame属性DataFrame级联与合并DataFrame基本操作DataFrame分组聚合操作DataFrame数据透视与交叉表1 DataFrame简介 我们在上次课中讲到了Pandas的Series结构,还没看的点这里 ailsa:python数据分析:Pandas之S…

具有NetBeans,WebLogic 12c,JPA和MySQL数据源的Arquillian

您可能已经关注了我的文章&#xff0c;其中涉及使用嵌入式GlassFish测试更复杂的场景&#xff08; 第I部分/第II部分 &#xff09;。 我要做的下一步是使此设置与最新的WebLogic 12c一起使用。 入门 按照我的前两个帖子的入门部分中的步骤进行操作。 要使此工作正常&#xff…

lfu算法实现c语言_哈希查找算法(C语言实现)

上一节介绍了有关哈希表及其构造过程的相关知识&#xff0c;本节将介绍如何利用哈希表实现查找操作。在哈希表中进行查找的操作同哈希表的构建过程类似&#xff0c;其具体实现思路为&#xff1a;对于给定的关键字 K&#xff0c;将其带入哈希函数中&#xff0c;求得与该关键字对…

现代化Java代码的七个NetBeans提示

在“ 七个不可或缺的NetBeans Java提示”一文中 &#xff0c;我谈到了一般使用NetBeans提示的问题&#xff0c;然后重点介绍了七个提示。 接下来列出了该帖子中强调的七个提示&#xff1a; 可疑方法调用 使用或&#xff01; AND字符串构造函数比较字符串 构造函数中的可重写方…