志在指尖
用双手敲打未来

java反射机制精讲

java反射机制精讲
目录
1.反射机制的概念
2.反射的根底Class类
3.反射的用法
4.反射的使用示例
作者简介:全栈学习笔记,一个正在尽力的人
反射机制的概念:
在运转状况中,关于恣意一个类,都能够获取到这个类的一切特点和办法,关于恣意一个目标,都能够调用它的恣意一个办法和特点(包含私有的办法和特点),这种动态获取的信息以及动态调用目标的办法的功用就称为java言语的反射机制。反射被视为动态言语的要害。简略来说反射便是java的各种成分映射成对应的java类。
浅显点讲,经过反射,该类对咱们来说是彻底通明的,想要获取任何东西都能够。包含结构办法,特点,办法。
java反射机制供给的功用:
在运转时判断恣意一个目标所属的类;
在运转时结构恣意一个类的目标;
在运转时判断恣意一个类所具有的成员变量和办法;
在运转时调用恣意一个目标的办法;
生成动态代理。
这其实也涉及到了言语的动态与静态,java言语本身不算是动态言语,可是他有一个十分突出的动态机制,便是咱们所说的反射机制。
什么是动态言语呢?便是说,程序在运转的时分,(注意是运转的时分,不是编译的时分)答应改变程序结构或许变量类型。反之静态便是没有这些特点了。
反射的根底Class类
Class类是反射完成的根底,所以想要学会反射,必须先把握Class类的一些根本的概念。
类是什么?类是Class类的实例目标,所以说Class类是一切类的类。
要想解剖一个类,必须先获取到该类的字节码文件目标。而解剖运用的便是Class类中的办法,所以先要获取每一个字节码文件对应的Class类型的目标。
Class类没有公共的结构办法,Class目标是在类加载的时分由Java虚拟机以及经过调用类加载器中的defineClass办法自动结构的,因此不能显式地声明一个Class目标。这儿又涉及到一个东西,类的加载
扼要的说明一下:Java
类加载器:当程序需要是用某个类时,假如该类还没有被加载到内存中,则,体系会经过加载,衔接,初始化这三步来对类进行初始化
加载:便是指将class文件读入内存(编译之后的文件是.class文件),并为之创立一个Class目标
任何类被运用时,体系都会树立一个Class目标,第一次的时分会,第二次则会判断这个类是否存在。
衔接:验证是否有正确的内部结构,并和其他类协调一致
准备为类的静态成员分配内存,并设置默认初始化值
并做一个解析:将类的二进制数据中的字符引证替换为直接引证。
上面提到Class目标是不能直接创立的,可是咱们能够经过其他办法得到Class类的,现在有三种办法能够得到咱们想要的Class类,得到Class类之后就能正常的运用反射了。
获取Class的三种办法(获取一个类的字节码目标):
第一种:运用目标获取,运用目标的getClass获取
Personperson=newPerson();Classclazz=person.getClass();
第二种:运用静态特点class
Classclazz=Person.class
第三种:运用Class类的静态办法forName(字符串的类名)
注;类名要写全包名
Classclazz=Calss.forName(“…….”);
好了,要点来了,反射怎样玩才风趣!
反射的用法
上面说了经过反射能够得到恣意一个类的什么什么,下面来看看是不是真的。
第一步要干啥?当然是经过之前的哪三种办法来得到这个能够为所欲为的Class类。有三种办法,咱们先都做个示例吧!
上代码
//获取Class第一种办法Studentstudent=newStudent();
Classclazz=student.getClass();//获取Class第二种办法ClassclazzTwo=Student.class;//获取Class第三种办法ClassclazzThree=Class.forName(“demo.qzxxbj.entity.Student”);
System.out.println(“第一个”+clazz+”\n第二个”+clazzTwo+”\n第三个”+clazzThree);
成果
第一个classdemo.qzxxbj.entity.Student第二个classdemo.qzxxbj.entity.Student第三个classdemo.qzxxbj.entity.Student
能够看到三种办法得到的Class目标是相同的,没有差异。
第三种办法是会有一个找不到类的反常抛出的。
其间Student便是一个简略的类,能够是任何类。
经过Class获取恣意一个类的特点
Student类的代码
packagedemo.qzxxbj.entity;/**
*@author微信大众号:全栈学习笔记
*@date2020/3/29
*@description*/publicclassStudent{privateStringname;privateIntegerage;privateStringsex;publicintnumber;publicintgetNumber(){returnnumber;
}publicvoidsetNumber(intnumber){this.number=number;
}publicStringgetName(){returnname;
}publicvoidsetName(Stringname){this.name=name;
}publicIntegergetAge(){returnage;
}publicvoidsetAge(Integerage){this.age=age;
}publicStringgetSex(){returnsex;
}publicvoidsetSex(Stringsex){this.sex=sex;
}
}
以下获取Class的办法都采用第二种,比较简洁
//获取Class第二种办法ClassclazzTwo=Student.class;//获取该类指定特点名的public成员变量,包含父类的Fieldfield=clazzTwo.getField(“number”);//fieldpublicintdemo.qzxxbj.entity.Student.numberSystem.out.println(“该类指定特点名的public成员变量,包含父类的”+field);//获取该类指定称号声明的变量,即不包含父类的FielddeField=clazzTwo.getDeclaredField(“name”);//deFieldprivatejava.lang.Stringdemo.qzxxbj.entity.Student.nameSystem.out.println(“该类一切声明的变量,即不包含父类的”+deField);//获取该类一切的public声明的成员变量Fieldfields[]=clazzTwo.getFields();System.out.println(“public声明的变量:”);//publicintdemo.qzxxbj.entity.Student.numberfor(Fieldfield1:fields){System.out.println(field1);
}//获取该目标的一切成员变量FielddeFields[]=clazzTwo.getDeclaredFields();System.out.println(“该目标的一切成员变量”);//privatejava.lang.Stringdemo.qzxxbj.entity.Student.name//privatejava.lang.Integerdemo.qzxxbj.entity.Student.age//privatejava.lang.Stringdemo.qzxxbj.entity.Student.sex//publicintdemo.qzxxbj.entity.Student.numberfor(Fieldfield1:deFields){System.out.println(field1);
}
记住getFields(),getField(Stringname),getDeclaredFields(),getDeclaredField(Stringname)的差异,你就能好好把握这个知识点!
经过Class获取恣意成员办法
仍是看代码吧!
获取成员办法Method
//获取Class第二种办法ClassclazzTwo=Student.class;//根据办法名以及参数类型获取,只能获取public声明的办法,包含父类的Methodmethod=clazzTwo.getMethod(“setAge”,Integer.class);//publicjava.lang.Integerdemo.qzxxbj.entity.Student.getAge()System.out.println(method);//根据办法名以及参数称号获取该类声明的一切的特点办法,不包含父类的MethoddeMethod=clazzTwo.getDeclaredMethod(“setAge”,Integer.class);System.out.println(deMethod);//获取该目标声明的一切的public办法,包含父类的Methodmethods[]=clazzTwo.getMethods();//获取该目标声明的一切的办法,可是不包含父类的办法MethoddeMethods[]=clazzTwo.getDeclaredMethods();
一个Method办法打印出来是什么呢?上面代码中也包含了
publicvoiddemo.qzxxbj.entity.Student.setAge(java.lang.Integer)
和之前讲的Field是不是很相似。
既然提到了办法,那么就必定涉及到了办法调用,咱们得到了这些办法,又该怎样调用这个类里边的办法呢?运用invoke函数,Method这个类里边包含了一个invoke函数,英语好的就知道了,这个invoke的中文意思便是“调用”。
怎样用呢?
//获取Class第二种办法ClassclazzTwo=Student.class;//根据办法名以及参数类型获取,只能获取public声明的办法,包含父类的Methodmethod=clazzTwo.getMethod(“setAge”,Integer.class);//publicjava.lang.Integerdemo.qzxxbj.entity.Student.getAge()System.out.println(method);//使用Class创立一个目标的实例Studentstudent=(Student)clazzTwo.newInstance();//函数调用Objectvalue=method.invoke(student,20);//nullSystem.out.println(value);
以上的代码,你可能会看不懂,我来讲一下,首要,咱们获取一个类的Class,然后咱们经过这个Class获取该类的一个setAge办法,获取到这个办法后继续调用这个办法,调用办法是不是应该调用一个实例目标里边的办法?所以咱们需要先实例化一个目标,经过什么办法呢,经过class里边的newInstance(),创立一个实例,这种办法需要该实例化的类具有一个无参结构办法。还有其他办法也能创立一个实例,后边咱们会说。创立出一个实例目标之后,咱们就能开始调用办法了。
经过invoke对办法进行调用,invoke的第一个参数便是一个实例化目标,不然我去哪找这个办法。第二个参数,或许第三个,等等,后边的一切参数都是我调用的该办法所具有的参数,按照次序填进去就OK了。然后这个函数回来的是一个Object目标,你都能想到,我调用一个办法是不是要让他做一些事,做了这些事需要回来一个东西,不知道这个东西是啥,就用Object获取嘛。因为咱们调用的这个办法不需要回来值,所以便是null了。很简略是不是。学到了记得给我点个关注哦!精彩美文第一时间推送到你的手中。
经过Class获取结构办法
这个被我放到了最后来学习,毕竟我觉得用的份额比较少。一起来学习一下怎样用Class获取结构办法,并调用他。
publicStudent(Stringname,intid){this.name=name;this.id=id;
}
这儿咱们在Student类里边添加了一个结构办法。
然后咱们来获取这个结构办法。
//获取Class第二种办法ClassclazzTwo=Student.class;//获取无参结构办法,public声明的,包含父类,加上参数时便是获取特定的结构办法Constructorconstructor=clazzTwo.getConstructor();//publicdemo.qzxxbj.entity.Student()System.out.println(constructor);//获取该类一切的public声明的结构办法Constructorconstructors[]=clazzTwo.getConstructors();//获取指定参数的结构办法ConstructordeConstructor=clazzTwo.getDeclaredConstructor(String.class,Integer.class);//获取一切的该类的结构办法,不包含父类的ConstructordeConstructors[]=clazzTwo.getDeclaredConstructors();
上面代码应该很简单看懂吧,我就不细说了。这儿说一下怎样运用得到的结构办法,结构办法顾名思义便是来实例化目标的,上面咱们也有提到怎样经过Class实例化一个目标,现在咱们来经过结构方办法实例化一个目标
Studentstudent=(Student)deConstructor.newInstance(“全栈学习笔记”,21);//21System.out.println(student.getAge());
现在知道了吧,咱们差不都将反射的功用讲完了,就差一个反射的动态代理,这个比较重要,会专门出一篇博客,码字不易。希望点个关注。微信大众号:全栈学习笔记,精彩美文每天为你推送。
最后我根据我自己曾经的经历写了一个java反射的sql语句拼接,适当于是一个反射的使用吧。
反射的使用示例
经过反射动态的生成SQL语句,是不是也有点牛逼的感觉?
直接上代码吧,我只发一个SQL语句,感兴趣的能够私信我找我拿完整的代码!
publicStringinsert(Objectobject)throwsIllegalAccessException,NoSuchMethodException,InvocationTargetException{`//insertintostudent(id,name,sex)values(1,”全栈学习笔记”,”男”)StringBuildersql=newStringBuilder();
Classclazz=object.getClass();
sql.append(“insertinto”);
sql.append(clazz.getSimpleName()+”(“);
Field[]fields=clazz.getDeclaredFields();for(Fieldfield:fields){
sql.append(field.getName()+”,”);
}
sql.deleteCharAt(sql.length()-1);
sql.append(“)”);
sql.append(“values(“);for(Fieldfield:fields){
field.setAccessible(true);Objectvalue=field.get(object);StringfieldName=field.getName();Stringstr1=fieldName.substring(0,1).toUpperCase();Stringstr2=fieldName.substring(1,fieldName.length());StringstrValue=str1.concat(str2);//StringstrValue=fieldName.substring(0,1).toUpperCase().concat(fieldName.substring(1,fieldName.length()));Methodmethod=clazz.getMethod(“get”+strValue,null);Objectvalue1=method.invoke(object,null);//if(value1.getClass().equals(String.class))//if(field.getType().equals(String.class))if(value1instanceofString){
sql.append(“\””).append(value1).append(“\””).append(“,”);
}else{
sql.append(value1).append(“,”);
}
}
sql.deleteCharAt(sql.length()-1);
sql.append(“)”);
System.out.println(sql.toString());returnsql.toString();
}

未经允许不得转载:IT技术网站 » java反射机制精讲
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载