再看Java之溫故知新(體系篇)

再看Java之溫故知新(體系篇)
目錄

一 數據類型

1.1 8種基本數據類型

1.2 引用數據類型

1.3 java內存機制 

1.3.1 寄存器

1.3.2 棧

1.3.3 堆

1.3.4. 靜態區/方法區

1.3.5. 常量池/運行時常量池(Runtime Constant Pool)

二:面向對象思想

2.1封裝

2.2 繼承

2.3 多態

2.3.1 方法重載(Overloading)

2.3.2 方法覆蓋(Overriding)

2.4 抽象

2.4.1 抽象類

2.4.2 接口

2.4.3 接口和抽象類區別

三 特殊類

3.1實名內部類

3.2 匿名內部類

3.3 內部類的好處

3.3.1 進一步實現多重繼承(通過內部類實現多類繼承)

3.3.2  更好解決接口和父類中的方法同名問題

3.3.3 隱藏內部細節、無條件訪問外部類成員

3.4 泛型類

3.5 class類

四 數組/字符串/枚舉

4.1 數組

4.2 字符串

4.3 枚舉

五 JAVA常用類/接口

5.1 java.lang包

5.1.1 Object類

5.1.2 Math類

5.1.3 System類

5.1.4 Runtime類

5.2 java.util包

5.2.1 Date類

5.2.2 Calendar類

5.2.3 Random類 

5.2.4 集合

六 集合 

6.1 有序可重複集合:List接口和ArrayList/LinkedList/Vector類

6.1.1 Arraylist類

6.1.2 LinkedList類

6.1.3 Vector類

6.2  非重複集合:Set接口和HashSet、TreeSet、LinkedHashSet類 

6.4 映射集合:Map接口和TreeMap類

6.4.1 TreeMap     

七 多線程

7.1 實現多線程的兩種方法   

7.1.1 繼承Thread類

7.1.2 實現Runable接口 

7.2   線程常用的控制方法

7.4 線程互斥同步

7.4.1 同步語句塊實例

7.4.2 同步化方法實例 

7.4 後臺線程

八:java 流和文件

8.1 字節流/字符流介紹

8.1.1 字節流

8.1.2 字符流

8.1.3 字符緩衝流

8.1.4 字節流字符流異同

8.2 文件

8.3 對象序列化

九 網絡編程

9.1 URL編程

9.1.1 URL類

9.1.2 URLConnection

9.2 Socket編程

9.3 Socket和URLConnection的異同

一 數據類型

1.1 8種基本數據類型
布爾  (1字節)

char   (2字節)

byte,short,int,long   (1字節,2字節,4字節,8字節)

float,doule  (4字節精確到7位有效數字,8字節精確到16位有效數字)

  • Java常量:

正無窮 Double.POSITIVE_INFINITY

負無窮 Double.NEGATIVE_INFINITY

不是個數 Double.NaN

  • 爲什麼分基本數據類型和引用數據類型?

答:基本數據類型使用極高,因此設計爲非對象類型,放棧中,使其存取速度快於堆中類對象。

1.2 引用數據類型
引用數據類型包括:類、接口、數組

1.3 java內存機制 

JVM內存 = 堆內存 + 線程數量 * 棧內存

java內存可分爲:

1.3.1 寄存器
我們在程序中無法控制,分支、跳轉、循環、異常處理、線程恢復都依賴程序計數器實現;每個線程都有一個單獨的程序計數器,所以程序計數器是私有的;

1.3.2 棧
存放局部變量(方法執行完會馬上釋放局部變量所佔棧空間,如果是引用數據類型,同樣地,句柄回收掉,堆中的具體對象失去引用會被GC掉)。

存放基本類型的數據和對象的引用,引用的對象放在堆中。

棧中的數據大小與生存期必須是確定的,因此速度快,但缺乏靈活性。

棧有一個很重要的特殊性,就是存在棧中的數據可以共享,每個線程對應着一個虛擬機棧,因此虛擬機棧也是線程私有的,虛擬機棧生命週期與線程相同。

*棧一般指虛擬機棧,還有本地方法棧。本地方法棧與java虛擬機棧所發揮的作用非常相似,它們之間的區別在於java虛擬機棧執行java方法服務的, 本地方法棧是執行本地方法服務的

