java-基礎

2019.05.08javascript

1.面向對象的內存分析html

  java虛擬機的內存能夠分爲三個區域:棧stack、堆heap、方法區method areajava

  (1)棧的特色以下:mysql

    1.棧描述的是方法執行的內存模型。每一個方法被調用都會建立一個棧幀(存儲局部變量、操做數、方法出口等)。程序員

    2.JVM爲每一個線程建立一個棧,用於存放該線程執行方法的信息(實際參數、局部變量等)。sql

    3.棧屬於線程私有,不能實現線程間的共享。數據庫

    4.棧的存儲特性是「先進後出,後進先出」。編程

    5.棧由系統自動分配,速度快,是一個連續的內存空間。api

  (2)堆的特色以下:數組

    1.堆用於存儲建立好的對象和數組(數組也是對象)。

    2.JVM只有一個堆,被全部線程共享。

    3.堆是一個不連續的內存空間,分配靈活,速度慢。·  

  (3)方法區(又叫靜態區)特色以下:

    1.JVM只有一個方法區,被全部線程共享。

    2.方法區實際也是堆,只是用於存儲類、常量相關的信息。

    3.用來存放程序中永遠不變或惟一的內容。(類信息【class對象】、靜態變量、字符串常量等)。

    內存分析

2.建立一個對象分爲以下四步:

  (1)分配對象空間,並將對象成員變量初始化爲0或空。

  (2)執行屬性值的顯式初始化

  (3)執行構造方法

  (4)返回對象的地址給相關的變量

3.this關鍵字

  this的本質就是「建立好的對象的地址」因爲在構造方法調用前,對象已經建立。所以,在構造方法中也可使用this表明「當前對象」。

4.static關鍵字

  在類中,用static聲明的成員變量爲靜態成員變量,也稱爲類變量。類變量的生命週期和類相同,在整個應用程序執行期間都有效。

5.重寫與重載

6.構造方法調用順序

  構造方法第一句老是:super(...)來調用父類對應的構造方法。因此流程就是:先向上追溯到Object,而後再依次向下執行類的初始化塊和構造方法,直到當前子類位置。

  靜態初始化塊調用順序,與構造方法調用順序同樣。

7.多態

  多態指的是同一個方法調用,因爲對象不一樣可能會有不一樣的行爲。現實生活中,同一個方法,具體實現會徹底不一樣。

  多態的要點:

    (1)多態是方法的多態,不是屬性的多態(多態與屬性無關)

    (2)多態的存在要有三個必要條件:繼承、方法重寫、父類引用指向子類對象。

    (3)父類引用指向子類對象後,用該父類引用調用子類重寫的方法

8.final關鍵字

 

2019.05.09

1.抽象類

  (1)使用要點:

    有抽象方法的類只能定義成抽象類

    抽象類不能實例化,即不能new來實例化抽象類

    抽象類能夠包含屬性、方法、構造方法。但構造方法不能用來new實例,只能用來被子類調用

    抽象類只能用來被繼承

    抽象方法必須被子類實現

  (2)相關規定

    抽象類也提供構造方法,而且子類也遵循對象實例化流程:先調用父類構造方法,再調用子類構造方法

    抽象類中能夠不定義抽象方法,但仍然沒法直接實例化對象

    abstract與final、private不能一塊兒使用:

      final聲明的類不容許有子類,而abstract抽象類必須有子類

      抽象方法必需要被重寫,所以不能用private封裝

    抽象類也分爲內部抽象類和外部抽象類:內部抽象類容許使用static

 2.接口

  (1)詳細說明

    訪問修飾符:只能是public或默認

    接口名:和類名採用相同命名機制

    extends:接口能夠多繼承

    常量:接口中的屬性只能是常量,老是:public static final修飾

    方法:接口中的方法只能是:public abstract

  (2)要點

    子類經過implements來實現接口中的規範

    接口不能建立實例,可是可用聲明引用變量類型

    一個類實現了接口,必須實現接口中全部的方法,而且這些方法只能是public的

    JDK1.7以前,接口中只能包含靜態常量、抽象方法,不能有普通屬性、構造方法、普通方法

    JDK1.8後,接口包含普通的靜態方法  

3.非靜態內部類

  (1)非靜態內部類必須寄存在一個外部類對象裏,所以,若是有一個非靜態內部類對象那麼必定存在對應的外部類對象,非靜態內部類對象單獨屬於外部類的某個對象。

  (2)非靜態內部類能夠直接訪問外部類的成員,可是外部類不能直接訪問非靜態內部類成員

  (3)非靜態內部類不能有靜態方法,靜態屬性和靜態初始化塊

  (4)外部類的靜態方法,靜態代碼塊不能訪非靜態內部類,包括不能使用非靜態內部類定義變量,建立實例。why:非靜態內部類依託於外部類對象

  (5)成員變量訪問要點:

      內部類裏方法的局部變量:變量名

      內部類屬性:this.變量名

      外部類屬性:外部類名.this.變量名

4.靜態內部類(不依託外部類對象)

  (1)當一個靜態內部類對象存在,並不必定存在對應的外部類對象。所以,靜態內部類的實例方法不能直接訪問外部類的實例方法

  (2)靜態內部類看作外部類的一個靜態成員。所以,外部類的方法中能夠經過:靜態內部類.名字的方式訪問靜態內部類的靜態成員,經過new靜態內部類()訪問靜態內部類的實例。

5.匿名內部類

  適合只須要使用一次的類。好比:鍵盤監聽操做等等

interface  AA {
    void  aa();
}

public class TestAnonymousInnerClass {
    
    public static  void  test01(AA a){
        a.aa();
    }
    
    public static void main(String[] args) {
        TestAnonymousInnerClass.test01(new AA(){

            @Override
            public void aa() {
                System.out.println("TestAnonymousInnerClass.main(...).new AA() {...}.aa()");
            }   
        }); 
    }
}

6.方法內部類

  方法內部類定義在方法內部,做用域只限於方法,稱爲局部內部類

 

2019.05.10

1.包裝類

  java是面嚮對象語言,但並非「純面向對象」的,由於咱們常常用到的基本數據類型就不是對象,可是咱們在實際應用中常常須要將基本數據轉化成對象,以便於操做。好比:將基本數據類型存儲到Object[]數組或集合中的操做等等。

  爲了解決這個不足,java在設計類時爲每一個基本數據類型設計了一個對應的類進行表明,這樣八個和基本數據類型對應的類統稱爲包裝類。

基本數據類型 包裝類
byte Byte
boolean Boolean
short

Short

char Character
int Integer
long Long
float Float
double

Double

 

相互轉化:

public class TestWrappedClass {
    public static void main(String[] args) {
        //基本數據類型轉成包裝類對象
        Integer   a  = new  Integer(3);
        Integer   b  = Integer.valueOf(30);   

        //把包裝類對象轉成基本數據類型
        int   c  =  b.intValue();
        double d = b.doubleValue();
        
        //把字符串轉成包裝類對象
        Integer  e = new  Integer("9999");
        Integer  f = Integer.parseInt("999888");
        
        //把包裝類對象轉成字符串
        String   str = f.toString();    //""+f
        
        //常見的常量
        System.out.println("int類型最大的整數:"+Integer.MAX_VALUE);
        
    }
}

2.自動裝箱、自動拆箱

  自動裝箱和拆箱就是編譯器將基本數據類型和包裝類之間進行自動的互相轉換(JDK1.5之後)

public class TestAutoBox {
    public static void main(String[] args) {
        Integer   a  = 234;   //自動裝箱。Integer  a = Integer.valueOf(234);
        int   b =  a;         //自動拆箱。編譯器會修改爲:int  b = a.intValue();
        
        Integer  c = null; 
        if(c!=null){
            int  d = c;            //自動拆箱:調用了:c.intValue()
        }
    }
}

3.可變字符序列:StringBuilder、StringBuffer

  StringBuilder:線程不安全效率高

  StringBuffer:線程安全效率低

  函數使用:api

4.時間相關類

  在計算機世界,咱們把1970年1月1日00:00:00定未基準時間,每一個度量單位是毫秒

  得到當前時刻的毫秒數:System.currentTimeMillis();

  (1)Date類

    Date()對象表示一個特定的瞬間,精確到毫秒

  (2)DateFormat類和SimpleDateFormat類

    DateFormat類的做用把時間對象轉化爲指定格式的字符串。反之,把指定格式的字符串轉化爲時間對象。

    DateFormat是一個抽象類,通常使用它的子類SimpleDateFormat類來實現

/**
 * 測試時間對象和字符串之間的互相轉換
 * DateFormat抽象類和SimpleDateFormat實現類的使用
 * @author Ma
 *
 */
public class TestDateFormat {
    public static void main(String[] args) throws ParseException {
        
        //把時間對象按照「格式字符串指定的格式」轉成相應的字符串
        DateFormat  df  = new SimpleDateFormat("yyyy-MM-dd  hh:mm:ss");
        String str  =  df.format(new Date(4000000)); 
        System.out.println(str);
        
        //把字符串按照「格式字符串指定的格式」轉成相應的時間對象
        DateFormat  df2 = new SimpleDateFormat("yyyy年MM月dd日 hh時mm分ss秒");
        
        Date  date = df2.parse("1983年5月10日 10時45分59秒");
        System.out.println(date);
        
        //測試其餘的格式字符。好比:利用D,得到本時間對象是所處年份的第幾天。
        DateFormat  df3  = new SimpleDateFormat("D");
        String str3  =  df3.format(new Date()); 
        System.out.println(str3);
        
    }
}

   (3)Calendar日曆類

    Calendar類是一個抽象類,爲咱們提供了關於日期計算的相關功能。好比:年、月、日、時、分、秒的展現和計算。

    GregorianCalendar是Calendar的一個具體子類,提供了世界上大多數國家/地區使用的標準日曆系統。

/**
 * 測試日期類的使用
 * @author Ma
 *
 */
public class TestCanlendar {
    public static void main(String[] args) {
        //得到日期的相關元素
        Calendar calendar = new GregorianCalendar(2999,10,9,22,10,50);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int  day = calendar.get(Calendar.DATE);        //也可使用:DAY_OF_MONTH。
        int weekday = calendar.get(Calendar.DAY_OF_WEEK);    //星期幾。 1-7.  1:星期日,2星期一,。。。7是星期六。 
        System.out.println(year) ;
        System.out.println(month) ;    //0-11表示對應的月份。0是1月,1月是2月.....11是12月。
        System.out.println(weekday);
        System.out.println(day);
        
        //設置日期的相關元素
        Calendar c2 = new GregorianCalendar();
        c2.set(Calendar.YEAR, 8012);
        
        System.out.println(c2);
        
        //日期的計算
        Calendar c3 = new GregorianCalendar();
        c3.add(Calendar.YEAR, -100);
        System.out.println(c3) ;
        
        //日期對象和時間對象的轉化
        Date  d4 =  c3.getTime();
        Calendar c4 = new GregorianCalendar();
        c4.setTime(new Date());
        
        printCalendar(c4); 
    }
    
