反射含路径问题部分笔记讲解Word文档下载推荐.docx
- 文档编号:22634005
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:17
- 大小:21.62KB
反射含路径问题部分笔记讲解Word文档下载推荐.docx
《反射含路径问题部分笔记讲解Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《反射含路径问题部分笔记讲解Word文档下载推荐.docx(17页珍藏版)》请在冰豆网上搜索。
);
//class文件时候独一无二的,那么Class对象也应该是单例的
System.out.println(clazz1==clazz2);
//true
System.out.println(clazz2==clazz3);
}
以上的方式都可以获取指定类的Class对象,在实际的开发中到底要使用哪一个?
一般的情况下我们都需要在不知道类名的情况下获取类的Class对象并进而获取类中包含的成员进行操作。
大家可以参考Tomcat的一个基本的server.xml文件
<
Resourcename="
UserDatabase"
auth="
Container"
type="
org.apache.catalina.UserDatabase"
description="
Userdatabasethatcanbeupdatedandsaved"
factory="
org.apache.catalina.users.MemoryUserDatabaseFactory"
类
pathname="
conf/tomcat-users.xml"
/>
2.将Class对象中的属性进行反射为Filed对象
常用的获取属性字段的方法
方法
Field[]getDeclaredFields()
获取所有声明的字段数组对象
Field[]getFields()
获取所有的声明的共有字段数组对象
FieldgetDeclaredField(Stringname)
获取指定名称的声明的字段对象
FieldgetField(Stringname)
获取指定名称的声明的共有字段对象
获取所有的声明字段数组对象。
//获取Shape类的Class对象
Classclazz=Class.forName("
cn.sve.bean.Shape"
//获取所有的属性
Field[]fs=clazz.getDeclaredFields();
System.out.println(fs.length);
//2
//获取所有共有的属性
fs=clazz.getFields();
//1
//获取指定名字的私有的属性
Fieldfield=clazz.getDeclaredField("
x"
System.out.println(field);
//获取指定名字的共有的属性
field=clazz.getField("
y"
举例2:
调用Field类的方法进行字段对象的操作。
Shapeshape=newShape();
//20
//操作私有的属性x
System.out.println("
属性名:
"
+field.getName());
//获取x的属性值,需要暴力的反射
field.setAccessible(true);
设置之前的x值:
"
+field.get(shape));
//设置x的属性值
field.set(shape,20);
设置之后的x值:
//给属性y进行设置值
//获取设置属性值之前的值
设置之前的y值:
field.set(shape,30);
//30
设置之后的y值:
+shape.y);
}
以上的代码可以通过程序进行反射类中的属性字段并操作,但是没有进行静态属性的反射和操作。
举例3:
反射静态的成员属性。
publicstaticvoidmain(String[]args)throwsException{
//获取共有的静态属性
Fieldfield=clazz.getField("
z"
设置之前的z值:
+field.get(null));
field.set(null,40);
设置之后的z值:
3.将Class对象中的方法进行反射为Method对象。
//获取所有的声明的方法
Method[]ths=clazz.getDeclaredMethods();
System.out.println(ths.length);
//获取私有的带参数的sayHello方法
MethodsayHello=clazz.getDeclaredMethod("
sayHello"
String.class);
System.out.println(sayHello);
//调用私有的方法
sayHello.setAccessible(true);
sayHello.invoke(newShape(),"
//获取所有的共有的方法
ths=clazz.getMethods();
//10
//获取带参数的共有的方法
Methodgreet=clazz.getDeclaredMethod("
greet"
System.out.println(greet);
//方法的调用
greet.invoke(newShape(),"
4.将Class对象中的构造函数进行反射为Constructor对象。
//获取所有的声明的构造函数
Constructor[]cons=clazz.getDeclaredConstructors();
System.out.println(cons.length);
//3
//获取带参数的私有的构造函数对象
Constructorcon=
clazz.getDeclaredConstructor(int.class,int.class);
System.out.println(con);
//暴力反射私有的构造函数创建对象
con.setAccessible(true);
Shapemyshape=(Shape)con.newInstance(400,500);
System.out.println(myshape.getX()+"
"
+myshape.y);
//获取所有的共有的构造函数
cons=clazz.getConstructors();
con=clazz.getConstructor(int.class);
//调用构造函数创建对象
Shapeshape=(Shape)con.newInstance(100);
System.out.println(shape.getX());
面试题:
请简单的叙述出你所可以创建的对象的几种方式?
第一种:
直接使用new关键字
第二种:
Construnctor.newInstance
第三种:
枚举
第四种:
单例、工厂模式
◆内省(Introspect)
其实在以上的反射技术体验中我们发现其实反射的对象一般是一个具有特定功能的一个类。
引入一个基本的概念:
JavaBean
如果一个类提供了封装好的属性、构造函数(无参数)、共有的get和set方法以及简单的业务逻辑方法那么将这样的一个类称之为JavaBean类。
对于一个javaBean的操作无非就是给属性值进行操作或函数的调用。
使用反射比较繁琐,那么SUN就提供了内省的技术方便大家进行JavaBean类的操作。
BeanInfo
对JavaBean进行描述的接口
Introspector
描述所有的JavaBean的成员类
PropertyDescriptor
描述的是JavaBean的属性类
使用属性描述器类操作JavaBean属性。
创建一个Book的javabean类
publicclassBook{
privateStringname;
//null
privateStringauthor;
privatedoubleprice;
//0.0
privateDatedate;
publicBook(){
super();
publicBook(Stringname,Stringauthor,doubleprice,Datedate){
this.name=name;
this.author=author;
this.price=price;
this.date=date;
//省略get和set方法
使用内省技术进行简单的属性的操作。
publicstaticvoidmain(String[]args)throwsException{
//获取一个属性的描述器对象就相当于获取了属性的名、set和get方法
PropertyDescriptorpd=new
PropertyDescriptor("
name"
Book.class);
//获取set方法
Methodset=pd.getWriteMethod();
//调用该方法设置属性的值
Bookbook=newBook();
设置前获取name属性值:
+book.getName());
set.invoke(book,"
JavaSE进阶"
设置后获取name属性值:
//获取get方法
Methodget=pd.getReadMethod();
System.out.println(get.invoke(book,null));
以上的代码每次都只能操作一个属性,这样就比较繁琐。
可以使用其他的类直接获取所有的属性描述器通过循环来直接操作。
//获取指定的BeanInfo对象
BeanInfoinfo=Introspector.getBeanInfo(Book.class);
//获取Book类中的所有的属性的描述器对象
PropertyDescriptor[]pds=info.getPropertyDescriptors();
//输出长度
System.out.println(pds.length);
//查看数组的第一个属性描述器是谁
PropertyDescriptorpd=pds[0];
//作者
System.out.println(pd.getName());
Bookbook=newBook();
//给书设置作者信息
pd.getWriteMethod().invoke(book,"
System.out.println(pd.getReadMethod().invoke(book,null));
总结:
其实发现在使用内省进行属性操作的时候要结合反射一起使用。
一个JavaBean中为什么必须要提供一个无参数的构造函数?
原因一:
为了可以做父类。
原因二:
为了可以使用反射创建对象。
◆BeanUtils工具
在实际的开发中我们经常需要将用户的录入的数据进行封装为对象,那么如果使用反射和内省技术就会变得吃力。
因此本节主要给大家讲解一个开源的操作JavaBean的一个工具即BeanUtils。
下载:
http:
//www.apache.org
beanutils-1.8.0.zip
commons-logging.jar
包的引入:
在项目中创建一个文件夹如libs,然后将整个项目需要的第三方的jar包可以直接拷贝带该目录,随后打开该目录全选右键Buildpathaddpath看到奶瓶子即可
使用BeanUtils工具封装用户提交的数据。
//模拟用户的输入的数据如下
Stringname="
XML基础"
;
Stringauthor="
Stringprice="
99.99"
Stringdate="
2016-07-07"
//任务是将以上的属性设置给指定的Book对象
BeanUtils.setProperty(book,"
name);
author"
author);
price"
price);
//查看属性是否封装好
System.out.println(book);
发现使用上面的代码可以省略基本数据类型的转型的问题。
进而提高代码的开发效率。
自定义一个类型转换器类。
//注册一个自己的转换器
/**
*converter指定具体的转换器
*clazz遇到什么类型调用上面的转换器
*/
ConvertUtils.register(
newConverter(){
//回调方法
@Override
publicObjectconvert(Classtype,Objectvalue){
if(value==null){
returnnull;
}
//转换为String
Stringdata=(String)value;
//将指定格式的字符串转换为Date
SimpleDateFormatformat=newSimpleDateFormat("
yyyy-MM-dd"
Datedate=null;
try{
date=format.parse(data);
returndate;
}catch(ParseExceptione){
e.printStackTrace();
}
},
Date.class);
date"
date);
如果每次遇到一个复杂类型都需要自定义转换器,那样的话实在麻烦。
大家看在开发的时候可以先查看该接口是否提供了有效的实现类。
ConvertUtils.register(newDateLocaleConverter(),Date.class);
其实真正的封装好的数据需要存储在数据库中,那么javabean的数据类型应该和数据库的数据类型保持一致,那么在声明持久化javabean的时候需要全部为数据库的基本数据类型。
因此大家在JavaBean中需要导入的是java.sql.Date类,这样就直接可以将日期自动转换了。
实现封装好的JavaBean对象的属性拷贝。
//实现属性封装数据的一个拷贝
Bookcopy=newBook();
System.out.println(copy);
PropertyUtils.copyProperties(copy,book);
思考:
如果使用BeanUtils封装用户的数据,那么也就是一个一个设置啊?
岂不是也很麻烦?
其实在真是的环境中我们可以直接获取用户提交的所有的数据信息,只需要进行遍历即可,但是为了方便快速的设置,那么可以将javabean中的属性名和用户提交的数据名保持一致。
框架体验
其实所谓的框架就是通过一些配置文件来将需要运行的模块以及类、方法在软件启动的时候自动运行。
如果将需要运行类以及模块配置在文件中那么便于后期的一个维护。
1.创建一个配置文件如下
run=cn.sve.service.UserService
me=autoRun
value=jack,lucy
2.创建两个实现接口的服务类
UserService.java
publicclassUserServiceimplementsService{
//提供自动运行的方法
publicvoidautoRun(Stringnames){
//使用,号切割用户列表
String[]ns=names.split("
//遍历
for(Stringname:
ns){
System.out.println("
姓名:
+name);
}
}
StartService.java
publicclassStartServiceimplementsService{
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 反射 路径 问题 部分 笔记 讲解