反射 注解 XML总结

Posted 夏芷雨涵梦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射 注解 XML总结相关的知识,希望对你有一定的参考价值。

反射 注解 XML

时间:2019.08.16 作者:夏晓林 内容:反射注解和xml

反射技术的操作:

  • 获取类的对象
  • 获取类中的构造方法
  • 获取类中的方法
  • 获取类中的属性
获取类的对象:
  • 使用class属性:Person.class
  • 使用getClass()方法:person.getClass()
  • 使用Class.forName():括号里是完整的包名和类名。
//方式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,"北京","2342343@qq.com");
    
获取类的属性(一般不建议使用,违反了封装的特性,框架中会使用)
 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);
    

注解:

注解中的属性类型:

  • String类型
  • 基本类型
  • class类型
  • 枚举类型
  • 注解类型
  • 或者以上类型的一维数组

注解其实就是接口,编译后就是将@符号去掉,将属性变为接口的抽象方法

在一个注解中,如果只有一个属性并且名字为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 工具提取成文档。

XML语言

为什么使用xml语言
  1. 问题1:Windows系统的应用怎么和Linux系统中的应用交互数据
  2. 问题2:其他诸如此类跨平台、跨操作系统的数据交互问题
xml的概述

可扩展性标记语言(eXtensible Markup Lanauage),文件扩展名为.xml

用途:描述、传输数据

使用场合:

  • 持久化存储数据
  • 数据交换
  • 数据配置
xml语法

文档声明

在编写XML文档时,需要先使用文档声明,声明XML文档的类型。
最简单的声明语法:
	<?xml version="1.0" ?>

用encoding属性说明文档的字符编码:

	<?xml version="1.0" encoding="GBK" ?>  

元素

XML元素指XML文件中出现的标签,一个标签分为开始标签和结束标签,一个标签有如下几种书写形式,例如:
	包含标签体:<a>www.qianfeng.cn</a>
	不含标签体的:<a></a>, 简写为:<a/>
一个标签中也可以嵌套若干子标签。但所有标签必须合理的嵌套,绝对不允许交叉嵌套 ,例如:
	<a>welcome to <b>www.qianfeng.org</a></b>
格式良好的XML文档必须有且仅有一个根标签,其它标签都是这个根标签的子孙标签。 
对于XML标签中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理。例如:下面两段内容的意义是不一样的。
<Name>
	冰冰
</Name>
和
<Name>冰冰</Name>
一个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解析

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模型最大的优点是内存消耗小
	只适合读取
6.1使用DOM4J解析
	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,"北京","2342343@qq.com");
    
    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"));

以上是关于反射 注解 XML总结的主要内容,如果未能解决你的问题,请参考以下文章

这些简单的Spring Bean注入方式,你都会吗?

注解+反射+递归动态生成多层XML

Java反射学习总结五(Annotation(注解)-基础篇)

Java反射学习总结五(Annotation(注解)-基础篇)

认识和总结反射

java 通过反射获取注解