1.3.3 堆
存放用new產生的數據

堆區也是Java GC機制所管理的主要內存區域,堆區由所有線程共享,

1.3.4. 靜態區/方法區
被所有線程共享區域,用於存放已被虛擬機加載的類信息,常量,靜態變量等數據。

被Java虛擬機描述爲堆的一個邏輯部分。

垃圾回收很少光顧這個區域,不過也是需要回收的,主要針對常量池回收,類型卸載。

*static 修飾的靜態變量,什麼時候被回收?
答:類被加載的時候,靜態變量被分配內存,並且在虛擬機中單獨佔用內存,靜態變量在類被卸載的時候纔會被銷燬,而類只有在進程結束的時候纔會被卸載,也就是說被static修飾的靜態變量只有在進程被銷燬的時候纔會被回收

 

1.3.5. 常量池/運行時常量池(Runtime Constant Pool)
Class 文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量池(Constant Pool Table), 用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載後存放到方法區的運行時常量池中。final修飾的對象就會放到常量池;

二:面向對象思想
2.1封裝
private

default

peotected

public

2.2 繼承
只能單繼承,只能繼承父類非private成員變量/方法,父類同名成員變量/方法會被覆蓋;(非要用用super關鍵字)

允許向上轉型;

2.3 多態
2.3.1 方法重載(Overloading)
2.3.2 方法覆蓋(Overriding)
只能重寫方法體;同一類的中方法只能重寫不能覆蓋;父私有的方法沒法覆蓋;父final方法沒法覆蓋;

2.4 抽象
2.4.1 抽象類
抽象類:包含抽象方法的類。eg:動物就是一個抽象類,老虎獅子猴子人都是這個抽象類的具體實現的派生類。

抽象類中還可以有成員變量,具體方法,構造方法等,但是他絕對包含抽象方法,設計出來就是爲了讓子類繼承實現的,所以不可能會有實例,也不可能用final修飾抽象類。

*在向上轉型過程中,向上轉型獲得的對象,在調用方法時,如果子類存在與父類重名的方法,子類方法會覆蓋父類方法;同樣地,訪問變量時,子類方法無法覆蓋父類,該對象也訪問不到父類方法。

2.4.2 接口
接口中的方法不含方法體,只由常量和抽象方法組成;

接口中所有變量默認加public、static、final修飾符;

接口中所有方法默認加public、abstract修飾符;

接口不含構造方法;

多繼承;

*接口回調:接口就是個角色,實現這些接口的類就是演員,角色的語言和行爲方法等就是演員要說的臺詞和行爲。

接口回調其本質與上轉型是一樣的,不同的是:接口回調是用接口句柄來得到並調用實現這個接口的子類的引用;而上轉型則是用父類句柄來得到並調用繼承此父類的子類的引用。

2.4.3 接口和抽象類區別
接口多繼承,抽象類單繼承;接口只有常量和抽象方法,抽象類還可以有成員變量和具體成員方法;接口不是類體系一部分;

三 特殊類
3.1實名內部類
實名內部類不得與外部類同名;

實名內部類可以是抽象類/接口;

static修飾的實名內部類稱爲靜態實名內部類;

非靜態內部類不能有靜態方法/靜態屬性(java類加載順序是1首先加載類,2執行static變量初始化,3接下來執行對象的創建。如果我們要執行代碼中的變量int a 初始化,那麼必須先執行加載外部類,再加載內部類,最後初始化靜態變量 a ,問題就出在加載內部類上面,我們可以把內部類看成外部類的非靜態成員,它的初始化必須在外部類對象創建後以後進行,要加載內部類必須在實例化外部類之後完成 ,java虛擬機要求所有的靜態變量必須在對象創建之前完成,這樣便產生了矛盾。所以不允許非靜態內部類有靜態方法/靜態屬性)。

若有靜態屬性必須+final(而java常量放在內存中常量池,它的機制與變量是不同的,編譯時,加載常量是不需要加載類的,所以就沒有上面那種矛盾);

靜態內部類可以有靜態屬性和方法;

3.2 匿名內部類
給人的感覺就好像把抽象類當成正常類來使用,只不過實現了方法體,並且實際上完成了向上轉型;

