时间:2019.08.16 作者:夏晓林 内容:反射注解和xml
//方式1:使用class属性
Class<Demo1> demo1Class = Demo1.class;
System.out.println(demo1Class.hashCode());
//方式2:使用getClass方法
Demo1 demo1=new Demo1();
Class<?> aClass = demo1.getClass();
System.out.println(aClass.hashCode());
//方式3 使用Class.forName方法:耦合性低,依赖类的全名称,即使没有类也能编译通过
Class<?> aClass1 = Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
System.out.println(aClass1.hashCode());
使用第三种方式,因为该方式可以在没有类的情况下进行编译而不会报错,耦合性低
扩展知识:获取父类、接口、包名
//获取父类
Class<?> superclass = aClass1.getSuperclass();
System.out.println(superclass.getName());//获取父类的名字
Type type = aClass1.getGenericSuperclass();//获取带泛型的类
System.out.println(type.getTypeName());
//获取接口
Class<?>[] interfaces = aClass1.getInterfaces();
System.out.println(interfaces.length);
//获取包名
Package aPackage = aClass1.getPackage();
System.out.println(aPackage.toString());
包括获取无参的和有参数的,利用构造方法创建对象
//获取构造方法
Class<?> clazz=Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
//获取单个构造方法
//无参数的构造方法
Constructor<?> constructor = clazz.getConstructor();
//获取带参数的
Constructor<?> constructor1 = clazz.getConstructor(String.class, int.class, String.class);
System.out.println(constructor1);
//利用构造方法创建对象
Object lisi = constructor.newInstance();
System.out.println(lisi);
Object xiayu = constructor1.newInstance("夏雨", 10, "男");
System.out.println(xiayu.toString());
Object o = clazz.newInstance();
System.out.println(o.toString());
获取无参数的、有参的、静态的、有返回值的、私有的(要将访问权限设置为无效,setAccessible(true))
public static void getMethod() throws Exception{
//获取无参的方法
Class<?> clazz = Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
//Method[] methods = clazz.getMethods();//公开的方法,还有继承的公开方法
/* Method[] methods = clazz.getDeclaredMethods();//获取类自己的所有方法,包括非公开的
System.out.println("-----Method----");
for (Method method : methods) {
System.out.println(method);
}*/
Object zhangsan = clazz.newInstance();
Method show = clazz.getMethod("show");
show.invoke(zhangsan);
//获取有参的方法
Method show1 = clazz.getMethod("show",String.class);
show1.invoke(zhangsan,"北京");
//带返回值的方法
Method getInfo = clazz.getMethod("getInfo");
Object invoke = getInfo.invoke(zhangsan);
System.out.println(invoke);
//静态方法
Method pring = clazz.getMethod("pring");
pring.invoke(null);
//私有方法
Method show2 = clazz.getDeclaredMethod("show", String.class, String.class);
//去掉修饰符,设置访问权限无效
show2.setAccessible(true);
show2.invoke(zhangsan,"北京","[email protected]");
}
public static void getField() throws Exception{
//获取类对象
Class<?> clazz = Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
Object lisi = clazz.newInstance();
//获取
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取单个
Field name = clazz.getDeclaredField("name");
//赋值
name.setAccessible(true);
name.set(lisi, "李四");
//获取
Object o = name.get(lisi);
System.out.println(o);
}
注解中的属性类型:
注解其实就是接口,编译后就是将@符号去掉,将属性变为接口的抽象方法
在一个注解中,如果只有一个属性并且名字为value,那么在调用的时候可以不用写value,如果不是该名字或者是多个属性的话,必须全写
@Retention:修饰注解的存活时间,默认class是在编译的时候存在,运行的时候消失;runtime是一直存在,source是只在代码中体现,编译的时候就没有了
RetentionPolicy.CLASS: 编译器将把注解记录在 class文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值
RetentionPolicy.RUNTIME:编译器将把注解记录在 class文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释
RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注释
@Inherited:是指该注解能够继承,子类可以获取到父类上的注解
@Target:指定注解用于修饰类的那个成员,@target包含了一个名字为value。类型为ElementType的成员变量。
@Documented:用于指定被该元 Annotation 修饰的Annotation类将被 javadoc 工具提取成文档。
可扩展性标记语言(eXtensible Markup Lanauage),文件扩展名为.xml
用途:描述、传输数据
使用场合:
文档声明
在编写XML文档时,需要先使用文档声明,声明XML文档的类型。
最简单的声明语法:
用encoding属性说明文档的字符编码:
元素
XML元素指XML文件中出现的标签,一个标签分为开始标签和结束标签,一个标签有如下几种书写形式,例如:
包含标签体:www.qianfeng.cn
不含标签体的:, 简写为:
一个标签中也可以嵌套若干子标签。但所有标签必须合理的嵌套,绝对不允许交叉嵌套 ,例如:
welcome to www.qianfeng.org
格式良好的XML文档必须有且仅有一个根标签,其它标签都是这个根标签的子孙标签。
对于XML标签中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理。例如:下面两段内容的意义是不一样的。
冰冰
和
冰冰
一个XML元素可以包含字母、数字以及其它一些可见字符,但必须遵守下面的一些规范:
1名称可以含字母、数字以及其他的字符
2名称不能以数字或者标点符号开始
3名称不能以字符 “xml”(或者 XML、Xml)开始
4名称不能包含空格
使用浏览器验证文件格式有效性。
属性
一个标签可以有多个属性,每个属性都有它自己的名称和取值,例如:
<Student name="zhangsan">
属性值一定要用双引号(")或单引号(')引起来
定义属性必须遵循与标签相同的命名规范
在XML技术中,标签属性所代表的信息,也可以被改成用子元素的形式来描述,例如:
<Student>
<name>text</name>
</Student>
注释
Xml文件中的注释采用:“” 格式。
注意:
1 XML声明之前不能有注释
2 注释不能嵌套
格式良好的XML文档
1必须有XML声明语句
2必须有且仅有一个根元素
3标签大小写敏感
4属性值用双引号或单引号
5标签成对
6元素正确嵌套
XML解析方式
◦1 DOM解析
使用DOM4J(DOM For Java)实现DOM解析
Java: JAXP技术
◦2 SAX解析(了解即可)
Pull解析和Sax类似
DOM和SAX比较
DOM解析 (Document Object Model) 文档对象模型
易用性强,使用DOM时,将把所有的XML文档信息都存于内存中,并且遍历简单,支持XPath,增强了易用性。
效率低,解析速度慢,内存占用量过高,对于大文件来说几乎不可能使用
支持增删改查
SAX解析(Simple API for Xml)
SAX是一个用于处理XML事件驱动的“推”模型,虽然它不是W3C标准,但它却是一个得到了广泛认可的API
SAX模型最大的优点是内存消耗小
只适合读取
Dom for java
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。
使用Dom4j开发,需下载Dom4j相应的jar文件
项目中如何使用DOM4J
(1)项目中创建文件夹lib
(2)把jar包复制到lib目录中
(3)右击jar包--->Add as library--->进行选择
如果第二次带入jar包,不能正常运行,此时不要再执行以上操作,直接关闭项目再打开即可
获取Document对象
SAXReader reader = new SAXReader();
Document document= reader.read(new File("input.xml"));
节点对象操作
1.获取文档的根节点.
Element root = document.getRootElement();
2.取得某个节点的子节点.
Element element=node.element(“书名");
3.取得节点的文字
String text=node.getText();
4.取得某节点下所有名为“member”的子节点,并进行遍历.
List nodes = rootElm.elements(“book");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
do something
}
节点属性操作
1.取得某节点下的某属性
Element root=document.getRootElement();
//属性名name
Attribute attribute=root.attribute("size");
2.取得属性的文字
String text=attribute.getText();
3.删除某属性
Attribute attribute=root.attribute("size");
root.remove(attribute);
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/*
* created by 夏晓林 in 2019/8/16/016 at 10:01
* 使用反射技术操作
* 1.获取类的对象
* 2.获取类中的构造方法
* 3.获取方法
*
*/
public class ReflectDemo1 {
public static void main(String[] args)throws Exception {
//getClazz();
//getConstructor();
//getMethod();
getField();
}
//获取类的对象
public static void getClazz() throws Exception{
//方式1:使用class属性
Class<Demo1> demo1Class = Demo1.class;
System.out.println(demo1Class.hashCode());
//方式2:使用getClass方法
Demo1 demo1=new Demo1();
Class<?> aClass = demo1.getClass();
System.out.println(aClass.hashCode());
//方式3 使用Class.forName方法:耦合性低,依赖类的全名称,即使没有类也能编译通过
Class<?> aClass1 = Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
System.out.println(aClass1.hashCode());
//扩展知识
//获取父类
Class<?> superclass = aClass1.getSuperclass();
System.out.println(superclass.getName());//获取父类的名字
Type type = aClass1.getGenericSuperclass();//获取带泛型的类
System.out.println(type.getTypeName());
//获取接口
Class<?>[] interfaces = aClass1.getInterfaces();
System.out.println(interfaces.length);
//获取包名
Package aPackage = aClass1.getPackage();
System.out.println(aPackage.toString());
}
public static void getConstructor() throws Exception{
//获取构造方法
Class<?> clazz=Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
//获取单个构造方法
//无参数的构造方法
Constructor<?> constructor = clazz.getConstructor();
//获取带参数的
Constructor<?> constructor1 = clazz.getConstructor(String.class, int.class, String.class);
System.out.println(constructor1);
//利用构造方法创建对象
Object lisi = constructor.newInstance();
System.out.println(lisi);
Object xiayu = constructor1.newInstance("夏雨", 10, "男");
System.out.println(xiayu.toString());
Object o = clazz.newInstance();
System.out.println(o.toString());
}
public static void getMethod() throws Exception{
//获取无参的方法
Class<?> clazz = Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
//Method[] methods = clazz.getMethods();//公开的方法,还有继承的公开方法
/* Method[] methods = clazz.getDeclaredMethods();//获取类自己的所有方法,包括非公开的
System.out.println("-----Method----");
for (Method method : methods) {
System.out.println(method);
}*/
Object zhangsan = clazz.newInstance();
Method show = clazz.getMethod("show");
show.invoke(zhangsan);
//获取有参的方法
Method show1 = clazz.getMethod("show",String.class);
show1.invoke(zhangsan,"北京");
//带返回值的方法
Method getInfo = clazz.getMethod("getInfo");
Object invoke = getInfo.invoke(zhangsan);
System.out.println(invoke);
//静态方法
Method pring = clazz.getMethod("pring");
pring.invoke(null);
//私有方法
Method show2 = clazz.getDeclaredMethod("show", String.class, String.class);
//去掉修饰符,设置访问权限无效
show2.setAccessible(true);
show2.invoke(zhangsan,"北京","[email protected]");
}
public static void getField() throws Exception{
//获取类对象
Class<?> clazz = Class.forName("com.qf1.fourth0816.reflectDemo.Demo1");
Object lisi = clazz.newInstance();
//获取
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取单个
Field name = clazz.getDeclaredField("name");
//赋值
name.setAccessible(true);
name.set(lisi, "李四");
//获取
Object o = name.get(lisi);
System.out.println(o);
}
}
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.List;
/*
* created by 夏晓林 in 2019/8/16/016 at 16:46
* 注意BOM头的问题,如果直接从记事本中复制到目录中,会出现前沿不允许有内容的错误
* 解决方法:直接写内容
*/
public class Demo2 {
public static void main(String[] args) throws Exception{
//readXML();
//writexml();
//updateAndDelete();
readXMLXPath();
}
//读取文件
public static void readXML() throws Exception{
//1.创建一个SaxReader读取器(类似流)
SAXReader reader =new SAXReader();
//2.读取,返回Document对象代表DOM树
Document document=reader.read(new FileReader("books.xml"));
//3.获取根节点
Element root = document.getRootElement();
//System.out.println(root);
//4.获取子节点
List<Element> book = root.elements("book");
//5.遍历
for (Element element : book) {
//System.out.println(element);
//获取id属性
String id = element.attributeValue("id");
//name
String name = element.elementText("name");
//author
String author = element.elementText("author");
//price
String price = element.elementText("price");
System.out.println(id+" "+name+" "+author+" "+price);
}
}
//写入文件
public static void writexml() throws Exception{
//创建SAXReader
SAXReader reader=new SAXReader();
Document document = reader.read(new FileReader("books.xml"));
Element root = document.getRootElement();
Element book = root.addElement("book");
//添加属性
book.addAttribute("id", "1003");
//添加子元素
book.addElement("name").setText("java葵花宝典");
book.addElement("author").setText("老叶");
book.addElement("price").setText("8.8");
//写入文件中
//创建一个输出格式
OutputFormat outputFormat=OutputFormat.createPrettyPrint();
outputFormat.setEncoding("utf-8");
//创建输出流
XMLWriter writer=new XMLWriter(new FileWriter("books.xml"),outputFormat);
//写入
writer.write(document);
//关闭
writer.close();
}
public static void updateAndDelete() throws Exception{
//创建SAXReader
SAXReader reader=new SAXReader();
Document document = reader.read(new FileReader("books.xml"));
Element root = document.getRootElement();
//更新
List<Element> book = root.elements("book");
Element first = book.get(0);
first.element("price").setText("99");
Element second = book.get(1);
second.element("price").setText("99");
//删除一个元素
Element element = book.get(book.size() - 1);
root.remove(element);
//写入文件
OutputFormat outputFormat=OutputFormat.createPrettyPrint();
outputFormat.setEncoding("utf-8");
//创建输出流
XMLWriter writer=new XMLWriter(new FileWriter("books.xml"),outputFormat);
//写入
writer.write(document);
writer.close();
}
//补充Xpath根据路径查找元素
public static void readXMLXPath() throws Exception {
SAXReader reader = new SAXReader();
//2.读取,返回Document对象代表DOM树
Document document = reader.read(new FileReader("books.xml"));
//使用XPath来查找
List<Node> nodes = document.selectNodes("/Books/book");
for (Node node : nodes) {
Element book=(Element)node;
System.out.println(book.attributeValue("id"));
System.out.println(book.elementText("name"));
System.out.println(book.elementText("author"));
System.out.println(book.elementText("price"));
}
}
}