    public static  void  printCalendar(Calendar  c){
        //打印:1918年10月10日 11:23:45 週三
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;   //0-11
        int  date = c.get(Calendar.DAY_OF_MONTH);
        int  dayweek  = c.get(Calendar.DAY_OF_WEEK)-1;    //1-7.1週日,2周1,3周2....
        String dayweek2 = dayweek==0?"日":dayweek+"";
        
        int hour = c.get(Calendar.HOUR);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        
        System.out.println(year+"年"+month+"月"+date+"日 "+hour+"時"+minute+"分"+second+"秒"
                +"   周"+dayweek2);
    }
}

5.Math類

經常使用方法:

public class TestMath {
    public static void main(String[] args) {
        //取整相關操做
        System.out.println(Math.ceil(3.2));
        System.out.println(Math.floor(3.2));
        System.out.println(Math.round(3.2));
        System.out.println(Math.round(3.8));
        //絕對值、開方、a的b次冪等操做
        System.out.println(Math.abs(-45));
        System.out.println(Math.sqrt(64));
        System.out.println(Math.pow(5, 2));
        System.out.println(Math.pow(2, 5));
        //Math類中經常使用的常量
        System.out.println(Math.PI);
        System.out.println(Math.E);
        //隨機數
        System.out.println(Math.random());// [0,1)
    }
}
public class TestRandom {
    public static void main(String[] args) {
        Random rand = new Random();
        //隨機生成[0,1)之間的double類型的數據
        System.out.println(rand.nextDouble());
        //隨機生成int類型容許範圍以內的整型數據
        System.out.println(rand.nextInt());
        //隨機生成[0,1)之間的float類型的數據
        System.out.println(rand.nextFloat());
        //隨機生成false或者true
        System.out.println(rand.nextBoolean());
        //隨機生成[0,10)之間的int類型的數據
        System.out.println(rand.nextInt(10));
        //隨機生成[20,30)之間的int類型的數據
        System.out.println(20 + rand.nextInt(10));
        //隨機生成[20,30)之間的int類型的數據(此種方法計算較爲複雜)
        System.out.print(20 + (int) (rand.nextDouble() * 10));
    }
}

 6.File類

/**
 * 測試File類的基本用法
 * @author Ma
 *
 */
public class TestFile {
    
    public static void main(String[] args) throws IOException {
        
//      File  f = new File("d:/a.txt");
        File  f = new File("d:\\a.txt");
        System.out.println(f); 
        f.renameTo(new File("d:/bb.txt"));
        
        
        File  f2 = new File("d:/gg.txt");        
        f2.createNewFile(); //d盤下生成gg.txt文件
        f2.delete();    //將該文件或目錄從硬盤上刪除
        
        
        System.out.println("File是否存在:"+f2.exists());
        System.out.println("File是不是目錄:"+f2.isDirectory());
        System.out.println("File是不是文件:"+f2.isFile());
        System.out.println("File最後修改時間:"+new Date(f2.lastModified()));
        System.out.println("File的大小:"+f2.length());
        System.out.println("File的文件名:"+f2.getName());
        System.out.println("File的目錄路徑:"+f2.getAbsolutePath());
        
        
        File f3 = new File("d:/電影/華語/大陸");
        boolean flag = f3.mkdir(); //目錄結構中有一個不存在,則不會建立整個目錄樹
        boolean flag = f3.mkdirs();//目錄結構中有一個不存在也不要緊;建立整個目錄樹
        System.out.println(flag);//建立失敗        
    }
}

 7.異常

(1)RuntimeException子類

方法名 說明
Exception 異常層次結構的跟類
ArithmeticException  算術條件異常。好比:整數除零等。
ArrayIndexOutOfBoundsException 數組索引越界異常。當對數組的索引值爲負數或大於等於數組大小時拋出
SecurityException 安全性異常
NullPointerException  嘗試訪問 null 對象成員
ClassNotFoundException  不能加載所需的類 
InputMismatchException  欲獲得數據類型與實際輸入類型不匹配
IllegalArgumentException  方法接收到非法參數
ClassCastException 對象強制類型轉換出錯
NumberFormatException  數字格式轉換異常,如把"ab"轉換成數字

(2)IOException

方法名 說明
IOException 操做輸入流和輸出流時可能出現的異常
EOFException 文件已結束異常
FileNotFoundException 文件未找到異常

 

(3)其餘

方法名 說明
ClassCastException 類型轉換異常類
ArrayStoreException 數組中包含不兼容的值拋出的異常
SQLException 操做數據庫異常類
NoSuchFieldException 字段未找到異常
NoSuchMethodException 方法未找到拋出的異常
NumberFormatException 字符串轉換爲數字拋出的異常
StringIndexOutOfBoundsException 字符串索引超出範圍拋出的異常
IllegalAccessException 不容許訪問某類異常
InstantiationException 當應用程序試圖使用Class類中的newInstance()方法建立

一個類的實例,而指定的類對象沒法被實例化時,拋出該異常

 

8.泛型

  泛型的本質就是「數據類型的參數化」。咱們能夠把「泛型」理解爲數據類型的一個佔位符(形式參數),即告訴編譯器,在調用泛型時必須傳入實際類型。

  咱們能夠在類的聲明出增長泛型列表,如:<T,E,V>

/**
 * 測試泛型
 * @author Ma
 */
public class TestGeneric {
    public static void main(String[] args) {
        
        MyCollection<String>  mc= new MyCollection<String>(); 
        mc.set("Ma", 0);
        String   b = mc.get(0);
    }
}

class  MyCollection<E> {  //E:表示泛型
    Object[]  objs = new Object[5];
    
    public  void  set(E e, int index){
        objs[index] = e;
    }
    
    public  E  get(int index){
        return  (E) objs[index];
    }
    
}

 9.容器(集合)

(1)Collection接口

  Collection存儲一組不惟1、無序的對象,它的兩個子接口是List、Set

Collection接口中定義的方法:

方法 說明
boolean add(Object element) 增長元素到容器中
boolean remove(Object element) 從容器中移除元素
boolean contains(Object element) 容器中是否包含該元素
int size() 容器中元素的數量
boolean isEmpty() 容器是否爲空
void clear() 清空容器中全部元素
Iterator iterator() 得到迭代器,用於遍歷全部元素
boolean containAll(Collection c) 本容器是否包含c容器中全部的元素
boolean addAll(Collection c) 將容器c中全部元素增長到本容器
boolean removeAll(Collection c) 移除本容器和容器c中都包含的元素
boolean retainAll(Collection c) 取本容器和容器c中都包含的元素,移除非交集元素
Object[] toArray() 轉化成Object數組

 

(2)List接口

  • List是有序、可重複的容器

    有序:List中每一個元素都有索引標記。能夠根據元素的索引標記(在List中的位置)訪問元素,從而精確控制這些元素。

    可重複:List容許加入重複的元素。

  • List接口經常使用地實現類有3個:ArrayList、LinkedList和Vector
  • List相對CollectIon增長了關於位置操做的方法
public static  void  test(){
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        
        System.out.println(list);
        
        list.add(2,"ma");  //添加
        System.out.println(list);
        
        list.remove(2);   //刪除
        System.out.println(list);
        
        list.set(2, "ma2"); //修改
        System.out.println(list);
        
        System.out.println(list.get(2)); 
        
        list.add("C");
        list.add("B");
        list.add("A");
        System.out.println(list);
        
        System.out.println(list.indexOf("B"));  
        System.out.println(list.lastIndexOf("B"));  
            
}

(3)ArrayList線性表中的順序表

  • ArrayList底層是用數組實現的存儲。特色:查詢效率高,增刪效率低,線程不安全
  • 在內存中分配連續的空間,實現了長度可變的數組
  • 優勢:遍歷元素和隨機訪問元素的效率比較高
  • 缺點:添加和刪除需大量移動元素效率低,按照內容查詢效率低

(4)LinkedList線性表中雙向鏈表

  • LinkedList底層用雙向鏈表實現存儲。特色:查詢效率低,增刪效率高,線程不安全
  • 優勢:插入、刪除元素效率比較高
  • 缺點:遍歷和隨機訪問元素的效率低下

(5)Vector

  • Vector底層說用數組實現的List,相關方法都加了同步檢查,線程安全,效率低下
  • Vector實現原理和ArrayList相同,功能相同,都是長度可變的數組結構,不少狀況下能夠互用
  • Vector是早期JDK接口,ArrayLis是替代Vector的新接口
  • 長度須要增加時,Vector默認增加一倍,ArrayList增加50%

(6)Map接口

  • Map用來存儲「鍵-值對」,Map類中存儲的鍵值對經過鍵來標識,因此「鍵對象」不能重複,若是重複新的覆蓋舊的。
  • Map接口實現類有HashMap、TreeMap、HashTable、Properties等
方法 說明
Object put(Object key,Object value) 存放鍵值對
Object get(Object key) 經過鍵對象查找獲得值對象
Object remove(Object key) 刪除鍵對象對應的鍵值對
boolean containsKey(Object key) Map容器中是否包含鍵對象對應的鍵值對
boolean containsValue(Object value) Map容器中是否包含值對象對應的鍵值對
int size() 包含鍵值對的數量
boolean isEmpty() Map是否爲空
void putAll(Map t) 將t的全部鍵值對存放到本map對象
void clear() 清空本map對象全部鍵值對

(7)HashMap

  • HashMap:線程不安全,效率高,容許key或value爲null
  • HashMap(Key無序 惟一,Value無序 不惟一)底層實現採用了哈希表,哈希表的基本結構是「數組+鏈表」
  • 當添加一個元素(key-value)時,首先計算key的hash值(hashcode&(數組長度-1)),以此肯定插入數組中的位置,但可能存在同一hash值的元素已經被放在數組同一位置了,這時就添加到同一hash值得元素得後面,他們在數組同一位置,就造成了鏈表,同一個鏈表上的Hash值是相同的,因此說數組存放的是鏈表。JDK8中,當鏈表長度大於8時,鏈表就轉換爲紅黑樹這樣又大大提升了查找的效率。
  • 擴容問題:HashMap的位桶數組,初始大小位16.實際使用時,大小是可變的。若是位桶數組中的元素達到(0.75*數組長度),就從新調整數組大小變爲原來2倍大小。

(8)TreeMap

  • TreeMap是紅黑二叉樹的典型實現,有序但速度低於HashMap
/**
 * 測試TreeMap的使用
 * @author Ma
 *
 */