3.3 內部類的好處
3.3.1 進一步實現多重繼承(通過內部類實現多類繼承)
class SuperA
{

public String SayHello(String s)
{
    return s + "  Hello";
}

}

class SuperB
{

public int calculation(int i)
{
    return ++i;
}

}

public class JInnerTest
{

private class JInnerTest1 extends SuperA
{

}

private class JInnerTest2 extends SuperB
{
    public int calculation(int i)
    {
        return super.calculation(i);
    }
}

public String SayHello(String s)
{
    return new JInnerTest1().SayHello(s);
}

public int calculation(int i)
{
    return new JInnerTest2().calculation(i);
}

public static void main(String args[])
{
    JInnerTest test = new JInnerTest();
    System.out.println(test.SayHello("Lucas"));
    System.out.println(test.calculation(100));
}

}
3.3.2  更好解決接口和父類中的方法同名問題
interface JPet6
{

void name();

}

class JSmallAnimal
{

public void name()
{
    System.out.println("class: JSmallAnimal---method: name");
}

}

public class JCat6 extends JSmallAnimal
{

private class JCatInner implements JPet6
{
    public void name()
    {
        System.out.println("class: JCat6.JCatInner---method: name");
    }
}

public static void main(String args[])
{
    JCat6 cat = new JCat6();
    cat.name();
    cat.new JCatInner().name();
}

}
3.3.3 隱藏內部細節、無條件訪問外部類成員
3.4 泛型類
泛型的本質是參數化類型,這種參數類型用在類中,該類就稱爲泛型類。

public class JGeneric{}
public class JGeneric{}
3.5 class類
class類能很好地結合java反射技術結合。

四 數組/字符串/枚舉
4.1 數組
數組對象的引用(首地址array(0)的值)存放在棧中,堆中存放數據具體值;二維數組中,一維的值存放在堆中,堆中一維數組再指向堆中二維數組的值所在的地址。

4.2 字符串
String s = 'hello',  'hello'存放在棧空間的字符串常量池中;

String s2 = 'hello',   s2同樣指向字符串常量池中的s所指向的‘hello’;

String s3 = new String('hello'),   s3會在堆內存中開闢一個空間,裏面存:“hello”;

String s4 = new String('hello'), s4同樣會在堆內存中開闢一個新空間,存hello,不和s3同引用;

String類型變量所指向的內存空間內容是不能被改變的;StringBuffer類型變量所指向的內存空間內容是可以被改變的;

4.3 枚舉
枚舉繼承了java.lang.Enum類,所以不能繼承其他父類,但是可以實現接口和添加方法;

public enum Color{
RED;
WHITE;
BLACK;
}
五 JAVA常用類/接口
5.1 java.lang包
java.lang包包含大多數常用的基本類,默認import的。

5.1.1 Object類
5.1.2 Math類
Math類中的所有方法和屬性都是靜態,且該類是final(Math類只能使用,不允許更改)

Math.random(): 產生(0,1)的隨機數

5.1.3 System類
System.exit(),退出當前java虛擬機;

System.arraycopy(), 從一個數組複製到另一個數組;

System.gc(), 主動對垃圾內存進行回收;

System.currentTimeMillis(), 返回當前時間,毫秒爲單位;

System.Nanotime(), 返回當前時間,毫微秒爲單位;

System的三個靜態變量:System.InputStream in;(鍵盤)    System.PrintStream out;(終端)  System.PrintStream err;(屏幕)

5.1.4 Runtime類
一個虛擬機對應一個Runtime實例對象,通過下述方式啓動的進程稱爲該進程的子進程;

Process p = Runtime.getRuntime().exec("notepad.exe c://count.txt");
Runtime類的常用方法還有freeMemory();totalMemory();

Runtime r = Runtime.getRuntime();
空閒空間:r.freemomery()/1024+"KB"
總空間:r.totalmomery()/1024+"KB"
5.2 java.util包
java.util包下包括常用的日期類Date/Calendar,隨機數類Random,集合映射等;

5.2.1 Date類
Date d = new Date();
5.2.2 Calendar類
獲得Calendar類:

