Day_52_Java高级
1. XML
Xml格式的文件在接下来的框架学习尤为重要,比如在框架中的配置文件大多都是用的xml格式的文件来配置的,所以xml格式的文件创建与解析特别重要。
1.1 XML概念
XML(eXtensible Markup Language)是一种可扩展标识语言,是一种简单的数据存储语言,使用一系列简单的标记描述数据。目前推荐遵循的是W3C组织于2000年发布的XML1.0版本。
1.2 XML语法规则
①、声明标签定在首行:<?xml version=“1.0” encoding=“utf-8|gb2312”?>
②、文档有且只有一个根元素
③、非空元素都必须有一对标签:起始/关闭标签
④、空元素的标签中同时表示起始和结束标签</>
⑤、大小写敏感
⑥、标签必须正确地嵌套
⑦、元素的属性必须有属性值且属性值必须加引号(单引或双引都可以)
⑧、在 XML 中,应使用实体引用来代替特殊字符
1.3 实体引用
< 小于号< 【必须】
> 大于号>
& 和号& 【必须】
' 单引号‘
" 双引号”
1.4 元素命名规则
名称可以含字母、数字以及其他的字符
名称不能以数字或者标点符号开始
名称不能以字符 “xml”(或者 XML、Xml)开始
名称不能包含空格
可使用任何名称,没有保留的字词
1.5 XML的特点
XML 仅仅是纯文本
XML 的设计宗旨是传输数据,而非显示数据
XML 是独立于软件和硬件的信息传输工具
XML 标签没有被预定义,需要自行定义标签
1.6 Dom4j概念
dom4j是一个Java的XML API,是jdom的升级品,用来读写XML文件的。dom4j是一个十分优秀javaXML API,具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面还可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,所以可以知道dom4j无论在哪个方面都是非常出色的。如今可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这已经是必须使用的jar包, Hibernate也用它来读写配置文件。
1.7 XML文档示例
<?xml version="1.0" encoding="UTF-8"?>
<books><!--This is a test for dom4j, holen, 2004.9.11--><book show="yes"><title>Dom4j Tutorials</title></book><book show="yes"><title>Lucene Studing</title></book><book show="no"><title>Lucene in Action</title></book><owner>O'Reilly</owner>
</books>
1.8 解析XML文档
解析/创建都是基于dom4j实现
public static void main(String[] args) throws DocumentException {File file = new File("hello.xml");SAXReader sax = new SAXReader();Document doc = sax.read(file);Element rootElement = doc.getRootElement();String name = rootElement.getName();System.out.println("根节点="+name);//判断是否是根节点System.out.println(rootElement.isRootElement());Iterator it = rootElement.elementIterator();while(it.hasNext()){Element ele = (Element)it.next();String eleName = ele.getName();if(eleName.equals("book")){Attribute attribute = ele.attribute(0);System.out.println(attribute.getName()+"="+attribute.getValue());Iterator it2 = ele.elementIterator();while(it2.hasNext()){Element ele2 = (Element)it2.next();System.out.println(ele2.getName()+"="+ele2.getText());}}else{System.out.println(ele.getText());}}}
1.9 创建XML文档
public static void main(String[] args) throws IOException, XMLStreamException {Document document = DocumentHelper.createDocument();Element booksElement = document.addElement("books");booksElement.addComment("This is a test for dom4j, holen, 2004.9.11");Element bookElement = booksElement.addElement("book");bookElement.addAttribute("show","yes");Element titleElement = bookElement.addElement("title");titleElement.setText("Dom4j Tutorials");/** 类似的完成后两个book */bookElement = booksElement.addElement("book");bookElement.addAttribute("show","yes");titleElement = bookElement.addElement("title");titleElement.setText("Lucene Studing");bookElement = booksElement.addElement("book");bookElement.addAttribute("show","no");titleElement = bookElement.addElement("title");titleElement.setText("Lucene in Action");/** 加入owner节点 */Element ownerElement = booksElement.addElement("owner");ownerElement.setText("O'Reilly");//用于格式化xml内容和设置头部标签OutputFormat format = OutputFormat.createPrettyPrint();//设置xml文档的编码为utf-8format.setEncoding("utf-8");Writer out = new FileWriter("hello2.xml");XMLWriter writer = new XMLWriter(out,format);writer.write(document);writer.close();}
2. 反射
2.1 定义
1、对于给定的一个类(Class)对象,可以获得这个类(Class)对象的所有属性和方法;
2、对于给定的一个对象(new XXXClassName<? extends Object>),都能够调用它的任意一
个属性和方法。
这种动态获取类的内容以及动态调用对象的方法和获取属性的机制,就叫做Java反射机制
2.2 反射初识
public class User {public void eat(){System.out.println("---eat---");}
}
public class TestReflect{public static void main(String[] args) throws Exception {Class<User> clazz = User.class;//获取类对象对应的属性和方法System.out.println(clazz.getName());System.out.println(clazz.getPackage());System.out.println(clazz.getSuperclass());System.out.println(clazz.getClassLoader());//获取一个对象实例User user = clazz.newInstance();Method method = clazz.getDeclaredMethod("eat");method.invoke(user);}
2.3 为什么使用反射
实例化一个User()对象,不使用反射,如果想再实例化其他对象比如new Person(),那么
就需要修改源代码,并重新编译。使用反射后就不需要修改源代码只需要灵活改动类描述就
可以了,不需要重新再编译。 如下代码所示
//类描述,可根据需要实例化的描述而改动
String className = "com.tledu.pojo.User";
//使用反射中API创建对象
Class.forName(className).newInstance();
2.4 反射的优缺点
优点:
增加程序的灵活性,避免固有逻辑写死到程序中
代码相对简洁,可以提高程序的复用性
缺点:
相比于直接调用反射有比较大的性能销毁
内部暴露和安全隐患
2.4.1 灵活性测试
public interface Ball {void playBall();}public class BasketBall implements Ball{@Overridepublic void playBall() {System.out.println("打篮球");}}public class FootBall implements Ball{@Overridepublic void playBall() {System.out.println("踢足球");}}//----------------------------public static void main(String[] args) {//System.out.println(getInstanceByKey("basket"));System.out.println(getInstanceReflectByKey("FootBall"));}public static Ball getInstanceByKey(String key) {if("foot".equals(key)){return new FootBall();}if("basket".equals(key)){return new BasketBall();}return null;}
如果我们想在添加一个乒乓球那么除了创建一个乒乓球类,还需要在方法中加入获取乒乓球对应的判断和乒乓球创建对象的返回,很显然不够灵活出现了写死代码的情况。
public static Ball getInstanceReflectByKey(String key) {String basePackage = "com.tledu.mjw";Ball ball = null;try {Class clazz = Class.forName(basePackage + "." + key);ball = (Ball)clazz.newInstance();} catch (Exception e) {e.printStackTrace();}return ball;}
使用反射的方式获取对象,可以看出代码灵活了很多而且不需要改动创建返回对象的源码。
2.4.2 性能测试
public static void main(String[] args) {//System.out.println(getInstanceByKey("basket"));//System.out.println(getInstanceReflectByKey("FootBall"));long start = System.currentTimeMillis();for (int i = 0; i < 1000000; i++){getInstanceByKey("basket");//getInstanceReflectByKey("FootBall");}long end = System.currentTimeMillis();System.out.println("耗时:" + (end - start));}
2.5 反射的操作
2.5.1 获取类对象的四种方式
//获取类对象的四种方式
Class<User> clazz1 = User.class;
Class<?> clazz2 = Class.forName("com.tledu.mjw.User");
Class<? extends User> clazz3 = new User().getClass();
Class<?> clazz4 = Demo3.class.getClassLoader().loadClass("com.tledu.mjw.User");
2.5.2 类中基本信息的获取
System.out.println(clazz1.getClassLoader());
System.out.println(clazz1.getSuperclass());
System.out.println(clazz1.getPackage());
System.out.println(clazz1.getModifiers()); //获取类的修饰符
System.out.println(clazz1.getName());
System.out.println(clazz1.getSimpleName());
System.out.println(clazz1.getInterfaces().length);//获取类实现的所有接口
System.out.println(clazz1.getAnnotations().length);
2.5.3 类中字段的操作
创建User类继承Person类添加相应属性
public class Person {
public String idCard;
private String userName;
}
public class User extends Person{
private String name;
public String sex;
public static String address;
public void eat(){
System.out.println("---eat---");
}
}
2.5.4 测试方法调用
public static void main(String[] args) throws Exception {Class<User> userClass = User.class;User user = userClass.newInstance();//getFields()获取的是本类及父类中的公共属性Field[] fields = userClass.getFields();for (Field field : fields) {System.out.println(field.getModifiers() + " " + field.getName());}System.out.println("---------------");//getDeclaredFields()获取本类中的所有属性Field[] fields2 = userClass.getDeclaredFields();for (Field field : fields2) {System.out.println(field.getModifiers() + " " + field.getName());}System.out.println("---------------");//获取name字段对应的fieldField nameField = userClass.getDeclaredField("name");//如果需要修改私有属性信息那么我们要放开权限nameField.setAccessible(true);nameField.set(user,"天亮教育");System.out.println(nameField.get(user));//System.out.println(user.getName());System.out.println("---------------");//如何对静态的属性赋值Field addressField = userClass.getDeclaredField("address");addressField.set(null,"Jack");System.out.println(addressField.get(null));//System.out.println(User.address);}
2.5.5 类中方法的操作
在User类中将eat方法改为私有的,并添加静态方法say
private void eat(){
System.out.println("---eat---");
}
public static void say(String msg){
System.out.println(msg);
}
在Person类中添加共有的fn1()方法和私有的fn2()方法
public void fn1(){}
private void fn2(){}
2.5.6 测试方法调用
public static void main(String[] args) throws Exception {Class<User> userClass = User.class;User user = userClass.newInstance();//获取本类及父类中的公共方法Method[] methods1 = userClass.getMethods();for (Method method : methods1) {System.out.println(method.getModifiers() + " " + method.getName());}System.out.println("--------------");//获取本类中所有的方法包括私有Method[] methods2 = userClass.getDeclaredMethods();for (Method method : methods2) {System.out.println(method.getModifiers() + " " + method.getName());}System.out.println("--------------");//调用方法执行Method eatMethod = userClass.getDeclaredMethod("eat");//调用私有方法时要先开放权限eatMethod.setAccessible(true);eatMethod.invoke(user);System.out.println("--------------");//调用静态的方法Method sayMethod = userClass.getDeclaredMethod("say",String.class);sayMethod.invoke(null,"你好");}
2.5.7 类中构造器的操作
在User中添加如下构造方法
public User() {
}
public User(String name) {
this.name = name;
}
private User(String name,String sex) {
this.name = name;
this.sex = sex;
}
通过反射操作User中的构造方法
public static void main(String[] args) throws Exception {Class<User> userClass = User.class;//获取公共的构造器Constructor<?>[] constructors = userClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor.getModifiers() + " " + constructor.getName());}System.out.println("------------------");//获取所有的构造器Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor.getModifiers() + " " + declaredConstructor.getName());}//1、直接通过newInstance创建对象User user = userClass.newInstance();//2、获取对应的Constructor对象获取实例Constructor<User> constructor = userClass.getDeclaredConstructor(String.class, String.class);//操作私有的构造器要先打开权限constructor.setAccessible(true);User user1 = constructor.newInstance("乔森", "男");}
2.5.8 反射破局单例
单例模式
public class PersonSingle {
private static PersonSingle instance = null;
private PersonSingle(){}
public static PersonSingle getInstance(){
if(instance == null){
instance = new PersonSingle();
}
return instance;
}
}
测试单例、通过反射可以调用私有构造
public static void main(String[] args) throws Exception {
PersonSingle instance1 = PersonSingle.getInstance();
PersonSingle instance2 = PersonSingle.getInstance();
PersonSingle instance3 = PersonSingle.getInstance();
System.out.println(instance1);
System.out.println(instance2);
System.out.println(instance3);
System.out.println("---------------------");
Class<PersonSingle> personSingleClass = PersonSingle.class;
Constructor<PersonSingle> declaredConstructor = personSingleClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
System.out.println(declaredConstructor.newInstance());
}
改进单例如下
private PersonSingle(){
if(instance != null){
throw new RuntimeException("实例已经存在不允许再创建")
}
}
2.5.9 反射使用场景
1、jdbc封装
2、SpringIOC
3、JdbcTemplate
4、Mybatis
Day_52_Java高级相关推荐
- Redis 高级特性(4)— 单线程架构
Redis 使用了单线程架构和 I/O 多路复用模型来实现高性能的内存数据库服务. 1. 单线程模型 开启三个 redis-cli 客户端同时执行命令.客户端 1 设置一个字符串键值对: 127.0. ...
- Redis 高级特性(2)—— 发布 订阅模式
Redis 高级特性 -- 发布订阅 1. 发布-订阅介绍 "发布-订阅"模式包含两种角色,分别为发布者和订阅者.订阅者可以订阅一个或者若干个频道(channel),而发布者可以向 ...
- Redis 高级特性(1)—— 事务 过期时间 排序
1. Redis 高级特性 -- 事务 事务概念 Redis 中的事务 (transaction)是一组命令的集合.事务同命令一样是 Redis 的最小执行单位,一个事务中的命令要么都执行,要么都不执 ...
- 【JavaScript总结】JavaScript语法基础:JS高级语法
作用域链: 1.JS中只有函数能够限定作用域的范围: 2.变量处理在制定的函数范围内,还有一个特殊的作用域,就是没有用var 声明的全局作用域 3.js中的作用域链是为了清晰的表示出所有变量的作用范围 ...
- 高级教程: 作出动态决策和 Bi-LSTM CRF 重点
https://www.zhihu.com/question/35866596 条件随机场 CRF(条件随机场)与Viterbi(维特比)算法原理详解 https://blog.csdn.net/qq ...
- PyTorch 高级实战教程:基于 BI-LSTM CRF 实现命名实体识别和中文分词
20210607 https://blog.csdn.net/u011828281/article/details/81171066 前言:译者实测 PyTorch 代码非常简洁易懂,只需要将中文分词 ...
- Mobileye高级驾驶辅助系统(ADAS)
Mobileye高级驾驶辅助系统(ADAS) Mobileye is the global leader in the development of vision technology for Adv ...
- 一种新的高级抖动分离解析方法
一种新的高级抖动分离解析方法 A new analytic approach for advanced jitter separation 抖动分量的分析是现代通信系统调试中一项越来越重要的任务.一方 ...
- 2021年大数据Hadoop(九):HDFS的高级使用命令
2021大数据领域优质创作博客,带你从入门到精通,该博客每天更新,逐渐完善大数据各个知识体系的文章,帮助大家更高效学习. 有对大数据感兴趣的可以关注微信公众号:三帮大数据 目录 HDFS的高级使用命令 ...
最新文章
- Something needs to be forgotten.
- 替换SQL字段中的换行符,回车符
- 数据结构(7)—— 排序总结
- 图片在section上下居中_新媒体运营者关于图片使用的几大要点
- Hibernate之二级缓存
- phpcms模型缓存更新原理分析(转)
- java初级学习04
- 不使用软盘加载驱动安装系统的方法--使用nLite集成驱动
- Unix环境高级编程(十)信号续
- Day 5内存管理,定义变量
- oracle中job的retry次数,Oracle 19c注意事项: DBMS_JOB 行为变化
- qt 矩形连续移动_建筑案例:海门謇公湖农产品展销中心-咬合的连续曲面坡屋顶...
- 侦探小明:如何判断电脑里突然出现的流氓广告来自哪个软件?
- 使用Python横向合并excel文件的实例
- 这件小事,我坚持了 200 天
- 自定义View显示超大图片
- Bluetooth 5 新功能概述
- 数据抓包(网络爬虫)-正方教务管理系统登录
- android高德地图点平滑移动,【高德地图SDK】如何实现轨迹平滑移动?
- 耦合和解耦的概念解析!
热门文章
- 原生js实现带左右箭头可滑动的tab效果
- 如何计算折半查找的平均查找长度?
- GitHub前100第三方库及各大公司使用的第三方库
- 万博思图-HPLC数据可视化分析引擎
- Oracle gsd服务是什么,RAC节点服务ora.rac2.gsd的offline问题解决方法
- 麦肯锡发布端到端汽车软件平台报告
- luogu P4994 终于结束的起点
- python 逻辑回归,预测银行客户是否购买定期存款
- 微信新版本7.0.4,漂流瓶真的凉了......
- 配电室综合监测系统的组网与应用