反射和XML

反射和XML

第一节:反射(Reflection)
2.1 为什么使用反射
需求:
	我公司定义了一组接口,然后第三方公司按照我公司的接口实现了一套功能,然后交给我们,但是我们公司的项目已经结束,如何实现动态加载第三方公司提供的功能。
2.2 什么是反射
反射就是把Java类中的各种成分映射成一个个的Java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
2.3 反射常用类
  • Class类—可获取类和类的成员信息
  • Field类—可访问类的属性
  • Method类—可调用类的方法
  • Constructor类—可调用类的构造方法
2.4 使用反射的基本步骤

​ 1.导入java.lang.reflect.*

​ 2.获得需要操作的类的Java.lang.Class对象

​ 3.调用Class的方法获取Field、Method等对象

​ 4.使用反射API进行操作(设置属性﹑调用方法)

第二节:Class类
2.1 Class类是反射机制的起源和入口
  • 每个类都有自己的Class对象
  • 提供了获取类信息的相关方法
  • Class类继承自Object类
2.2 Class类存放类的结构信息
  • 类名
  • 父类﹑接口
  • 方法﹑构造方法﹑属性
  • 注释
2.3 获取 Class对象的方式

第一种方式

//方法1:对象.getClass()
Student stu=new Student();
Class clazz=stu.getClass();

第二种方式

//方法2:类.class
clazz= Student.class;
clazz=String.class;

第三种方式(推荐)

//方法3:Class.forName()
clazz=Class.forName("java.lang.String");
clazz=Class.forName("java.util.Date");
2.4 获取类的其他结构信息
Class clazz = Class.forName("java.lang.Object");
Field fields[ ] = clazz.getDeclaredFields();//获取Field 对象 
Method methods[] = clazz.getDeclaredMethods();//获取Method 对象 
Constructor constructors[] = clazz.getDeclaredConstructors();//获取Constructor对象 
2.5 动态创建对象

方法一:使用Class的newInstance()方法,仅适用于无参构造方法

Class clazz=Class.forName("com.qf.reflection.Student");
Object obj=clazz.newInstance();	

方法二:调用Constructor的newInstance()方法,适用所有构造方法

Constructor cons = clazz.getConstructor(new Class[]{ String.class,  int.class, float.class });
Object obj = cons.newInstance(new Object[ ] {"lkl", 32, 56.5f });
2.6 动态执行方法

调用方法基本步骤:

1.通过Class对象获取Method 对象

2.调用Method对象的invoke()方法

例如:

Object invoke(Object obj,Object [] args);
//object 返回值
//obj 当前方法所属对象
//args 当前方法的参数列表
2.7 反射动态操作属性值

操作属性的基本步骤

1.通过Class对象获取Field 对象

2.调用Field 对象的方法进行取值或赋值操作

方法说 明
Xxx getXxx(Object obj)获取基本类型的属性值
Object get(Object obj) )得到引用类型属性值
void setXxx(Object obj,Xxx val)将obj对象的该属性设置成val值
void set(Object obj,object val)将obj对象的该属性设置成val值
void setAccessible(boolean flag)对获取到的属性设置访问权限
第三节:反射技术的优点和缺点

优点:

​ 1.提高了Java程序的灵活性和扩展性,降低了耦合性,提高自适应能力

​ 2.允许程序创建和控制任何类的对象,无需提前硬编码目标类

缺点:

​ 1.性能问题

​ 2.代码维护问题

第四节:注解

注释:给代码添加说明和解释,注释帮助开发人员理解程序。(Comment)

注解:给代码添加说明,这个说明给程序使用。(Annotation)

从 JDK 5.0 开始,Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)。

三个基本的 Annotation:

​ @Override:限定重写父类方法, 该注解只能用于方法

​ @Deprecated:用于表示某个程序元素(类, 方法等)已过时

​ @SuppressWarnings: 抑制编译器警告.

什么是注解

​ Annotation其实就是代码里的特殊标记, 它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行。在Java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。

注解技术的要点:

​ 如何定义注解

​ 如何反射注解,并根据反射的注解信息,决定如何去运行类

2.1 自定义注解:

​ 定义新的 Annotation 类型使用@interface关键字

​ 声明注解的属性