Calendar c = Calendar.getInstance();
設置Calendar的日期:

c.set(Calendar.YEAR, 2019);
c.set(Calendar.MONTH, 2);
c.set(Calendar.DATE, 19);
獲得Calendar中的具體日期:
 

c.get(Calendar.YEAR);
c.get(Calendar.MONTH)+1;
c.get(Calendar.DATE);
在當前日期上增加日期:

//計算當前時間100天后的日期
c.add(Calendar.DATE, 100);
判斷日期在某日期前/後:

c.after(c1);
c.before(c2);
獲得long型時間戳,/根據long型時間戳設置Calendar:

c.getTimeInMillis();
c.setTimeInMillis(long millis);
*時間類型的相互裝換:

Calendar轉Date:                                                                                                                                                                                        
Date d = c.getTime();
 

Date轉long型時間戳:                                                                                                                                                                                
long timestamp = date.getTime();
 

時間戳轉date:                                                                                                                                                                                           
Date date = new Date(long mylong);
 

date轉String:                                                                                                                                                                                              
//獲取當前的日期
Date date = new Date();
//設置要獲取到什麼樣的時間
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//獲取String類型的時間
String createdate = simpleDateFormat.format(date);
String轉date:                                                                                                                                                                                             
SimpleDateFormat simpleDateFormat = newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time="1970-01-06 11:45:55";
Date date = simpleDateFormat.parse(time);
System.out.print("Format To times:"+date.getTime());
date轉Calendar :                                                                                                                                                                                    
Date date=new Date();
Calendar cal=Calendar.getInstance();
cal.setTime(date);                                                                            
                                                                                                                                                                                                                
 

5.2.3 Random類 
Random r = new Random();
r.nextBoolean();//生產50%概率的true和false;
r.nextDouble();//生成[0,1.0)之間的double類型隨機數
r.nextInt(int n);//生成[0,n)區間的隨機int數
5.2.4 集合
詳見C6

六 集合 
        Java的集合類主要由兩個接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口。Java集合大致可以分爲Set、List、Queue和Map四種體系,其中Set代表無序、不可重複的集合;List代表有序、重複的集合;而Map則代表具有映射關係的集合,Java 5 又增加了Queue體系集合,代表一種隊列集合實現。

 類關係圖:                                                                                                                                                                     

6.1 有序可重複集合:List接口和ArrayList/LinkedList/Vector類
      list表示有序集合,其中的元素可以重複;

6.1.1 Arraylist類
       ArrayList採用可變大小的“數組”實現List接口,ArrayList對象會隨着元素的增加自動擴大其容器。舉例的常見的三種List實現類中,該類最常見且效率最高。

      常見方法:get();   set();   add();    remove();

6.1.2 LinkedList類
       LinkedList採用鏈表結構實現List接口,提供了再List開頭和結尾進行get、remove和insert的操作,以便實現堆棧、隊列或雙端隊列;LinkedList的數據結構是一個雙向鏈式結構,沒一個對象除了本身外帶一個指向前一個元素和後一個元素的引用,因此特性,它相比順序存儲結構ArrayList,插入和刪除比較方便,但速度會慢些。  

6.1.3 Vector類
vector採用可變體積的數組實現List接口,但向量中不能存放基本數據與類型的數據,加入的數據必須均爲對象。

常見方法:addElement(Object object);   removeElement(Object object);  removeElementAt(int index);   removeAllElements(); insertElementAt(Object object, int index);       

6.2  非重複集合:Set接口和HashSet、TreeSet、LinkedHashSet類 
set接口表示的集合不能有重複元素。

HashSet採用Hash表實現set接口,HashSet對象中的元素存在Hash表中;
TreeSet採用有序樹的結構存儲集合中元素,TreeSet對象中元素按照升序排列;
LinkedHashSet採用Hash表和鏈表相結合的方式存儲集合中的元素,既保證了集合中元素順序又具有較高存取效率。   
6.4 映射集合:Map接口和TreeMap類
key-value:Map集合會把鍵值映射到某一個值上。

主要方法:

Object put (Object key, Oblect value);

Object remove (Object key);

Boolean containsKey(Object key);

Boolean containsValue(Object value);

int size();

boolean isEmpty();