public class TestTreeMap {
    public static void main(String[] args) {
        Map<Integer,String>  treemap1 = new TreeMap<>();
        treemap1.put(20, "aa");
        treemap1.put(3, "bb");
        treemap1.put(6, "cc");
        
        //按照key遞增的方式排序
        for(Integer  key:treemap1.keySet()){
            System.out.println(key+"---"+treemap1.get(key)); 
        }
        
        Map<Emp,String>  treemap2 = new TreeMap<>();
        treemap2.put(new Emp(100,"張三",50000), "張三是一個好小夥");
        treemap2.put(new Emp(200,"李四",5000), "李四工做不積極");
        treemap2.put(new Emp(150,"王五",6000), "王五工做還不錯");
        treemap2.put(new Emp(50,"趙六",6000), "趙六是個開心果");
        
        //按照key遞增的方式排序
        for(Emp  key:treemap2.keySet()){
            System.out.println(key+"---"+treemap2.get(key)); 
        }        
    }
}

class Emp  implements Comparable<Emp>  {
    int id;
    String name;
    double salary;
    
    public Emp(int id, String name, double salary) {
        super();
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return  "id:"+id+",name:"+name+",salary:"+salary;
    }
    
    @Override
    public int compareTo(Emp o) {        //負數:小於,0:等於,正數:大於
        
        if(this.salary>o.salary){
            return 1;
        }else if(this.salary<o.salary){
            return -1;
        }else{
            if(this.id>o.id){
                return 1;
            }else if(this.id<o.id){
                return -1;
            }else{
                return 0;
            }
        }
        
    }
    
}

(9)HashTable

  • HashTable:線程安全,效率低。不容許key或value爲null

(10)Set接口

  • Set接口繼承自Collection,Set接口中沒有新增方法,方法和Collection保持一致
  • Set容器特色:無序、不可重複。無序值Set中的元素沒有索引,咱們只能遍歷查找;不可重複指不容許加入重複的元素(Set中只能放入一個null元素,不能多個)
  • Set經常使用的實現類有:HashSet、TreeSet

(11)TreeSet

  • TreeSet底層實際是使用TreeMap實現,內部維持了一個簡化版的TreeMap,經過key來存儲Set的元素。TreeSet內部須要對存儲的元素進行排序,所以咱們對應的類須要實現Commparable接口

2019.05.11

1.使用Iterator迭代器遍歷容器元素(List/Set/Map)

  Iterator方法

    boolean hasNext():判斷是否存在另外一個可訪問的元素

    Object next():返回要訪問的下一個元素

    void remove():刪除上次訪問返回的對象

/**
 * 測試迭代器遍歷List、Set、Map
 * @author Ma
 *
 */
public class TestIterator {
    public static void main(String[] args) {
//        testIteratorList();
//        testIteratorSet();
//        testIteratorMap();
        
        testRemove();
    }
    
    public static void testIteratorList(){
        List<String>  list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        
        //使用iterator遍歷List
        for(Iterator<String> iter=list.iterator();iter.hasNext();){
            String  temp = iter.next();
            System.out.println(temp);
        }     
    }
    
    public static void testIteratorSet(){
        Set<String>  set = new HashSet<>();
        set.add("aa");
        set.add("bb");
        set.add("cc");
        
        //使用iterator遍歷Set
        for(Iterator<String> iter=set.iterator();iter.hasNext();){
            String  temp = iter.next();
            System.out.println(temp);
        }      
    }
    
    public static void testIteratorMap(){
        Map<Integer,String> map1 = new HashMap<>();
        map1.put(100, "aa");
        map1.put(200, "bb");
        map1.put(300, "cc");
        

        //第一種遍歷Map的方式
        Set<Entry<Integer,String>>  ss =  map1.entrySet();
        for(Iterator<Entry<Integer,String>> iter=ss.iterator();iter.hasNext();){
            Entry<Integer,String> temp = iter.next();
            
            System.out.println(temp.getKey()+"--"+temp.getValue());
            
        }
        System.out.println("++++++++++++++++++++++++");
        //第二種遍歷Map的方式
        Set<Integer>  keySet = map1.keySet();
        for(Iterator<Integer> iter=keySet.iterator();iter.hasNext(); ){
            Integer key = iter.next();
            System.out.println(key+"----"+map1.get(key));
        }        
    }
    
    //測試邊遍歷,邊刪除
    public static void testRemove(){
        List<String> list = new ArrayList<>();
        for(int i=0;i<20;i++){
            list.add("gao"+i);
        }
        
        for(int i=0;i<list.size();i++){
            String temp = list.get(i);
            if(temp.endsWith("2")){
                list.remove(i);
            }
            System.out.println(list.size()); 
            System.out.println(list.get(i));  
        }        
    }
    
}

2.Collections工具類

  類java.util.Collections提供了對Set、List、Map進行排序、填充、查找元素的輔助方法

方法 說明
void sort(List) 對List容器內元素排序,排序規則按照升序排序
void shuffle(List) 對List容器內的元素進行隨機排序
void reverse(List) 對List容器內的元素進行逆序排序
void fill(List,Object) 用一個特定的對象重寫整個List容器
int binarySearch(List,Object) 對於順序的List容器,採用折半查找的方法查找特定對象

3.使用容器存儲表格數據(ORM思想:對象關係映射)

(1)每一行數據使用一個Map,整個表格使用一個List

/**
 * 測試表格數據的存儲
 * ORM思想的簡單實驗:map表示一行數據,多行數據是多個map;將多個map放到list中
 * @author Ma
 *
 */
public class TestStoreData {
    public static void main(String[] args) {
        
        Map<String,Object>  row1 = new HashMap<>();
        row1.put("id", 1001);
        row1.put("姓名", "張三");
        row1.put("薪水", 20000);
        row1.put("入職日期", "2018.5.5");
        
        Map<String,Object>  row2 = new HashMap<>();
        row2.put("id", 1002);
        row2.put("姓名", "李四");
        row2.put("薪水", 30000);
        row2.put("入職日期", "2005.4.4");
        
        Map<String,Object>  row3 = new HashMap<>();
        row3.put("id", 1003);
        row3.put("姓名", "王五");
        row3.put("薪水", 3000);
        row3.put("入職日期", "2020.5.4");
        
        List<Map<String,Object>>   table1 = new ArrayList<>();
        table1.add(row1);
        table1.add(row2);
        table1.add(row3);
        
        for(Map<String,Object> row:table1){
            
            Set<String> keyset = row.keySet();
            
            for (String key : keyset) {
                System.out.print(key+":"+row.get(key)+"\t");
            }
            System.out.println();
        }
     
    }
}

(2)每一行數據使用javabean對象存儲,整個表格使用一個map或list

/**
 * 測試表格數據的存儲
 * 體會ORM思想
 * 每一行數據使用javabean對象存儲,多行使用放到map或list中。
 * @author Ma
 *
 */
public class TestStoreData2 {
    public static void main(String[] args) {
        User  user1 = new User(1001, "張三", 20000, "2018.5.5");
        User  user2 = new User(1002, "李四", 30000, "2005.4.4");
        User  user3 = new User(1003, "王五", 3000, "2020.5.4");
        
        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        
        for(User u:list){
            System.out.println(u);
        }
        
        Map<Integer,User>  map = new HashMap<>();
        map.put(1001, user1);
        map.put(1002, user2);
        map.put(1003, user3);
        
        Set<Integer>  keyset = map.keySet();
        for (Integer key : keyset) {
            System.out.println(key+"===="+map.get(key)); 
        }  
    }
}

class  User {
    private int id;
    private String name;
    private double salary;
    private String  hiredate;
    
    
    //一個完整的javabean。要有set和get方法,以及無參構造器!
    public User() {
    }
    
    public User(int id, String name, double salary, String hiredate) {
        super();
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.hiredate = hiredate;
    }
      
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    public String getHiredate() {
        return hiredate;
    }
    public void setHiredate(String hiredate) {
        this.hiredate = hiredate;
    }

    @Override
    public String toString() {
        return "id:"+id+",name:"+name+",salary:"+salary+",hiredate:"+hiredate;
    }
}

 

2019.5.12

1.相對路徑與絕對路徑

  絕對路徑:存在盤符

  相對路徑:不存在盤符,相對於當前目錄user.dir

2.File類

Java文件類以抽象的方式表明文件名和目錄路徑名。該類主要用於文件和目錄的建立、文件的查找和文件的刪除等。

File對象表明磁盤中實際存在的文件和目錄。經過如下構造方法建立一個File對象。

構造方法:

  • 經過給定的父抽象路徑名和子路徑名字符串建立一個新的File實例。
  File(File parent, String child);
  • 經過將給定路徑名字符串轉換成抽象路徑名來建立一個新 File 實例。
  File(String pathname)
  • 根據 parent 路徑名字符串和 child 路徑名字符串建立一個新 File 實例。
  File(String parent, String child)
  • 經過將給定的 file: URI 轉換成一個抽象路徑名來建立一個新的 File 實例。
  File(URI uri)
建立File對象成功後,可使用如下列表中的方法操做文件:
方法 說明
public String getName() 返回文件或目錄的名稱
public String getParent() 返回父路徑名的字符串,若是沒有指定父目錄,則返回 null
public File getParentFile() 返回父路徑名的File對象,若是此路徑名沒有指定父目錄,則返回 null
public String getPath() 將此抽象路徑名轉換爲一個路徑名字符串
public boolean isAbsolute() 是否爲絕對路徑
public String getAbsolutePath() 返回抽象路徑名的絕對路徑名字符串
public boolean canRead() 是否能夠讀取此文件
public boolean canWrite() 是否能夠修改此文件
public boolean exists() 文件或目錄是否存在
public boolean isDirectory() 文件是不是一個目錄
public boolean isFile() 是不是一個標準文件
public long lastModified() 返回文件最後一次被修改的時間
public long length() 返回文件的長度
public boolean createNewFile() throws IOException 當且僅當不存在指定的名稱的文件時,原子地建立一個新的空文件
public boolean delete() 刪除文件或目錄
public void deleteOnExit() 在虛擬機終止時,請求刪除文件或目錄
public String[] list() 返回下級目錄文件名稱的字符串數組
public String[] list(FilenameFilter filter) 返回由包含在目錄中的文件和目錄的名稱所組成的字符串數組,這一目錄是經過知足指定過濾器的抽象路徑名來表示的
public File[] listFiles() 返回下級目錄文件名稱的File對象數組
public File[] listFiles(FileFilter filter) 返回表示此抽象路徑名所表示目錄中的文件和目錄的抽象路徑名數組,這些路徑名知足特定過濾器
public boolean mkdir() 建立指定的目錄,確保上級目錄存在,不存在建立失敗
public boolean mkdirs() 建立指定的目錄,上級目錄不存在一同建立
public boolean renameTo(File dest) 從新命名此文件
public boolean setLastModified(long time) 設置指定文件或目錄的最後一次修改時間
public boolean setReadOnly() 標記指定的文件或目錄,以便只可對其進行讀操做
public static File createTempFile(String prefix, String suffix, File directory) throws IOException 在指定目錄中建立一個新的空文件,使用給定的前綴和後綴字符串生成其名稱
public static File createTempFile(String prefix, String suffix) throws IOException 在默認臨時文件目錄中建立一個空文件,使用給定前綴和後綴生成其名稱
public int compareTo(File pathname) 按字母順序比較兩個抽象路徑名
public int compareTo(Object o) 按字母順序比較抽象路徑名與給定對象
public boolean equals(Object obj) 測試此抽象路徑名與給定對象是否相等
public String toString() 返回路徑名字符串

 3.文件編碼

  字節->字符:編碼(encode)

  字符->字節:解碼(decode)