注解属性的作用:原来写在配置文件中的信息,可以通过注解的属性进行描述。
Annotation的属性声明方式:String name();
属性默认值声明方式:Stringname() default “xxx”;
特殊属性value:如果注解中有一个名称value的属性,那么使用注解时可以省略value=部分,如@MyAnnotation(“xxx")
特殊属性value[];
注解属性的类型可以是:
    String类型
    基本数据类型
    Class类型
    枚举类型
    注解类型
    以上类型的一维数组

案例演示1 创建和使用注解

public @interface MyAnnocation {
	String name();
	int num() default 10;
	MyAnnocation2 anno();
}
public @interface MyAnnocation2 {
	String value();
}

public class Demo1 {
	@MyAnnocation(name="哈哈",num=50,anno=@MyAnnocation2(value = "xxx"))
	public void show() {
		System.out.println("xxxxxxx");
	}
}
2.2 JDK的元 Annotation

元 Annotation指修饰Annotation的Annotation。

@Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留的域, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 通过这个变量指定域。

RetentionPolicy.CLASS: 编译器将把注解记录在 class文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值
RetentionPolicy.RUNTIME:编译器将把注解记录在 class文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释
RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注释

@Target:指定注解用于修饰类的哪个成员.@Target 包含了一个名为value,类型为ElementType的成员变量。

@Documented:用于指定被该元 Annotation 修饰的Annotation类将被 javadoc 工具提取成文档。

@Inherited:被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的Annotation,则其子类将自动具有该注解。

案例演示2 使用反射获取注解信息

@Retention(RetentionPolicy.RUNTIME)
public @interface PersonInfo {
	String name();
	int age() default 20;
	String gender();
}

public class PersonOpe {
	@PersonInfo(name="李四",age=20,gender="男")
	public void show(String name,int age,String gen) {
		System.out.println(name);
		System.out.println(age);
		System.out.println(gen);
	}
}
public class Demo2 {
	public static void main(String[] args) throws Exception{
		PersonOpe ope=new PersonOpe();
		Class<?> class1=PersonOpe.class;
		Method method = class1.getMethod("show", String.class,int.class,String.class);
		PersonInfo annotation = method.getAnnotation(PersonInfo.class);
		String name=annotation.name();
		int age=annotation.age();
		String gender=annotation.gender();
		method.invoke(ope, name,age,gender);
		
	}
}
第五节:XML语言
5.1为什么使用XML

问题1:Windows系统的应用怎么和Linux系统中的应用交互数据

问题2:其它诸如此类跨平台、跨操作系统的数据交互问题……

使用XML解决。

5.2XML概述

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

用途:描述、传输数据

使用场合:

​ ◦持久化存储数据

​ ◦数据交换

​ ◦数据配置

示例:persons.xml

<?xml version="1.0" encoding="utf-8" ?>
<Person>
    <ID>1002</ID>
    <Name>曹操</Name>
    <Age>20</Age>
    <!--注释 -->
    <ID>1001</ID>
    <Name>周瑜</Name>
    <Age>22</Age>
</Person>
5.3XML语法

文档声明

在编写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包--->build path--->add to build path

获取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);
案例1 读取xml文件
public static void readxml() throws Exception{
		//1创建SaxReader
		SAXReader reader=new SAXReader();
		//2获取Document对象
		Document document=reader.read(new FileReader("src\\books2.xml"));
		//3获取根节点
		Element root=document.getRootElement();//books
		//System.out.println(root.getName());
		//4获取book集合
		List<Element> bookList=root.elements("book");
		for (Element b : bookList) {
			//System.out.println(b.getName());
			//5获取属性
			String id=b.attributeValue("id");
			String name=b.element("name").getText();
			String author=b.element("author").getText();
			String price=b.elementText("price");
			Book book=new Book(Integer.parseInt(id), name, author, Double.parseDouble(price));
			System.out.println(book.toString());
		}
	}
案例2 写入XML文件
//2写入xml文件
	
	public static void writeXml() throws Exception{
		//1 创建SaxReader
		SAXReader reader=new SAXReader();
		//2读取
		Document document=reader.read(new FileReader("src\\books2.xml"));
		//3获取根节点
		Element root = document.getRootElement();
		//4添加节点
		Element newbook = root.addElement("book");
		//5添加属性
		newbook.addAttribute("id","1003");
		//6newbook添加name author price
		newbook.addElement("name").setText("android开发");;
		newbook.addElement("author").setText("老张");;
		newbook.addElement("price").setText("88.8");;
		
		//7写入文件中
		OutputFormat format=OutputFormat.createPrettyPrint();//创建一个漂亮的输出格式
		format.setEncoding("utf-8");
		XMLWriter writer=new XMLWriter(new FileWriter("src\\books2.xml"), format);
		writer.write(document);
		writer.close();
		System.out.println("写入成功");
		
	}
案例3 修改和删除xml文件
//3 修改和删除xml文件内容
	
	public static void updateXml() throws Exception{
		//1创建Xmlreader
		SAXReader reader=new SAXReader();
		//2文档
		Document document = reader.read(new FileReader("src\\books2.xml"));
		//3获取根节点
		Element root = document.getRootElement();
		
		
		//4获取id=1003的book
		List<Element> elements = root.elements("book");
		Element bookEle = elements.get(2);
		bookEle.element("name").setText("android从入门到大神");
		Element first =elements.get(0);
		//5删除
		root.remove(first);
		
		//6写入
		OutputFormat format=OutputFormat.createPrettyPrint();
		format.setEncoding("utf-8");
		XMLWriter writer=new XMLWriter(new FileWriter("src\\books2.xml"), format);
		writer.write(document);
		writer.close();
		
		System.out.println("修改删除完毕");
	}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值