java反射如何通俗易懂理解-金沙1005

java反射如何通俗易懂理解_java反射到底是啥[通俗易懂]之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前java篇的基础上再写一篇有关反射的内容,还是以实际的程序为主,了解反射是做什么的、应该怎么用。一、什么是反射反射就是把java类中的各个成分映射成一个个的java对象。即在运行状态中,对于任意一个类,都能够知道

  之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前java篇的基础上再写一篇有关反射的内容,还是以实际的程序为主,了解反射是做什么的、应该怎么用。

一、什么是反射

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

  1. 反射机制的功能

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

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

  2. 实现反射机制的类

   java中主要由以下的类来实现java反射机制(这些类都位于java.lang.reflect包中):

  • class类:代表一个类。 field类:代表类的成员变量(成员变量也称为类的属性)。

  • method类:代表类的方法。

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

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

二、反射的使用

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

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

  1. customer类

 1 public class customer {
 2     
 3     private long id;
 4     private string name;
 5     private int age;
 6       
 7     public customer() {}
 8     
 9     public customer(string name,int age) {
10         this.name = name;
11         this.age = age;
12     }
13       
14     public long getid() {
15         return id;
16     }
17     public void setid(long id) {
18         this.id=id;
19     }
20     public string getname() {
21         return name;
22     }
23     public void setname(string name) {
24         this.name=name;
25     }
26     public int getage() {
27         return age;
28     }
29     public void setage(int age) {
30         this.age=age;
31     }
32 
33 }

希望我今天分享的这篇文章可以帮到您。

   2. reflecttester类

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

 1 import java.lang.reflect.field;
 2 import java.lang.reflect.method;
 3 
 4 public class reflecttester {
 5     
 6     public object copy(object object) throws exception{
 7         //获得对象的类型
 8         class classtype=object.getclass();
 9         system.out.println("class:" classtype.getname());
10 
11         //通过默认构造方法创建一个新的对象
12         object objectcopy=classtype.getconstructor(new class[]{}).newinstance(new object[]{});
13 
14         //获得对象的所有属性
15         field fields[]=classtype.getdeclaredfields();
16 
17         for(int i=0; i){
18               field field=fields[i];
19 
20               string fieldname=field.getname();
21               string firstletter=fieldname.substring(0,1).touppercase();
22               //获得和属性对应的getxxx()方法的名字
23               string getmethodname="get" firstletter fieldname.substring(1);
24               //获得和属性对应的setxxx()方法的名字
25               string setmethodname="set" firstletter fieldname.substring(1);
26 
27               //获得和属性对应的getxxx()方法
28               method getmethod=classtype.getmethod(getmethodname,new class[]{});
29               //获得和属性对应的setxxx()方法
30               method setmethod=classtype.getmethod(setmethodname,new class[]{field.gettype()});
31 
32               //调用原对象的getxxx()方法
33               object value=getmethod.invoke(object,new object[]{});
34               system.out.println(fieldname ":" value);
35               //调用拷贝对象的setxxx()方法
36              setmethod.invoke(objectcopy,new object[]{value});
37         }
38         return objectcopy;
39      }
40 
41 }

  下面分析一下上述代码。

  首先,通过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方法,可自行编写(具体实例见下篇):

1 public static void main(string[] args) throws exception {
2   customer customer = new customer();
3   customer.setid(10l);
4   customer.setname("adam");
5   customer.setage(3);
6         
7   new reflecttester().copy(customer);
8 }   

   运行结果如下:

  java反射如何通俗易懂理解_java反射到底是啥[通俗易懂]