/**
 * 編碼: 字符串-->字節
 * @author Ma
 *
 */
public class ContentEncode {

    public static void main(String[] args) throws IOException {
        String msg ="性命生命使命a";
        //編碼: 字節數組
        byte[] datas = msg.getBytes();  //默認使用工程的字符集
        System.out.println(datas.length);
        
        //編碼: 其餘字符集
        datas = msg.getBytes("UTF-16LE");
        System.out.println(datas.length);
        
        datas = msg.getBytes("GBK");
        System.out.println(datas.length);                
    }
}
/**
 * 解碼: 字節->字符串
 * @author Ma
 *
 */
public class ContentDecode {

    public static void main(String[] args) throws UnsupportedEncodingException {
        String msg ="性命生命使命a";
        //編碼: 字節數組
        byte[] datas = msg.getBytes();  //默認使用工程的字符集
        
        //解碼: 字符串 String​(byte[] bytes, int offset, int length, String charsetName)
        msg = new String(datas,0,datas.length,"utf8");
        System.out.println(msg);
        
        
        //亂碼: 
        //1)、字節數不夠
        msg = new String(datas,0,datas.length-2,"utf8");
        System.out.println(msg);
        msg = new String(datas,0,datas.length-1,"utf8");
        System.out.println(msg);
        
        //2)、字符集不統一
        msg = new String(datas,0,datas.length-1,"gbk");
        System.out.println(msg);
    }
}

4.InputStream:字節輸入流的父類,數據單位爲字節

經常使用方法:

方法 說明
void close() 關閉此輸入流並釋放與流相關聯的任何系統資源
int read(byte[] b) 從輸入流中讀取一些字節數,並將他們存儲到緩衝器陣列b
int read(byte[] b,int off, int len) 從輸入流讀取最多len個字節的數據到字節數組
abstract int read() 從輸入流讀取數據的下一個字節

 

/**
 * 四個步驟: 分段讀取 文件字節輸入流
 * 一、建立源
 * 二、選擇流
 * 三、操做
 * 四、釋放資源
 * 
 * @author Ma
 *
 */
public class IOTest03 {

    public static void main(String[] args) {
        //一、建立源
        File src = new File("abc.txt");
        //二、選擇流
        InputStream  is =null;
        try {
            is =new FileInputStream(src);
            //三、操做 (分段讀取)
            byte[] flush = new byte[1024*10]; //緩衝容器
            int len = -1; //接收長度
            while((len=is.read(flush))!=-1) {
                //字節數組-->字符串 (解碼)
                String str = new String(flush,0,len);
                System.out.println(str);
            }        
        
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //四、釋放資源
            try {
                if(null!=is) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

5.OutputStream:字節輸出流的父類,數據單位爲字節

經常使用方法:

方法 說明
void close() 關閉此輸出流並釋放與此流相關聯的任何系統資源
void flush() 刷新此輸出流並強制任何緩衝的輸出字節被寫出
void write(byte[] b) 將b.length字節從指定的字節數組寫入此輸出流
void write(byte[] b,int off,int len) 從指定的字節數組寫入len字節,從偏移量off開始輸出此輸出流
abstract void write(int b) 將指定的字節寫入此輸出流

 

/**
 * 文件字節輸出流
 *一、建立源
 *二、選擇流
 *三、操做(寫出內容)
 *四、釋放資源
 *  @author Ma
 *
 */
public class IOTest04 {

    public static void main(String[] args) {
        //一、建立源
        File dest = new File("dest.txt");  //文件不存在建立文件
        //二、選擇流
        OutputStream os =null;
        try {
            os = new FileOutputStream(dest,true); //true爲追加操做
            //三、操做(寫出)
            String msg ="IO is so easy\r\n";
            byte[] datas =msg.getBytes(); // 字符串-->字節數組(編碼)
            os.write(datas,0,datas.length);
            os.flush();
        }catch(FileNotFoundException e) {        
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            //四、釋放資源
            try {
                if (null != os) {
                    os.close();
                } 
            } catch (Exception e) {
            }
        }
    }

}

6.Reader:字符輸入流的父類,數據單位爲字符

經常使用方法:

方法 說明
void close() 關閉此輸入流並釋放與流相關聯的任何系統資源
int read() 讀一個字符
int read(char[] cbuf) 將字符讀入數組
abstract int read(cbuf[] b,int off, int len) 從輸入流讀取最多len個字符的數據到字符數組
/**
 * 四個步驟: 分段讀取 文件字符輸入流
 * 一、建立源
 * 二、選擇流
 * 三、操做
 * 四、釋放資源
 * 
 * @author Ma
 *
 */
public class IOTest05 {

    public static void main(String[] args) {
        //一、建立源
        File src = new File("abc.txt");
        //二、選擇流
        Reader  reader =null;
        try {
            reader =new FileReader(src);
            //三、操做 (分段讀取)
            char[] flush = new char[1024]; //緩衝容器
            int len = -1; //接收長度
            while((len=reader.read(flush))!=-1) {
                //字符數組-->字符串
                String str = new String(flush,0,len);
                System.out.println(str);
            }        
        
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //四、釋放資源
            try {
                if(null!=reader) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

7.Writer:字節輸出流的父類,數據單位爲字符

經常使用方法:

方法 說明
abstract void close() 關閉流,先刷新
abstract void flush() 刷新流
void write(int c) 寫入一個字符
void write(String str) 寫入一個字符串
void write(String str,int off,int len) 寫入字符串的一部分
abstract void write(byte[] cbuf,int off,int len) 寫入字符數組的一部分
/**
 * 文件字符輸出流
 *一、建立源
 *二、選擇流
 *三、操做(寫出內容)
 *四、釋放資源
 *  @author Ma
 *
 */
public class IOTest06 {

    public static void main(String[] args) {
        //一、建立源
        File dest = new File("dest.txt");
        //二、選擇流
        Writer writer =null;
        try {
            writer = new FileWriter(dest);
            //三、操做(寫出)
            //寫法一
//            String msg ="IO is so easy\r\n歡迎你";
//            char[] datas =msg.toCharArray(); // 字符串-->字符數組
//            writer.write(datas,0,datas.length);
            //寫法二
            /*String msg ="IO is so easy\r\n歡迎你";
            writer.write(msg);    
            writer.write("add");        
            writer.flush();*/
            
            //寫法三
            writer.append("IO is so easy\r\n").append("歡迎你");
            writer.flush();
        }catch(FileNotFoundException e) {        
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            //四、釋放資源
            try {
                if (null != writer) {
                    writer.close();
                } 
            } catch (Exception e) {
            }
        }
    }
}

2019.5.13

1.字節數組流(ByteArrayInputStream&ByteArrayOutputStream)

  咱們常見的節點流(FileInputStream/FileOutputStream  FileReader/FileWrite)和常見處理流(BufferedInputStream/BufferedOutputStream BufferedReader/BufferedWriter),都是針對文件的操做,而後帶上緩衝的節點流進行處理,但有時候爲了提高效率,咱們發現頻繁的讀寫文件並非太好,因而出現了字節數組流,即存放在內存中,也稱爲內存流;其中字節數組流也是一種節點流

(1)ByteArrayInputStream

  字節數組輸入流在內存建立一個字節數組緩衝區,從輸入流讀取的數據保存在該字節數組緩衝區中

(2)ByteArrayOutputStream

  字節數組輸出流在內存中建立一個字節數組緩衝區,全部發送到輸出流的數據保存在該字節數組緩衝區中

/**
 *一、 圖片讀取到字節數組
 *二、 字節數組寫出到文件
 *  @author Ma
 *
 */
public class IOTest {

    public static void main(String[] args) {
        //圖片轉成字節數組
        byte[] datas = fileToByteArray("p.png");
        System.out.println(datas.length);
        byteArrayToFile(datas,"p-byte.png");        
    }
    /**
     * 一、圖片讀取到字節數組
     * 1)、圖片到程序  FileInputStream
     * 2)、程序到字節數組    ByteArrayOutputStream
     */
    public static byte[] fileToByteArray(String filePath) {
        //一、建立源與目的地
        File src = new File(filePath);//二、選擇流
        InputStream  is =null;
        ByteArrayOutputStream baos =null;
        try {
            is =new FileInputStream(src);
            baos = new ByteArrayOutputStream();
            //三、操做 (分段讀取)
            byte[] flush = new byte[1024*10]; //緩衝容器
            int len = -1; //接收長度
            while((len=is.read(flush))!=-1) {
                baos.write(flush,0,len);         //寫出到字節數組中            
            }        
            baos.flush();
            return baos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //四、釋放資源
            try {
                if(null!=is) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;        
    }
    /**
     * 二、字節數組寫出到圖片
     * 1)、字節數組到程序 ByteArrayInputStream
     * 2)、程序到文件 FileOutputStream
     */
    public static void byteArrayToFile(byte[] src,String filePath) {
        //一、建立源
        File dest = new File(filePath);
        //二、選擇流
        InputStream  is =null;
        OutputStream os =null;
        try {
            is =new ByteArrayInputStream(src);
            os = new FileOutputStream(dest);
            //三、操做 (分段讀取)
            byte[] flush = new byte[5]; //緩衝容器
            int len = -1; //接收長度
            while((len=is.read(flush))!=-1) {
                os.write(flush,0,len);            //寫出到文件    
            }        
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //四、釋放資源
            try {
                if (null != os) {
                    os.close();
                } 
            } catch (Exception e) {
            }
        }
    }
}

2.緩衝

 緩衝輸入流相對於普通輸入流的優點是,它提供了一個緩衝數組,每次調用read方法的時候,它首先嚐試從緩衝區裏讀取數據,若讀取失敗(緩衝區無可讀數據),則選擇從物理數據源(譬如文件)讀取新數據(這裏會嘗試儘量讀取多的字節)放入到緩衝區中,最後再將緩衝區中的內容部分或所有返回給用戶.從緩衝區裏讀取數據遠比直接從物理數據源(譬如文件)讀取速度快。

 (1)BufferedInputStream&BufferedOutputStream

/**
 * 文件拷貝:文件字節輸入、輸出流
 *
 *  @author Ma
 *
 */
public class Copy {

    public static void main(String[] args) {
        long t1 = System.currentTimeMillis();
        copy("IO開篇.mp4","IO-copy.mp4"); 
        long t2 = System.currentTimeMillis();
        System.out.println(t2-t1);
    }
    
    public static void copy(String srcPath,String destPath) {
        //一、建立源
            File src = new File(srcPath); //源頭
            File dest = new File(destPath);//目的地
            //二、選擇流        
            try( InputStream is=new BufferedInputStream(new FileInputStream(src));
                    OutputStream os =new BufferedOutputStream( new FileOutputStream(dest));    ) {                
                //三、操做 (分段讀取)
                byte[] flush = new byte[1024]; //緩衝容器
                int len = -1; //接收長度
                while((len=is.read(flush))!=-1) {
                    os.write(flush,0,len); //分段寫出
                }            
                os.flush();
            }catch(FileNotFoundException e) {        
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }
    }
}

(2)BufferedReader&BufferedWriter

/**
 * 純文本拷貝:文件字節輸入、輸出流
 *
 *  @author Ma
 *
 */
public class CopyTxt {

    public static void main(String[] args) {
        copy("abc.txt","abc-copy.txt"); 
    }    
    public static void copy(String srcPath,String destPath) {
        //一、建立源
            File src = new File(srcPath); //源頭
            File dest = new File(destPath);//目的地
            //二、選擇流        
            try( BufferedReader br=new BufferedReader(new FileReader(src));
                    BufferedWriter bw =new BufferedWriter( new FileWriter(dest));    ) {                
                //三、操做 (逐行讀取)
                String line =null;
                while((line=br.readLine())!=null) {
                    bw.write(line); //逐行寫出
                    bw.newLine();
                }            
                bw.flush();
            }catch(FileNotFoundException e) {        
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }
    }
}

 3.轉換流:InputStreamReader&OutputStreamWriter

  • 以字符流的形式操做字節流(純文本)
  • 爲字節流指定字符集
/**
 * 轉換流: InputStreamReader OutputStreamWriter
 * 一、以字符流的形式操做字節流(純文本的)
 * 二、指定字符集
 * @author Ma
 *
 */
public class ConvertTest {
    public static void main(String[] args) {
        //操做System.in 和System.out
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(System.out));){
            //循環獲取鍵盤的輸入(exit退出),輸出此內容
            String msg ="";
            while(!msg.equals("exit")) {
                msg = reader.readLine(); //循環讀取
                writer.write(msg); //循環寫出
                writer.newLine();
                writer.flush(); //強制刷新
            }
        }catch(IOException e) {
            System.out.println("操做異常");
        }    
    }
}
/**
 * 轉換流: InputStreamReader OutputStreamWriter
 * 一、以字符流的形式操做字節流(純文本的)
 * 二、指定字符集
 * @author Ma
 *
 */
public class ConvertTest {
    public static void main(String[] args) {
        try(BufferedReader reader =
                new BufferedReader(
                        new InputStreamReader(
                                new URL("http://www.baidu.com").openStream(),"UTF-8"));
                BufferedWriter writer =
                        new BufferedWriter(
                                new OutputStreamWriter(
                                        new FileOutputStream("baidu.html"),"UTF-8"));){
            //三、操做 (讀取)
            String msg ;
            while((msg=reader.readLine())!=null) {
                writer.write(msg); 
                writer.newLine();
            }                    
            writer.flush();
        }catch(IOException e) {
            System.out.println("操做異常");
        }
    }
}

 4.數據流:DataInputStream&DataOutputStream

  • 保留了數據類型,方便處理基本 Java 數據類型
  • 寫出後讀取
  • 讀取的順序與寫出保持一致

5.對象流:ObjectInputStream(反序列化)&ObjectOutputStream(序列化)

  • 只有支持java.io.Serializable接口的對象才能序列化
  • 寫出後讀取
  • 讀取的順序與寫出保持一致
/**
 * 對象流: 一、寫出後讀取 二、讀取的順序與寫出保持一致 三、不是全部的對象均可以序列化Serializable
 * 
 * ObjectOutputStream ObjectInputStream
 * 
 * @author Ma
 *
 */
public class ObjectTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 寫出 -->序列化
        ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("obj.ser")));
        // 操做數據類型 +數據
        oos.writeUTF("編碼辛酸淚");
        oos.writeInt(18);
        oos.writeBoolean(false);
        oos.writeChar('a');
        // 對象
        oos.writeObject("誰解其中味");
        oos.writeObject(new Date());
        Employee emp = new Employee("馬雲", 400);
        oos.writeObject(emp);
        oos.flush();
        oos.close();
        // 讀取 -->反序列化
        ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("obj.ser")));
        // 順序與寫出一致
        String msg = ois.readUTF();
        int age = ois.readInt();
        boolean flag = ois.readBoolean();
        char ch = ois.readChar();
        System.out.println(flag);
        // 對象的數據還原
        Object str = ois.readObject();
        Object date = ois.readObject();
        Object employee = ois.readObject();

        if (str instanceof String) {
            String strObj = (String) str;
            System.out.println(strObj);
        }
        if (date instanceof Date) {
            Date dateObj = (Date) date;
            System.out.println(dateObj);
        }
        if (employee instanceof Employee) {
            Employee empObj = (Employee) employee;
            System.out.println(empObj.getName() + "-->" + empObj.getSalary());
        }
        ois.close();
    }
}

6.打印流

7.隨機讀取和寫入流RandomAccessFile

8.CommonsIO

public class CIOTest01 {

    public static void main(String[] args) {
        //文件大小
        long len =FileUtils.sizeOf(new File("src/com/sxt/commons/CIOTest01.java"));
        System.out.println(len);
        //目錄大小
        len = FileUtils.sizeOf(new File("D:/java300/IO_study04"));
        System.out.println(len);
    }
}
/**
 * 列出子孫級
 */
public class CIOTest02 {

    public static void main(String[] args) {
        Collection<File> files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
                EmptyFileFilter.NOT_EMPTY, null);
        for (File file : files) {
            System.out.println(file.getAbsolutePath());
        }
        System.out.println("---------------------");
         files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
                    EmptyFileFilter.NOT_EMPTY, DirectoryFileFilter.INSTANCE);
        for (File file : files) {
            System.out.println(file.getAbsolutePath());
        }
        System.out.println("---------------------");
         files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
                    new SuffixFileFilter("java"), DirectoryFileFilter.INSTANCE);
        for (File file : files) {
            System.out.println(file.getAbsolutePath());
        }
        System.out.println("---------------------");
         files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
                    FileFilterUtils.or(new SuffixFileFilter("java"),
                            new SuffixFileFilter("class"),EmptyFileFilter.EMPTY), DirectoryFileFilter.INSTANCE);
        for (File file : files) {
            System.out.println(file.getAbsolutePath());
        }
        
        System.out.println("---------------------");
         files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
                    FileFilterUtils.and(new SuffixFileFilter("java"),
                            EmptyFileFilter.NOT_EMPTY), DirectoryFileFilter.INSTANCE);
        for (File file : files) {
            System.out.println(file.getAbsolutePath());
        }
    }
}
/**
 * 讀取內容
 * @author Ma
 *
 */
