反射和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.*html

​ 2.得到須要操做的類的Java.lang.Class對象java

​ 3.調用Class的方法獲取Field、Method等對象node

​ 4.使用反射API進行操做(設置屬性﹑調用方法)android

第二節: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

相關文章
相關標籤/搜索