void putAll(Map t);

6.4.1 TreeMap     
TreeMap與TreeSet類似,採用有序樹的結構實現了Map的子接口SortedMap,按鍵的升序排列元素。   

七 多線程
7.1 實現多線程的兩種方法   
        Thread類實際上也是實現Runable接口實現的,繼承Thread類可以輕鬆獲取當前線程信息:this.getName();實現Runable接口獲取當前線程信息:Thread.currentThread();          

7.1.1 繼承Thread類
7.1.2 實現Runable接口 
7.2   線程常用的控制方法
線程睡眠(阻塞狀態):Thread.sleep(long millis);

線程喚醒:Thread.interrupt();

線程讓步(讓是讓了,但是誰獲得還是操作系統安排分配):Thread.yield();

線程等待:

Thread.join();等待這個線程運行完,再運行主程序中這行代碼下面的代碼

Thread.join(long millis); 主程序等待這個線程millis時長

7.4 線程互斥同步
        Java中,虛擬機通過給每個對象加鎖的方式實現多線程同步。Java虛擬機爲每個對象準備一把鎖(Lock)和等候集(Wait Set),確保任一對象同一時刻只能有一個訪問與該對象相關的同步語句塊和同步方法。

        synchoronized(obj){同步語句塊} 

        synchoronized void fun(){同步化方法的方法體}

7.4.1 同步語句塊實例
public class TestSynchronizedExample1 implements Runnable {

//一共十張票
private int ticket=10; 

public void run(){ 
    //一直賣票直到餘票爲0
    while(true) { 
        synchronized (this) { 
            if (ticket > 0) { 
                try { 
                    //爲了演示產生的問題,線程在這裏睡眠一次
                    Thread.sleep(10); 
                } catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
                //線程睡眠結束後,繼續當前的票進行銷售
                System.out.println(Thread.currentThread().getName()+"ÂôƱ-->"+(this.ticket--));
            } else { 
                break; 
            } 
        }
    }
} 

static public void main(String args[]) {
    //建立三個售票窗口 
    TestSynchronizedExample1 ru = new TestSynchronizedExample1(); 
    Thread t = new Thread(ru); 
    t.setName("窗口1");
    Thread t1 = new Thread(ru);
    t1.setName("窗口2");
    Thread t2 = new Thread(ru); 
    t2.setName("窗口3");
    t.start(); 
    t1.start(); 
    t2.start(); 
} 

}
7.4.2 同步化方法實例 
public class TestSynchronizedExample2 implements Runnable {

//一共十張票
private int ticket=10; 

public void run(){ 
    //賣票
    while(ticket>0) { 
        sell();
    }
} 

public synchronized void sell() {
    if (ticket > 0) {
        try { 
            //爲了演示問題,線程在這裏睡眠一次
            Thread.sleep(10); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
        //˯Ãß½áÊøºó£¬¼ÌÐøµ±Ç°µÄƱ½øÐÐÏúÊÛ
        System.out.println(Thread.currentThread().getName()+"ÂôƱ-->"+(this.ticket--));
    }
}

static public void main(String args[]) {//½¨Á¢Èý¸öÊÛƱ´°¿ÚµÄÏß³ÌÀàÀ´Ä£Äâ´°¿ÚÊÛƱ
     
    TestSynchronizedExample2 ru = new TestSynchronizedExample2(); 
    Thread t = new Thread(ru); 
    t.setName("窗口1");
    Thread t1 = new Thread(ru);
    t1.setName("窗口2");
    Thread t2 = new Thread(ru); 
    t2.setName("窗口3");
    t.start(); 
    t1.start(); 
    t2.start(); 
} 

}

7.4 後臺線程
後臺線程:Daemon線程。所有用Thread建立的線程都是前臺線程;main就是前臺線程;

前後臺線程的區別:進程中只要有前臺線程沒退出,進程就不會終止; 所有前臺線程都退出,哪怕現在還有後臺線程,進程也會自動結束;                                                                                  

主要方法:判斷是不是後臺線程:isDaemon();Thread類的setDaemon()來設置爲後臺線程;

八:java 流和文件
8.1 字節流/字符流介紹
java數據流都在java.io包中;

字節流1字節;常以InputStream和OutputStream爲基類;類名大多以Stream爲結尾;

字符流2字節;以Reader和Writer爲基類;類名大多以Reader和Writer爲結尾;