public class CIOTest03 {

    public static void main(String[] args) throws IOException {
        //讀取文件
        String msg =FileUtils.readFileToString(new File("emp.txt"),"UTF-8");
        System.out.println(msg);
        byte[] datas = FileUtils.readFileToByteArray(new File("emp.txt"));
        System.out.println(datas.length);
        
        //逐行讀取
         List<String> msgs= FileUtils.readLines(new File("emp.txt"),"UTF-8");
         for (String string : msgs) {
            System.out.println(string);
        }
        LineIterator it =FileUtils.lineIterator(new File("emp.txt"),"UTF-8");
        while(it.hasNext()) {
            System.out.println(it.nextLine());
        }
    }
}
/**
 * 寫出內容
 * @author Ma
 *
 */
public class CIOTest04 {

    public static void main(String[] args) throws IOException {
        //寫出文件
        FileUtils.write(new File("happy.sxt"), "學習是一件偉大的事業\r\n","UTF-8");
        FileUtils.writeStringToFile(new File("happy.sxt"), "學習是一件辛苦的事業\r\n","UTF-8",true);
        FileUtils.writeByteArrayToFile(new File("happy.sxt"), "學習是一件幸福的事業\r\n".getBytes("UTF-8"),true);
        
        //寫出列表
        List<String> datas =new ArrayList<String>();
        datas.add("馬雲");
        datas.add("馬化騰");
        datas.add("弼馬溫");
        
        FileUtils.writeLines(new File("happy.sxt"), datas,"。。。。。",true);
    }
}
/**
 * 拷貝
 * @author Ma
 *
 */
public class CIOTest05 {

    public static void main(String[] args) throws IOException {
        //複製文件
        //FileUtils.copyFile(new File("p.png"),new File("p-copy.png"));
        //複製文件到目錄
        //FileUtils.copyFileToDirectory(new File("p.png"),new File("lib"));
        //複製目錄到目錄
        //FileUtils.copyDirectoryToDirectory(new File("lib"),new File("lib2"));
        //複製目錄
        //FileUtils.copyDirectory(new File("lib"),new File("lib2"));
        //拷貝URL內容
        //String url = "https://pic2.zhimg.com/v2-7d01cab20858648cbf62333a7988e6d0_qhd.jpg";
        //FileUtils.copyURLToFile(new URL(url), new File("marvel.jpg"));
        String datas =IOUtils.toString(new URL("http://www.163.com"), "gbk");
        System.out.println(datas);
    }
}

 

2019.5.16

1.IP地址

  用來標識網絡中的一個通用實體的地址2.

2.InetAddress

/**
 * InetAddress:
 * 1.getLocatHost:本機
 * 2.getByName:根據域名DNS | IP地址--》IP
 * 
 * 兩個成員方法
 * 1.getHostAddress:返回地址
 * 2.getHostName:返回計算機名
 * @author MA
 *
 */
public class IPTest {

    public static void main(String[] args) throws UnknownHostException {
        //使用getLocaHost方法建立InetAddress對象 本機
        InetAddress addr = InetAddress.getLocalHost();
        System.out.println(addr.getHostAddress());//返回IP地址
        System.out.println(addr.getHostName());//輸出計算機名
        
        //根據域名獲得InetAddress對象
        addr = InetAddress.getByName("www.163.com");
        System.out.println(addr.getHostAddress());//返回163服務器IP
        System.out.println(addr.getHostName());//輸出:www.163.com
        
        //根據IP獲得InetAddress對象
        addr = InetAddress.getByName("123.56.138.176");
        System.out.println(addr.getHostAddress());//返回shsxt的ip
        System.out.println(addr.getHostName());//輸出ip而不是域名。若是這個IP地址不存在或DNS服務器不容許進行IP地址和域名的映射,getHostName方法就直接返回這個IP地址
    }
}

 3.端口

  IP地址用來標識一臺計算機,電腦裏的軟件由端口區分。端口0~65535,0~1023爲公認端口

  8080-》tomact

  1521-》oracle

  3306-》mysql

  查看全部端口:netstat -ano

  查看指定端口:netstat -ano|findstr "808"

  查看指定進程:tasklist|findstr "808"

  查看具體程序:使用任務管理器查看PID

4.InetSocketAddress

  包含端口,用於socket通訊

