• 反射和XML


    反射和XML

    回顾:

    1  NIO简介  Java Non-blocking IO   New IO
    
    2 和传统IO   
    
    	(1) 面向流 ,面向缓冲区
    
    	(2) 阻塞,   非阻塞
    
    	(3)  无      选择器(selector)
    
    3 NIO  
    
    	Buffer:ByteBuffer CharBuffer
    
    	Channel:FileChannel、ServerSocketChannel  、SocketChannel
    
    	Selector:选择器、轮询器
    
    4  Buffer 
    
    	ByteBuffer
    
    	CharBuffer
    
    	ShortBuffer
    
    	....
    
    	重要属性 
    
    	0<=mark<=postion<=limit<=capacity
    
    	put();//放入数据
    
    	get();//获取数据
    
    	flip();//切换为读模式
    
    	rewind()//可以重复
    
    	mark();//做标记
    
    	reset();//返回上一个标记
    
    	clear()//清空, 
    
    	compact();//清空,会保留未读取的数据
    
    	间接缓冲区:  堆中,空间不大,速度慢,jvm可以回收
    
    	直接缓冲区: 物理内存(虚拟内存)中,空间大,速度块,jvm不能回收。
    
    
    5 Channel
    
    	FileChannel
    		InputStream OutputStream RandomAcceFile的getChannle();
    		FileChannel.open();
    	ServerSocketChannel
    	SocketChannel
    
    6 Selector:选择器(轮询器)
    
    JUC  java.util.concurrent;
    volitale :易变,不稳定
    	(1)内存可见性
    	(2)禁止指令重排序
    	
    并发编程中三个特性:
    	(1)互斥性(原子性)
    	 (2) 可见性
    	 (3) 禁止指令重排序
    synchronized:
    	 (1)互斥性
    	 (2)可见性
    原子变量: i++	 
    	AtomicInteger
    	CAS (Compare And Swap)使用cpu的特殊的指令
    Lock 接口
    	Lock lock=new ReentrantLock();
    	lock.lock();
    	try{
          	
    	}finally{
          lock.unlock();
    	}
    	Condition:条件(队列)
    	交替输出20遍  ABC
    	
    并发集合
    	CopyOnWriteArrayList  有序,可以重复
    	CopyOnWriteArraySet  有序,不能重复
    	ConcurrentHashMap:无序,键不能重复
    		JDK1.7: 分段锁机制(Segment 16段)  写入时互斥(段中) ,读取时共享  ,存储结构 数组+链表
    		JDK1.8: 采用CAS算法 如果hash位置没有元素,使用cas放入,如果有元素把第一个节点锁住,存储结构:
    			    数组+链表+红黑树
    	ArrayBlockingQueue:有界阻塞队列:同步容器
        	实现生产者消费者
     同步工具类
     	CountDownLatch:闭锁,实现当多个线程执行完后,才继续执行阻塞线程
     	CyclicBarrier:屏障,实现当多个同时到达后,然后一起执行
     	Semaphore:信号量,控制并发的线程个数.
    			    
    	
    
    

    今天任务

    1.反射
    2.注解
    3.XML语言
    4.解析XML
    

    教学目标

    1.掌握反射
    2.掌握注解
    3.了解XML语言
    4.掌握如何解析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 });
    

    练习一:

    1 定义Student类,包含:姓名和年龄等属性,有参和无参构造方法,输出所有信息的方法

    2 使用多种方法生成一个Student类的Class对象

    3 使用Class类获取Student类的属性并输出

    4 通过有参(无参)构造方法动态创建Student类的对象

    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文件描述学生信息

    Student( 学号stuNo, 姓名 name, 年龄 age, 班级 clazz )

    第六节:XML解析

    XML解析方式

    ◦1 DOM解析

    ​ 1.1 使用DOM4J(DOM For Java)实现DOM解析

    ​ 1.2 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是一个简单、灵活的开放源代码的库。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("修改删除完毕");
    	}
    

    总结:

    1 反射:其实java中一种解剖技术,获取类中的属性、方法、构造方法等信息

    2 获取类的类对象

     1》创建对象,调用对象的getClass()方法
    

    ​ 2》类名.class属性

    ​ 3》 Class.forName("类的全名称");

    3 获取构造方法

    Constructor[] cs= class1.getConstructors();

    Constructor c2= class1.getConstructor(String.class,int.class,String.class);

    c2.newInstance("xxx",20,"男");

    4 获取方法

    class1.getMethods();

    Method method= class1.getMethod(“show”);

    method.invoke(obj);

    5 获取属性

    Field nameField=class1.getDeclaredField("name");

    nameField.setAccessable(true);

    nameField.set(obj,"xxx");

    nameFiled.get(obj);

    6 XML 可扩展标记语言

    用途:描述 传输数据

    使用场合: 持久化数据

    ​ 传输数据

    ​ 配置文件

    语法 :

    ​ 声明

    ​ 标签

    ​ 属性

    ​ 注释

    格式良好的文档 :

    ​ 1 必须有声明

    ​ 2 标签区分大小写

    ​ 3 有且只有一个根节点

    4 属性值用双引号和单引号

    5 成对出现

    6 正确嵌套

    xml解析

    DOM解析(Document Object Model)

    ​ 创建DOm树,易于操作,遍历 、删除、修改、写入

    ​ 内存大

    Sax解析 (Simple API for XML)

    ​ Sax只能读取文件 ,不能删除 修改

    ​ 内存小

    DOM4J (four for)

    默写:

    1获取类对象的三种方式

    作业:

    1 设计一个Student类,属性有:id,name,age,borndate,使用反射创建对象。

    2 使用反射调用方法show显示学生信息。

    3 使用反射调用name属性。

    面试题:

    1 简述Java中的反射使用

    2 JAVA常用反射API

  • 相关阅读:
    shell if 条件语句实践
    shell函数
    透视财富增长的秘密
    kvm虚拟化实践
    Linux驱动编程--基于I2C子系统的I2C驱动
    Makefile中=、:=、+=、?=的区别
    字符设备驱动结构与开发
    驱动分类
    为什么ARM的frq中断的处理速度比较快
    Linux设备驱动01
  • 原文地址:https://www.cnblogs.com/Zzzxb/p/11397166.html
Copyright © 2020-2023  润新知