  • 所謂的in、out、 輸入、輸出,都是相對於內存而言的。

8.1.1 字節流
輸入字節流,InputStream的子類:FileInputStream; BufferdInputStream; DataInputStream;

FileInputStream in = new FileInputStream("d:/java/test.txt");

    // 定義一個int類型的變量b,記住每次讀取的一個字節
    int b = 0;
    while (b = in.read() != -1) {
        System.out.println((char) b);
    }
    in.close();

輸出字節流,OutputStream的子類:FileOutputStream; BufferedOutputStream; DataOutputStream; PrintStream;

//複製的源文件file1.txt
FileInputStream rf=new FileInputStream("G:/java1/TestVector.java");
//複製的目的文件file2.txt,若不存在,則會自動創建
FileOutputStream wf=new FileOutputStream("G:/java1/file2.txt");
byte b[]=new byte[512];
int count=-1;
while((count=rf.read(b, 0, 512))!=-1)//每次讀取512個字節到數組b中,read(byte[] b, int off, int len)返回實際讀取數量
wf.write(b,0,count);

rf.close();
wf.close();
8.1.2 字符流
輸入字符流,Reader的子類:BugfferdReader;FileReader;

//創建FileReader對象,用來讀取字符流

FileReader fr = new FileReader("G:/aillo.txt"); 
//緩衝指定文件的輸入
BufferedReader br = new BufferedReader(fr); 
//創建FileWriter對象,用來寫入字符流
FileWriter fw = new FileWriter("G:/jacky.txt"); 
//將緩衝對文件的輸出
BufferedWriter bw = new BufferedWriter(fw); 
String strLine;//定義一個String類型的變量,用來每次讀取一行
while (br.ready()) {
    strLine = br.readLine();//讀取一行
    bw.write(strLine); //寫入文件
    bw.newLine();
    System.out.println(strLine);//在屏幕上輸出
}
bw.flush();    //刷新該流的緩衝,即將該流輸出到目的
bw.close();
br.close();
fw.close();
br.close();
fr.close();

輸出字符流,Writer的子類:FileWriter; BufferedWriter;

char c[] = new char[512];

    int n, i;
    try {
        FileWriter wf = new FileWriter("TestFileOutCH.txt");
        // 利用InputStreamReader正確的讀取中文
        System.out.print("請輸入中文:");
        InputStreamReader isr = new InputStreamReader(System.in);
        n = isr.read(c, 0, 512);
        wf.write(c);
        wf.close();

        System.out.println("剛輸入的數據爲:"+String.valueOf(c,0,n));
    } catch (IOException e) {
        System.out.println(e);
    }

8.1.3 字符緩衝流
BufferedReader和BufferedWriter以類似緩衝區方式對數據進行輸入輸出,他們分別擁有8192個字符;

/緩衝System.in輸入流
//System.in是字節流,通過InputStreamReader將其轉換爲字符流
BufferedReader bufReader = new BufferedReader(new InputStreamReader(System.in));
//緩衝FileWriter
BufferedWriter bufWriter = new BufferedWriter(new FileWriter(args[0]));

String input = null;

//每讀一行進行一次寫入動作
while(!(input = bufReader.readLine()).equals("quit")){
bufWriter.write(input);
/*
newLine()方法寫入與操作系統相依的換行字符,依執行環境當時的OS來決定該輸出那種換行字符
*/
bufWriter.newLine();
}
bufReader.close();
bufWriter.close();
8.1.4 字節流字符流異同

  1. 字節流字符流本質區別在於byte(字節)和char(字符)的區別:字節流採用二進制編碼,字符流涉及到本地的編碼問題;網絡通信建議字節流;

2.字節流和字符流之間的轉化通過InputStreamReader和OutputStreamReader來關聯,實際上通過byte[]和String來關聯:

//byte轉String
public String (byte[] bytes, String charsetName)

//String轉byte
byte[] String.getBytes( String charsetName)