/**
 * InetSocketAddress
 * 1.構造器
 * new InetSocketAddress(地址|域名,端口);
 * 2.方法
 * getAddress()
 * getport()
 * getHostName()
 * @author MA
 *
 */
public class PortTest {

    public static void main(String[] args) {
        //包含端口
        InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
        InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",9000);
        System.out.println(socketAddress.getHostName());
        System.out.println(socketAddress2.getAddress());
        System.out.println(socketAddress2.getPort());
    }
}

5.URI(統一資源標誌符)

  (1)URN:統一資源名稱(磁力連接)

  (2)URL:統一資源定位符,互聯網三大基石之一(html,http)區分資源

    http://www.google.com:80/index.html

    協議:http

    主機域名:www.google.com

    端口號:80

    請求資源:index.html

public class URLTest01 {
    
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://www.baidu.com:80/index.html?uname=shsxt&age=18#a");
        System.out.println("協議:" + url.getProtocol());
        System.out.println("域名|ip:" + url.getHost());
        System.out.println("端口:" + url.getPort());
        System.out.println("請求資源1:" + url.getFile());
        System.out.println("請求資源2:" + url.getPath());
        
        //參數
        System.out.println("參數:" + url.getQuery());
        //錨點
        System.out.println("錨點:" + url.getRef());
    }

}

6.網絡爬蟲的原理

/**
 * 網絡爬蟲原理
 * @author MA
 *
 */
public class SpiderTest {

    public static void main(String[] args) throws IOException {
        //獲取URL
        URL url = new URL("https://www.jd.com");
        //下載資源
        InputStream is = url.openStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        String msg = null;
        while(null!=(msg=br.readLine())){
            System.out.println(msg);
        }
        br.close();
        //分析
        //處理。。。
    }
}
/**
 * 網絡爬蟲原理 + 模擬瀏覽器
 * @author MA
 *
 */

public class SpiderTest2 {

    public static void main(String[] args) throws IOException {
        //獲取URL
        URL url = new URL("https://www.dianping.com");
        //下載資源
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134");
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        String msg = null;
        while(null!=(msg=br.readLine())){
            System.out.println(msg);
        }
        br.close();
        //分析
        //處理。。。
    }
}

7.Socket 套接字

(1)TCP傳輸協議

  一種面向鏈接的、可靠的、基於字節流的運輸層通信協議。

/**
 * 建立客戶端
 * 1.創建鏈接:使用Socket建立客戶端+服務的地址和端口
 * 2.操做:輸入輸出操做
 * 3.釋放資源
 * @author MA
 *
 */
public class Client {

    public static void main(String[] args) throws UnknownHostException, IOException {
        //1.創建鏈接:使用Socket建立客戶端+服務的地址和端口
        Socket client = new Socket("localhost",8888);
        //2.操做:輸入輸出操做
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());
        String data="hello";
        dos.writeUTF(data);
        dos.flush();
        //3.釋放資源
        dos.close();
        client.close();
    }
}
/**
 * 建立服務器
 * 1.指定端口 使用ServerSocket建立服務器
 * 2.阻塞式等待鏈接accept
 * 3.操做:輸入輸出流操做
 * 4.釋放資源
 * @author MA
 *
 */
public class Server {

    public static void main(String[] args) throws IOException {
        //1.指定端口 使用ServerSocket建立服務器
        ServerSocket server = new ServerSocket(9999);
        //2.阻塞式等待鏈接accept
        Socket client = server.accept();
        //3.操做:輸入輸出流操做
        DataInputStream dis = new DataInputStream(client.getInputStream());
        String data = dis.readUTF(dis);
        //4.釋放資源
        dis.close();
        client.close();    
    }
}

(2)UDP協議

  一種無鏈接的傳輸協議,提供面向事務的簡單不可靠信息傳送服務。

/**
 * 發送端
 * 1.使用DatagrammSocket指定端口建立發送端
 * 2.準備數據 必定轉成字節數組
 * 3.封裝成DatagramPacket包裹,須要指定目的地
 * 4.發送包裹send(DatagramPacket p)
 * 5.釋放資源
 * @author MA
 */
public class UdpClient {

    public static void main(String[] args) throws IOException {
        //1.使用DatagrammSocket指定端口建立發送端
        DatagramSocket client = new DatagramSocket(8888);
        //2.準備數據 必定轉成字節數組
        String data = "Hello world!";
        byte[] datas = data.getBytes();
        //3.封裝成DatagramPacket包裹,須要指定目的地
        DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost", 9999));
        //4.發送包裹send(DatagramPacket p)
        client.send(packet);
        //5.釋放資源
        client.close();
    }
}
/**
 * 接收端
 * 1.使用DatagrammSocket指定端口建立接收端
 * 2.準備容器 封裝成DatagramPacket包裹
 * 3.阻塞式接收包裹receive(DatagramPacket p)
 * 4.分析數據 
 *     byte[] getData()
 *     int getLength()
 * 5.釋放資源
 * @author MA
 */
public class UdpServer {

    public static void main(String[] args) throws IOException {
         //1.使用DatagrammSocket指定端口建立接收端
            DatagramSocket server = new DatagramSocket(9999);
         //2.準備容器 封裝成DatagramPacket包裹
            byte[] container = new byte[1024*60];
            DatagramPacket packet = new DatagramPacket(container,0,container.length);
         //3.阻塞式接收包裹receive(DatagramPacket p)
            server.receive(packet);
         //4.分析數據 
            byte[] datas = packet.getData();
            int len = packet.getLength();
            System.out.println(new String(datas,0,len));
         //5.釋放資源
            server.close();
    }
}

 

2019.5.19

1.反射

  反射Reflection:把java類中的各類結構(方法、屬性、構造器、類名)映射成一個個的java對象。

/**
 * 反射:把java類中的各類結構(方法、屬性、構造器、類名)映射成一個個的java對象。
 * 1.獲取Class對象
 * 三種方式:Class.forName("完整路徑")
 * 2.動態建立對象
 * clz.getConstructor().newInstance()
 * @author MA
 */
public class ReflectTest {
    
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
        //三種方式
        //1.對象,getClass()
        Class clz = new Iphone().getClass();
        //2.類.class();
        clz = Iphone.class;
        //3.Class.forName("包名.類名")
        clz = Class.forName("com.mxj.server.basic.Iphone");
        
        //建立對象
        /*Iphone iphone1 = (Iphone)clz.newInstance();
        System.out.println(iphone1);*/
        //JDK9推薦構造器的方式
        Iphone iphone2 = (Iphone)clz.getConstructor().newInstance();
    }
    
}

class Iphone{
    public Iphone(){
        
    }
}

2.XML解析

  XML:Extensible Markup Language,可擴展標記語言,做爲數據的一種存儲格式或用於存儲軟件的參數,程序解析配置文件,就能夠達到不修改代碼就能更改程序的目的。

  (1)DOM解析

  (2)SAX解析

    XML:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
    <person>
        <name>張三</name>
        <age>20</age>
    </person>
    <person>
        <name>李四</name>
        <age>25</age>
    </person>
</persons>

    Person類:

package com.mxj.server.basic;

public class Person {
    private String name;
    private int age;
    
    public Person() {
        super();
        // TODO Auto-generated constructor stub
    }
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

    SAX解析:

/**
 * SAX解析流程
 * 1.獲取解析工廠
 * 2.從解析工廠中獲取解析器
 * 3.加載文檔Document註冊處理器
 * 4.編寫處理器
 * @author MA
 */
public class XmlTest01 {

    public static void main(String[] args) throws Exception, SAXException {
        //1.獲取解析工廠
        SAXParserFactory factory = SAXParserFactory.newInstance();
        //2.從解析工廠中獲取解析器
        SAXParser parse = factory.newSAXParser();
        //3.編寫處理器
        //4.加載文檔Document註冊處理器
        PersonHandler handler = new PersonHandler();
        //5.解析
        parse.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("com/mxj/server/basic/person.xml"),handler);
        
        //獲取數據
        List<Person> persons = handler.getPersons();
        for(Person p:persons){
            System.out.println(p.getName()+"-->"+p.getAge());
        }
    }

}

class PersonHandler extends DefaultHandler{
    private List<Person> persons;
    private Person person;
    private String tag;//存儲操做標籤
    
    //解析文檔開始
    @Override
    public void startDocument() throws SAXException {
        persons = new ArrayList<Person>();
    }
    //解析標籤(元素)開始
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName!=null){
            tag = qName;//存儲標籤名
        }
        
        if(tag.equals("person")){
            person = new Person();
        }
    }
    
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String contents = new String(ch,start,length).trim();
        if(null!=tag){
            if(tag.equals("name")){
                person.setName(contents);
            }else if(tag.equals("age")){
                if(contents.length()>0){
                    person.setAge(Integer.valueOf(contents));
                }            
            }
        }    
    }
    //解析標籤(元素)結束
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        
        if(null!=qName){
            if(qName.equals("person")){
                persons.add(person);
            }    
        }
        tag = null;
    }
    
    //解析文檔結束
    @Override
    public void endDocument() throws SAXException {
    }
    
    public List<Person> getPersons() {
        return persons;
    }
}

3.HTML

  Hyper Text Markup Language:超文本標記語言,簡單理解爲瀏覽器使用的語言

4.HTTP協議

  超文本傳輸協議(HTTP,Hyper Text Transfer Protocol)是互聯網上應用最爲普遍的一種網絡協議,全部的www文件都必須遵照這個標準。

 

2019.5.21

1.註解Annotation

  Annotation是從JDK5.0開始引入的新技術,能夠被其餘程序(好比:編輯器)讀取,能夠附加在package,class,method,field等上面,至關於給他們添加了額外的輔助信息,咱們能夠經過反射機制編程實現對這些元數據的訪問。

  (1)@Override

    定義在java.lang.Override中,此註釋只使用於修飾方法,表示一個方法聲明打算重寫超類中的另外一個方法聲明。

  (2)@Deprecated

    定義在java.lang.Deprecated中,此註釋可用於修飾方法、屬性、類,表示不鼓勵程序員使用這樣的元素,一般是由於它很危險或存在更好的選擇。

2.內置註解

  (1)@SuppressWarning

    定義在java.lang.SuppressWarning中,用來抑制編譯時的警告信息。

參數 說明
deprecation 使用了過期的類或方法的警告
unchecked 執行了未檢查的轉換時的警告,如使用集合時未指定泛型
fallthrough 當在switch語句使用時發生case穿透
path 在類路徑、源文件路徑等中有不存在路徑的警告
serial 當在可序列化的類上缺乏serialVersionUID定義時的警告
finally 任何finally子句不能完成時的警告
all 關於以上全部狀況的警告

3.自定義註解

  使用@interface自定義註解時,自動繼承了java.lang.annotation.Anntation接口

  格式:public @interface 註解名 {定義體}