三、具体实例

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

  目录结构如下:

  java反射如何通俗易懂理解_java反射到底是啥[通俗易懂]

  1. reflexdemo类

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

 1 import java.io.file;  2 import java.lang.reflect.field;  3 import java.lang.reflect.method;  4 import java.net.url;  5 import java.net.urlclassloader;  6 import java.util.enumeration;  7 import java.util.jar.jarentry;  8 import java.util.jar.jarfile;  9 10 /** 11  * @classname: reflexdemo 12  * @description: 通过反射获取类、属性及方法 13  * @author adamjwh 14  * @date 2018年5月28日 15  * 16 */ 17 public class reflexdemo { 18 19 private static stringbuffer sbuffer; 20 21 public static void getjar(string jar) throws exception { 22 try { 23 file file = new file(jar); 24 url url = file.touri().to; 25 urlclassloader classloader = new urlclassloader(new url[] { url }, 26  thread.currentthread().getcontextclassloader()); 27 28 jarfile jarfile = new jarfile(jar); 29 enumeration enumeration = jarfile.entries(); 30  jarentry jarentry; 31 32 sbuffer = new stringbuffer(); //存数据 33 34 while (enumeration.hasmoreelements()) { 35 jarentry = enumeration.nextelement(); 36 37 if (jarentry.getname().indexof("meta-inf") < 0) { 38 string classfullname = jarentry.getname(); 39 if (classfullname.indexof(".class") < 0) { 40 classfullname = classfullname.substring(0, classfullname.length() - 1); 41 } else { 42 // 去除后缀.class,获得类名 43 string classname = classfullname.substring(0, classfullname.length() - 6).replace("/", "."); 44 class myclass = classloader.loadclass(classname); 45 sbuffer.append("类名\t:"   classname); 46 system.out.println("类名\t:"   classname); 47 48 // 获得属性名 49 class clazz = class.forname(classname); 50 field[] fields = clazz.getdeclaredfields(); 51 for (field field : fields) { 52 sbuffer.append("属性名\t:"   field.getname()   "\n"); 53 system.out.println("属性名\t:"   field.getname()); 54 sbuffer.append("-属性类型\t:"   field.gettype()   "\n"); 55 system.out.println("-属性类型\t:"   field.gettype()); 56  } 57 58 // 获得方法名 59 method[] methods = myclass.getmethods(); 60 for (method method : methods) { 61 if (method.tostring().indexof(classname) > 0) { 62 sbuffer.append("方法名\t:"   method.tostring().substring(method.tostring().indexof(classname))   "\n"); 63 system.out.println("方法名\t:"   method.tostring().substring(method.tostring().indexof(classname))); 64  } 65  } 66 sbuffer.append("--------------------------------------------------------------------------------"   "\n"); 67 system.out.println("--------------------------------------------------------------------------------"); 68  } 69  } 70  } 71 } catch (exception e) { 72  e.printstacktrace(); 73 } finally { 74 sbuffer.append("end"); 75 system.out.println("end"); 76 77 writefile.write(sbuffer); //写文件 78  } 79  } 80 81 }

  2. writefile类

  进行写文件操作。

 1 import java.io.bufferedwriter;  2 import java.io.file;  3 import java.io.filewriter;  4  5 /**  6  * @classname: writefile  7  * @description: 写文件操作  8  * @author adamjwh  9  * @date 2018年5月28日 10  * 11 */ 12 public class writefile { 13 14 private static string pathname = "src/com/adamjwh/jnp/ex14/out.txt"; 15 16 public static void write(stringbuffer sbuffer) throws exception { 17 file file = new file(pathname); 18 bufferedwriter bw = new bufferedwriter(new filewriter(file)); 19 20  bw.write(sbuffer.tostring()); 21  bw.close(); 22  } 23 24 }

  3. main类

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

  java反射如何通俗易懂理解_java反射到底是啥[通俗易懂]

  执行程序:

 1 /**  2  * @classname: main  3  * @description:  4  * @author adamjwh  5  * @date 2018年5月28日  6  *  7 */  8 public class main {  9 10 private static string jar = "lib/dt.jar"; 11 12 public static void main(string[] args) throws exception { 13  reflexdemo.getjar(jar); 14  } 15 16 }

  运行结果如下:

  java反射如何通俗易懂理解_java反射到底是啥[通俗易懂]

金沙1005的版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由思创斯整理,转载请注明出处:https://ispacesoft.com/380197.html

(0)


相关推荐

  • 数组的map方法_数组的filter方法「建议收藏」1.数组filter方法作用筛选数组,将满足条件的元素放入新数组中2.语法:array.filter(function(item,index,arr){})第一个参数:item,必须,当前元素的值第二个参数:index,可选,当前元素在数组中的索引值第三个参数:arr,当前元素所处的数组对象3.filter方法特点(1)函数执行次数===数组长度(2)函数内部的returnreturntrue:满足筛选条件,放入新数组中return_数组filter

  • java度转度分秒_所有长度单位换算「建议收藏」有没有适合win7系统的单位换算器,可以推荐安装?或是比较好用的在线换.importjava.awt.event.*;importjavax.swing.*;importjava.awt.*;publicclasstestconvert.this.add(newjlabel("单位(m/y)"));this.add(text1);this.add(newjlabel("…_java米换算千米

  • java怎么连接数据库_java怎么连接数据库[通俗易懂]概述java程序发送e-mail十分简单,但是首先你应该在你的机器上安装javamailapi和javaactivationframework(jaf)。java访问数据则需要 使用jdbc连接mysql数据库。jdbc起到数据库驱动作用。e-mail的发送第

  • java进度条不关闭_重装系统进度条不动在编写完进度条后,我们有时候会遇到它完全不动的情况,小伙伴们知道是什么原因吗?下面听小编为你们讲解讲解。进度条不动可能是因为这个原因,“当应用程序在事件线程中执行长时间的操作时,会阻塞正常的awt事件处理,因此阻止了重绘操作的发生”,即api本身就是线程不安全的。造成这个错误的原因,就是在run方法内直接写:progressbar.setvalue(jd);最终修改示例:importjava.a…

  • javascript中createtextfile函数javascript中createtextfile函数是创建指定的文件名并返回一个textstream对象,可以使用这个对象对文件进行读写。使用实例:object.createtextfile(filename[,overwrite[,unicode]])其中object是必选项。应

  • 【springboot】34、springboot整合redis实现序列化存储java对象[通俗易懂]前面我们已经介绍过【springboot】十七、springboot中整合redis,我们可以看出,在springboot对redis做了一系列的自动装配,使用还是非常方便的一、背景1、思考‘通过我们前面的学习,我们已经可以往redis中存入字符串,那么我们要往redis中存入java对象该怎么办呢?2、方案我们可以将java对象转化为json对象,然后转为json字符串,存入redis,那么我们从redis中取出该数据的时候,我们也只能取出字符串,并转

    2022年12月16日
  • java2的7次方怎么表示_2的十万次幂怎么求?用java做再一次修正了下代码,测试了下大于10的数字也可以正常执行了publicclasspowertest{publicint[]power(intbase,intindex){int[]end=newint[]{1};for(inti=0;i

  • java构造函数和构造方法_java默认构造函数我们人出生的时候,有些人一出生之后再起名字的,但是有些人一旦出生就已经起好名字的。那么我们在java里面怎么在对象一旦创建就赋值呢?1.构造方法的作用:构造方法作用:对对象进行初始化.如图:2.构造函数与普通函数的区别:(1). 一般函数是用于定义对象应该具备的功能。而构造函数定义的是,对象在调用功能之前,在建立时,应该具备的一些内容。也就是对象的初

发表回复

您的电子邮箱地址不会被公开。

联系js555888金沙老品牌

关注“java架构师必看”公众号

回复4,添加站长微信。

附言:ispacesoft.com网而来。

关注微信
网站地图