  1. 一個八位傳輸(1字節),一個16位傳輸(2字節);

8.2 文件
一些專門用於處理磁盤文件的類,常見的比如File類等。

8.3 對象序列化
目的:提供對象持久化的解決方案。

原理:把內存對象數據分解成字節流;反序列化就是打開字節流重構對象;

需求場景:內存對象保存到文件或者數據庫;通過Socket網絡傳輸對象;想通過RMI傳輸對象;

實現方法:對象繼承java.iio.Serializable類;

注意事項:序列化只保存對象的數據,方法和構造函數不被序列化(所以反序列化時需要指定恢復的對象類型);聲明爲static和transient的變量不能序列化。

九 網絡編程
9.1 URL編程
9.1.1 URL類
//構建一URL對象

        URL tirc = new URL("http://www.tsinghua.edu.cn/publish/th/index.html"); 
        BufferedReader in = new BufferedReader( new InputStreamReader(tirc.openStream(), "utf-8"));

        //使用openStream得到一輸入流並由此構造一個BufferedReader對象
        String inputLine;
        //從輸入流不斷的讀數據,直到讀完爲止
        while ((inputLine = in.readLine()) != null) {
            //把讀入的數據輸出到屏幕上
            System.out.println(inputLine); 
        }
        in.close(); //關閉輸入流

9.1.2 URLConnection
通過URL類的openStream()方法獲得;

向網絡輸出數據:通過URL類獲得URLConnection,建立了與URL的鏈接,而後向服務器端的CGI(公共網關接口)程序發送數據。

//創建一URL對象

    URL url = new URL("http://www.javasoft.com/cgi-bin/backwards");
    //由URL對象獲取URLConnection對象
    URLConnection connection = url.openConnection();
    connection.setDoOutput(true);
    //由URLConnection獲取輸出流,並構造PrintStream對象
    PrintStream ps = new PrintStream(connection.getOutputStream());
    //向服務器寫出字符串
    ps.println("123456");
    ps.close();
    //由URLConnection獲取輸入流,並構造DataInputStream對象
    DataInputStream dis = new DataInputStream(connection.getInputStream());
    String inputLine;
    //從服務器持續讀入,並顯示
    while((inputLine = dis.readLine())!=null) {
        System.out.println(inputLine);
    }
    dis.close();

9.2 Socket編程
Socket工作過程步驟:

1 創建Socket;

2 打開連接到Socket的輸入輸出流;

3 按照一定協議對Socket進行讀寫操作;

4 關閉Socket;

*主要類:Socket、SocketServer;

9.3 Socket和URLConnection的異同
        socket通信時,在服務器端運行一個socket通信程序,服務器端不停地監聽某個端口,等待客戶的連接申請,接到申請後建立連接並進行通信,所以,在socket通信方式中,服務器是主動等待連接通信的到來。

       URL通信時,在服務器端常駐一個CGI程序,但它一直處於休眠狀態。只有在客戶端要求建立連接時才被激活,然後與用戶進行通信。所以,在URL 通信方式中,服務器是被動等待連接通信的到來。

       利用socket進行通信時,服務器端的程序可以打開多個線程與多個客戶進行通信,還可以通過服務器使各個客戶之間進行通信。這種方式比較靈活,適用於一些較複雜的通信,但是服務器端的程序必須始終處於運行狀態以監聽端口。

       利用 URL進行通信時,服務器端的程序只能與一個客戶進行通信,形式比較單一。但是它不需要服務器端的CGI程序一直處於運行狀態,只是在有客戶申請時才被激活。所以,這種方式比較適用於客戶機的瀏覽器與服務器之間的通信。

    總之,Socket是底層實現,協議你要自己去寫,不侷限於http,可以是任何協議。而類似HttpClient, FtpClient,URLConnetcion之類的,是對專屬協議的封裝,當然由於部分實現原理,你可能無法完全控制連接操作,比如setTimeout這個參數。

Socket只是一個供上層調用的抽象接口,隱躲了傳輸層協議的細節。

urlconnection 基於Http協議,Http協議是應用層協議,對傳輸層Tcp協議進行了封裝,是無狀態協議,不需要你往考慮線程、同步、狀態治理等。

作者:許進進
來源:CSDN
原文:https://blog.csdn.net/LucasXu01/article/details/93022464
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章