4.元註解

  元註解的做用就是負責註解其餘註解。java定義了4個標準的meta-annotation類型,它們被用來提供對其餘annotation類型做說明。

  (1)@Target

    用於描述註解的使用範圍(即:被描述的註解能夠用在什麼地方)

所修飾範圍 取值ElementType
package包 PACKAGE
類、接口、枚舉、Annotation類型 TYPE
類型成員(方法、構造方法、成員變量、枚舉值)

CONSTRUCTOR:用於描述構造器

FIELD:用於描述域

METHOD:用於描述方法

方法參數和本地變量

LOCAL_VARIABLE:用於描述局部變量

PARAMETER:用於描述參數

 

  (2)@Retention

    表示須要在什麼級別保存該註釋信息,用於描述註解的聲明週期

取值RetentionPolicy 做用
SOURCE 在源文件有效(即源文件保留)
CLASS 在class文件中有效(即class保留)
RUNTIME

在運行時有效(即運行時保留)

爲Runtime能夠被反射機制讀取

 

  (3)@Documented

  (4)@Inherited

Eg:

@Target(value=ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation01 {
    String studentName() default "";
    int age() default 0;
    String[] value();
}

5.ORM(Object relationship Mapping)對象關係映射

    類和表結構對應

    屬性和字段對應

    對象和記錄對應

@Target(value=ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtTable {
    String value();
}

@Target(value=ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtField {
    String columnName();
    String type();
    int length();
}

@SxtTable("tb_student")
public class Student {
    
    @SxtField(columnName="id",type="int",length=10)
    private int id;
    @SxtField(columnName="sname",type="varchar",length=10)
    private String studentName;
    @SxtField(columnName="age",type="int",length=3)
    private int age;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getStudentName() {
        return studentName;
    }
    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

/**
 * 使用反射讀取註解的信息,模擬處理註解信息的流程
 * @author MA
 *
 */
public class Demo3 {
    public static void main(String[] args) throws NoSuchFieldException, SecurityException {
        try {
            Class clazz = Class.forName("com.mxj.test.annotation.Student");
            
            //得到類的全部註解
            Annotation[] annotations = clazz.getAnnotations();
            for(Annotation a:annotations){
                System.out.println(a);
            }
            
            //得到類的指定的註解
            SxtTable table = (SxtTable) clazz.getAnnotation(SxtTable.class);
            System.out.println(table.value());
            
            //得到類的屬性的註解
            Field f = clazz.getDeclaredField("studentName");
            SxtField sxtField = f.getAnnotation(SxtField.class);
            System.out.println(sxtField.columnName()+"---"+sxtField.type()+"---"+sxtField.length());
        
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

6.反射機制 reflection

   反射機制指的是能夠在運行時加載、探知、使用編譯期間徹底未知的類。程序在運行狀態中,能夠動態加載一個只有名稱的類,對於任意一個已加載的類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;

  Class c = Class. forName ("com.mxj.test.User");
  加載完類以後,在堆內存中,就產生了一個 Class 類型的對象(一個類只有一個 Class 對象),這個對象就包含了完整的類的結構信息。咱們能夠經過這個對象看到類的結構。這個對象就像一面鏡子,透過這個鏡子看到類的結構,因此,咱們形象的稱之爲:反射。

/**
 * 應用反射的API,獲取類的信息(類的名字,屬性,方法,構造器等)
 * @author MA
 *
 */
public class Demo02 {
    public static void main(String[] args) throws Exception {
        String path = "com.mxj.test.bean.User";
        
        try {
            Class clazz = Class.forName(path);
            
            //獲取類的名字
            System.out.println(clazz.getName());//得到包名+類名
            System.out.println(clazz.getSimpleName());//得到類名:User
            
            //得到屬性信息
            //Field[] fields = clazz.getFields();//只能得到public的屬性
            Field[] fields = clazz.getDeclaredFields();//得到全部的field
            Field f = clazz.getDeclaredField("uname");  
            //得到方法信息
            Method[] method = clazz.getDeclaredMethods();
            Method m01 = clazz.getDeclaredMethod("getUname", null);
            Method m02 = clazz.getDeclaredMethod("setUname", String.class);
            //得到構造器信息
            Constructor[] constructors = clazz.getDeclaredConstructors();//得到全部構造器
            Constructor c1 = clazz.getDeclaredConstructor(null);//獲取無參構造器
            Constructor c2 = clazz.getDeclaredConstructor(int.class,int.class,String.class);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 經過反射API動態的操做:構造器、方法、屬性
 * @author MA
 *
 */
public class Demo03 {
    public static void main(String[] args) {
        String path = "com.mxj.test.bean.User";
        
        try {
            Class clazz = Class.forName(path);
            
            //經過動態調用構造方法,構造對象
            User u1 = (User) clazz.newInstance();//其實調用了User的無參構造方法
        
            Constructor<User> c= clazz.getConstructor(int.class,int.class,String.class);
            User u2 = c.newInstance(1001,18,"22");
        
            //經過反射API調用普通方法
            User u3 = (User) clazz.newInstance();
            Method method = clazz.getDeclaredMethod("setUname", String.class);
            method.invoke(u3, "333");
            
            //經過反射API操做屬性
            User u4 = (User) clazz.newInstance();
            Field f = clazz.getDeclaredField("uname");
            f.setAccessible(true);//這個屬性不用作安全檢查(private),能夠直接訪問
            f.set(u4, "4444");        //經過反射直接寫屬性
            System.out.println(u4.getUname());//經過對象調用
            System.out.println(f.get(u4));//經過反射直接讀屬性
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

反射機制性能問題:

  setAccessible啓用和禁用訪問安全檢查的開關,值爲true則反射的對象在使用時應該取消java語法訪問檢查,值爲false則反射的對象應該實施java語言訪問檢查。禁止安全檢查,能夠提升反射的運行速度。

 7.動態編譯

  應用場景:上傳服務器編譯和運行的在線評測系統

        服務器動態加載某些類文件進行編譯

  動態編譯的兩種作法:

(1)經過Runtime調用javac,啓動新的進程去操做

Runtime run = Runtime.getRuntime();
Process process = run.exec("javac -cp d:/myjava/ HelloWorld.java");

(2)經過javaCompiler動態編譯

public class Demo01 {
    public static void main(String[] args) {
JavaCompiler compiler
= ToolProvider.getSystemJavaCompiler(); int result = compiler.run(null, null, null, "D:/HelloWorld.java"); System.out.println(result==0?"編譯成功":"編譯失敗"); } }

動態運行編譯好的類:

(1)經過Runtime. getRuntime() 運行啓動新的進程運行

Runtime run = Runtime.getRuntime();
Process process = run.exec("java -cp d:/myjava HelloWorld");
// Process process = run.exec("java -cp "+dir+" "+classFile);

(2)經過反射運行編譯好的類

//經過反射運行程序
public static void runJavaClassByReflect(String dir,String classFile) throws Exception{
    try {
        URL[] urls = new URL[] {new URL("file:/"+dir)};
        URLClassLoader loader = new URLClassLoader(urls);
        Class c = loader.loadClass(classFile);
        //調用加載類的main方法
        Method m = c.getMethod("main",String[].class);
     m.invoke(null, (Object)newString[]{}); } catch (Exception e) { e.printStackTrace(); } }

 8.java腳本引擎(JDK6.0以後添加的新功能)
腳本引擎介紹:

  • 使得 Java 應用程序能夠經過一套固定的接口與各類腳本引擎交互,從而達到在 Java 平臺上調用各類腳本語言的目的。
  • Java 腳本 API 是連通 Java 平臺和腳本語言的橋樑。
  • 能夠把一些複雜異變的業務邏輯交給腳本語言處理,這又大大提升了開發效率。
/**
 * 測試腳本引擎執行javascript代碼
 * @author MA
 *
 */
public class Demo01 {
    public static void main(String[] args) throws Exception {
        //得到腳本引擎對象
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("JavaScript");
        
        //定義變量,存儲到引擎上下文中
        engine.put("msg", "HelloWorld!");
        String str = "var user = {name:'mxj',age:18,schools:['清華大學','sau']};";
        str += "print(user.name);";
        
        //執行腳本
        engine.eval(str);    
        engine.eval("msg = '12455';");
        System.out.println(engine.get("msg"));
        System.out.println("###################");
        
        
        //定義函數
        engine.eval("function add(a,b){var sum = a+b; return sum;}");
        //取得調用接口
        Invocable jsInvoke = (Invocable) engine;
        //執行腳本中定義的方法
        Object result = jsInvoke.invokeFunction("add",new Object[]{13,20});
        System.out.println(result);
    
        //導入其餘java包,使用其餘包中的java類
        String jsCode = "var list=java.util.Arrays.asList([\"1232\",\"mxj\",\"hello\"]);";
        engine.eval(jsCode);
        
        List<String> list2 = (List<String>) engine.get("list");
        for(String temp : list2){
            System.out.println(temp);
        }
        
        //執行一個js文件
        URL url = Demo01.class.getClassLoader().getResource("a.js");
        engine.eval(new FileReader(url.getPath()));
    }
}

 

2019.5.22

1.java動態性的兩種常見實現方式

  字節碼操做:比反射開銷小,性能高

  反射

2.JAVAssist庫的簡單使用

/**
 * 測試使用javassist生成一個新的類
 * @author MA
 *
 */
public class Demo01 {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.makeClass("com.mxj.bean.Emp");
    
        //建立屬性
        CtField f1 = CtField.make("private int empno;", cc);
        CtField f2 = CtField.make("private String ename;", cc);
        cc.addField(f1);
        cc.addField(f2);
        
        //建立方法
        CtMethod m1 = CtMethod.make("public int getEmpno(){return empno;}", cc);
        CtMethod m2 = CtMethod.make("public void setEmpno(int empno){this.empno = empno;}", cc);
        cc.addMethod(m1);
        cc.addMethod(m2);
        
        //添加構造器
        CtConstructor constructor = new CtConstructor(new CtClass[]{CtClass.intType,pool.get("java.lang.String")}, cc);
        constructor.setBody("{this.empno=empno;this.ename=ename;}");
        cc.addConstructor(constructor);
        
        cc.writeFile("D:\\develop\\xuexi\\TestJavassist");//將構建好的類寫入到工做空間
        System.out.println("生成類成功");
    }
}
    

 

2019.5.30

1.單例模式

(1)單例模式的優勢:
  因爲單例模式只生成一個實例,減小了系統性能開銷,當一個對象的產生須要比較多的資源時,如讀取配置、產生其餘依賴對象時,則能夠經過在應用啓動時直接產生一個單例對象,而後永久駐留內存的方式來解決單例模式能夠在系統設置全局的訪問點,優化環共享資源訪問,例如能夠設計一個單例類,負責全部數據表的映射處理

(2)常見的五種單例模式實現方式:
  主要:
  • 餓漢式(線程安全,調用效率高。 可是,不能延時加載。)
  • 懶漢式(線程安全,調用效率不高。 可是,能夠延時加載。)
  其餘:
  • 雙重檢測鎖式(因爲JVM底層內部模型緣由,偶爾會出問題。不建議使用)
  • 靜態內部類式(線程安全,調用效率高。 可是,能夠延時加載)
  • 枚舉式(線程安全,調用效率高,不能延時加載。而且能夠自然的防止反射和反序列化漏洞!)
(3)如何選用?
  單例對象 佔用 資源 少,不須要 延時加載:枚舉式 好於 餓漢式
  單例對象 佔用 資源 大,須要 延時加載:靜態內部類式 好於 懶漢式

(4)雙重檢測鎖實現

public class SingletonDemo03 {
  private static SingletonDemo03 instance = null;
  public static SingletonDemo03 getInstance() {
    if (instance == null) {
      SingletonDemo03 sc;
      synchronized (SingletonDemo03.class) {
        sc = instance;
        if (sc == null) {
          synchronized (SingletonDemo03.class) {
            if(sc == null) {
              sc = new SingletonDemo03();
            }
          }
    instance = sc;
    }
  }
}
  return instance;
}
  private SingletonDemo03() {
  }
}

(5)靜態內部類實現方式(也是一種懶加載方式)

public class SingletonDemo04 {
  private static class SingletonClassInstance {
    private static final SingletonDemo04 instance = new SingletonDemo04();
  }
  public static SingletonDemo04 getInstance() {
    return SingletonClassInstance.instance;
  }
  private SingletonDemo04() {
  }
}

(6) 使用枚舉實現單例模式

public enum SingletonDemo05 {
    /**
    *  定義一個枚舉的元素,它就表明了Singleton 的一個實例。
    */
    INSTANCE;
    /**
    *  單例能夠有本身的操做
    */
    public void singletonOperation(){
    // 功能處理
    }
}
public static void main(String[] args) {
    SingletonDemo05 sd = SingletonDemo05.INSTANCE;
    SingletonDemo05 sd2 = SingletonDemo05.INSTANCE;
    System.out.println(sd==sd2);
}

 (7) 反射能夠破解上面幾種(不包含枚舉式)實現方式!(能夠在構造方法中手動拋出異常控制)

public class SingletonDemo01 implements Serializable {
    private static SingletonDemo01 s;
    private SingletonDemo01() throws Exception{
        if(s!=null){
            // 經過手動拋出異常,避免經過反射建立多個單例對象!
           throw new Exception(" 只能建立一個對象");
       
        }
    } //私有化構造器
}                

(8)反序列化能夠破解上面幾種((不包含枚舉式))實現方式!(能夠經過定義readResolve()防止得到不一樣對象)

   反序列化時,若是對象所在類定義了readResolve(),(實際是一種回調),定義返回哪一個對象。

public class SingletonDemo01 implements Serializable {
    private static SingletonDemo01 s;

    public static synchronized SingletonDemo01 getInstance() throws Exception{
       if(s!=null){
            // 經過手動拋出異常,避免經過反射建立多個單例對象!
            throw new Exception(" 只能建立一個對象");
        }
        return s;
  }

  //反序列化時,若是對象所在類定義了readResolve() ,(實際是一種回調),定義返回哪一個對象。 private Object readResolve() throws ObjectStreamException { return s; } }

 2.工廠模式

(1)工廠模式:
  實現了建立者和調用者的分離。
  詳細分類:
    簡單工廠模式:用來生產同一等級結構中的任意產品
    工廠方法模式:用來生產同一等級結構中的固定產品
    抽象工廠模式:用來生產不一樣產品族的所有產品

(2)核心本質:

   實例化對象,用工廠方法代替new操做。
  將選擇實現類、建立對象統一管理和控制。從而將調用者跟咱們的實現類解耦。
(3)面向對象設計的基本原則:
  OCP(開閉原則,Open-Closed Principle):一個軟件的實體應當對擴展開放,對修改關閉。
  DIP(依賴倒轉原則,Dependence Inversion Principle):要針對接口編程,不要針對實現編程。
  LoD(迪米特法則,Law of Demeter):只與你直接的朋友通訊,而避免和陌生人通訊。

3.適配器adapter模式

(1)什麼是適配器模式?
  將一個類的接口轉換成客戶但願的另一個接口。Adapter模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠在一塊兒工做。
(2)模式中的角色

  目標接口(Target):客戶所期待的接口。目標能夠是具體的或抽象的類,也能夠是接口。
  須要適配的類(Adaptee):須要適配的類或適配者類。
  適配器(Adapter):經過包裝一個須要適配的對象,把原接口轉換成目標接口。

類適配器:

class Adapter extends Adaptee implements Target{
    public void request() {
        super.specificRequest();
    }
}    

對象適配器:

class Adapter implements Target{
    private Adaptee adaptee;
    public Adapter (Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    public void request() {
        this.adaptee.specificRequest();
    }
}    

 2019.6.3

1.MySQL數據庫的命令操做

  • 配置環境變量

    將bin目錄配置到path中

  • 命令行操做
登錄操做 mysql -hlocalhost –uroot –p123456
退出操做 exit
數據庫操做 建庫:create database 庫名;
卸載庫:drop database 庫名;
顯示全部數據庫:show databases;
選擇庫:use testjdbc;
表操做 建表的sql語句;
顯示庫中全部表:show tables;
顯示某個表的結構:describe testjdbc;
SQL操做 select語句;Insert語句; update語句; delete語句;
表操做DDL語句(create, alter, drop等);

2.什麼是JDBA?

  JDBC(Java Database Connection)爲java開發者使用數據庫提供了統一的編程接口,它由一組java類和接口組成。是java程序與數據庫系統通訊的標準API。JDBC API 使得開發人員可使用純java的方式來鏈接數據庫,並執行操做。

3.JDBC經常使用接口

(1) Driver接口

  Driver接口由數據庫廠家提供,對於java開發者而言,只須要使用Driver接口就能夠了。
  在編程中要鏈接數據庫,必須先裝載特定廠商的數據庫驅動程序。不一樣的數據庫有不一樣的裝載方法。
  驅動:就是各個數據庫廠商實現的Sun公司提出的JDBC接口。 即對Connection等接口的實現類的jar文件
  裝載MySql驅動

     Class.forName("com.mysql.jdbc.Driver");
  裝載Oracle驅動
    Class.forName("oracle.jdbc.driver.OracleDriver");

(2)DriverManager接口

   DriverManager是JDBC的管理層,做用於用戶和驅動程序之間。

   DriverManager跟蹤可用的驅動程序,並在數據庫和相應的驅動程序之間創建鏈接。

(3)Connection接口

  Connection與特定數據庫的鏈接(會話),在鏈接上下文中執行 SQL語句並返回結果。     

  DriverManager的getConnection()方法創建在JDBC URL中定義的數據庫Connection鏈接上
  鏈接MYSQL數據庫:
    Connection con =
      DriverManager.getConnection("jdbc:mysql://host:port/database","user","password");
  鏈接ORACLE數據庫:
    Connection con =
      DriverManager.getConnection("jdbc:oracle:thin:@host:port:databse","user","password");

(4) Statement接口

  用於執行靜態 SQL 語句並返回它所生成結果的對象。
  三種Statement類:
    • Statement:
      由createStatement建立,用於發送簡單的SQL語句。(不帶參數的)
    • PreparedStatement:
      繼承自Statement接口,由prepareStatement建立,用於發送含有一個或多個輸入參數的sql語句。PreparedStatement對象比Statement對象的效率更高,而且能夠防止SQL注入。咱們通常都用PreparedStatement.
    • CallableStatement:
      繼承自PreparedStatement 。由方法prePareCall建立,用於調用存儲過程。
  經常使用的Statement方法:
    • execute():運行語句,返回是否有結果集。
    • executeQuery():運行select語句,返回ResultSet結果集。
    • executeUpdate():運行insert/update/delete操做,返回更新的行數。

(5)ResultSet接口

   Statement執行SQL語句時返回ResultSet結果集。

   ResultSet提供的檢索不一樣類型字段的方法,經常使用的有:
    • getString():得到在數據庫裏是varchar、char等數據類型的對象。
    • getFloat():得到雜數據庫裏是Float類型的對象。
    • getDate():得到在數據庫裏面是Date類型的數據。
    • getBoolean():得到在數據庫裏面是Boolean類型的數據

  依序關閉使用之對象及鏈接:ResultSet -》Statement-》 Connection

/**
 * 測試PreparedStatement的基本用法
 * @author MA
 *
 */
public class Demo03 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //加載驅動類
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456"); 
            
            String sql="insert into t_user(username,pwd)values(?,?);"; //?佔位符
            ps = (PreparedStatement) conn.prepareStatement(sql);
            ps.setString(1, "mxj"); //參數索引從1開始計算
            ps.setString(2, "123456");
            
            ps.execute();
        } catch (Exception e) {        
            e.printStackTrace();
        }finally{
            if(ps!=null){
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
/**
 * 測試resultSet結果集的基本用法
 * @author MA
 *
 */
public class Demo04 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //加載驅動類
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456"); 
            
            String sql="select id,username,pwd from t_user where id > ?"; 
            ps = (PreparedStatement) conn.prepareStatement(sql);
            ps.setObject(1, 2); 
            
            rs = ps.executeQuery();
            while(rs.next()){
                System.out.println(rs.getInt(1)+"---"+rs.getString(2)+"---"+rs.getString(3));
            }
        } catch (Exception e) {        
            e.printStackTrace();
        }finally{
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(ps!=null){
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 4.批處理

/**
 * 批處理的基本用法
 * @author MA
 *
 */
public class Demo05 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //加載驅動類
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456"); 
            
            conn.setAutoCommit(false);//設置手動提交
            stmt = (Statement) conn.createStatement();
            
            for(int i=0;i<20000;i++){
                stmt.addBatch("insert into t_user(username,pwd,regTime)values('ma"+i+"',666666,now())");
            }
            stmt.executeBatch();
            conn.commit();
            
            
        } catch (Exception e) {        
            e.printStackTrace();
        }finally{
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 5.事務的基本概念

   一組要麼同時執行成功,要麼同時執行失敗的SQL語句。是數據庫操做的一個執行單元!

(1)事務的四大特色(ACID)

  atomicity(原子性)
    • 表示一個事務內的全部操做是一個總體,要 麼所有成功,要麼全失敗;        

    consistency(一致性)
    • 表示一個事務內有一個操做失敗時,全部的更改過的數據都必須回滾到修改前的狀態;
  isolation(隔離性)
    • 事務查看數據時數據所處的狀態,要麼是另外一併發事務修改它以前的狀態,要麼是另外一事務修改它以後的狀態,事務不會查看中間狀態的數據。
  durability(持久性)
    • 持久性事務完成以後,它對於系統的影響是永久性的。

(2)事務隔離級別從低到高:

  讀取未提交(Read Uncommitted)  讀取已提交(Read Committed)  可重複讀(Repeatable Read)  序列化(serializable)

相關文章
相關標籤/搜索