@TOCjava
簡歷:技術(10W)+ 項目(20W)+ 算法(30W) + 業務(50~100W) + 行業視野(上不封頂)正則表達式
JAVA_HOME : JAVA安裝的目錄算法
Path:%JAVA_HOME%\bin數據庫
解決方法:編程
一、因爲系統默認編碼不是utf8,因此要將編譯改寫爲javac -encoding UTF-8 XXX.java就能夠正常輸出數組
二、將XXX.java文件另存爲-->選擇編碼ANSI保存緩存
System.out.format("%.3f %.3f\n",r,volume); System.out.printf("%.3f %.3f\n",r,volume);
兩數有一個爲long,則結果爲long。安全
沒有long時,結果爲int。即便操做數全爲short、byte,結果也是int。服務器
有一個爲long,結果爲long。網絡
兩個爲float,結果才爲float。
通常使用整數,結果是」餘數「,」餘數「符號和左邊相同。
a++ //先賦值,再自增
++a //先自增,再賦值
\>、>=、<、<= 僅針對數值類型(byte/short/int/long,float/double 以及char-->0~65535)
整型常量是int類型,可是能夠自動轉爲:byte、short、char。只要不超過對應類型的範圍。
java中Scanner類nextInt以後用nextLine沒法讀取輸入
問題出現緣由:
這是由於在調用nextLine()函數前調用了Scanner的另外一個函數nextInt()(或是nextDouble())。出現這種狀況的緣由是兩個函數的處理機制不一樣,nextInt()函數在緩衝區中遇到「空格」、「回車符」等空白字符時會將空白字符前的數據讀取走,但空白字符不會被處理掉,而nextLine()函數是在緩衝區中讀取一行數據,這行數據以「回車符」爲結束標誌,nextLine()會把包括回車符在內的數據提走。因此nextInt()後的nextLine()函數並不是讀取不到數據,由於nextInt()將「回車符」留在了緩衝區,nextLine()讀取時遇到的第一個字符即是「回車符」,因此直接結束了。
解決方法:
在要使用nextLine()前先調用一次nextLine(),這樣留在緩衝區的「回車符」就會被處理掉,這時第二個nextLine()函數能夠正常讀取到數據。
方法重載(overload):實際是徹底不一樣的方法,只是名稱相同而已,釋義:定義多個方法名相同,但參數不一樣的方法。
構成方法重載的條件:
①. 建立大量無用對象
②.靜態集合類的使用
③.各類鏈接對象(IO流對象、數據庫鏈接對象、網絡鏈接對象)未關閉
④.監聽器的使用
①.分配對象空間,並將對象成員變量初始化爲0或空
②.執行屬性值得顯式初始化
③.執行構造方法
④.返回對象的地址給相關的變量
經過變量引用操做對象
對象咩有被變量使用,則被認爲是」垃圾「,會被垃圾回收器回收
** this的本質是「建立好的對象地址」,在構造方法調用前,對象已經建立。所以,在構造方法中使用this表示"當前對象"。
instanceof是二元運算符,左邊是對象,右邊是類;當對象是右邊類或子類所建立對象時,返回true;反之爲false。
public class Person{ String name; int age; public static void main(String[] args){ Student s = new Student(「AAA」,66); System.out.println(s instanceof Person); System.out.println(s instanceof Student); } } class Student extends Person{ }
子類經過重寫父類的方法,能夠用自身的行爲替換父類的行爲;方法的重寫是實現多態的必要條件。
屬性和方法前加final,是不可擴展(繼承)和更改的,方法不可重寫,但可重載。
組合不一樣於繼承,更加靈活。
組合的核心是將父類對象做爲子類的屬性,而後,子類經過調用這個屬性來獲取父類的屬性和方法。
public class Animal{ public static void main(String[] args){ Taidi t = new Taidi(); t.dog.shout(); } } class Dog{ public void shout(){ System.out.println("wangwang...."); } } //組合 class Taidi { Dog dog = new Dog(); //Taidi包含(吸取)了Dog,因此具有了Dog的屬性和方法 }
總結:
繼承除了代碼複用、也能方便咱們對事務建模。」is a「 關係建議使用繼承,」has a「 關係建議使用組合。(如:Student is a Person邏輯就沒問題,但Student has a Person就有問題了;筆記本和芯片的關係屬於包含,則可使用」has a「)
+ protected須要注意的兩個細節
多態指的是同一個方法調用,因爲對象不一樣可能會有不一樣的行爲。
abstract修飾的方法,沒有方法體,只有聲明。定義的是一種"規範",就是告訴子類必需要給抽象方法提供具體的實現。
定義接口的詳細說明:
區別:
接口:JDK1.8以前只有規範,但JDK1.8以後新增了靜態方法和默認方法
接口徹底支持多繼承,和類的繼承相似,子接口擴展某個父接口,將會得到父接口中所定義的一切。
字符串String是在方法區的字符串常量池(String Pool)中存儲
//外部類 public class Outer { private int age = 10; private void show(){ System.out.println("good!!!"); } //非靜態內部類 public class Inner{ private String name = "tom"; private int age = 20; public void showInner(){ System.out.println("Inner.showInner"); System.out.println(age); System.out.println(Outer.this.age); show(); } } public static void main(String[] args) { Outer.Inner inner = new Outer().new Inner(); //經過 new 外部類名().內部類名() 來建立內部類對象 inner.showInner(); } }
//外部類 public class Outer { private int a = 10; private static int b = 20; //靜態內部類 static class Inner{ public void test(){ System.out.println(b); } } public static void main(String[] args) { Outer.Inner inner = new Outer.Inner(); //經過 new 外部類名.內部類名() 來建立內部類對象 inner.test(); } }
適合那種只須要使用一次的類。
public class AnonymousInnerClass { public void test(A a){ a.run(); } public static void main(String[] args) { AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass(); //匿名內部類 anonymousInnerClass.test(new A() { @Override public void run() { System.out.println("匿名內部類是沒有名字的類,只需使用一次;若是從新調用一次,就會定義新的匿名內部類!"); } }); } } interface A{ void run(); }
定義在方法內部的,做用域只限於本方法。
public class LocalInnerClass{ public void show(){ //做用域僅限於該方法 class Inner{ public void fun(){ System.out.println("局部內部類的實現!"); } } new Inner().fun(); } public static void main(String[] args){ new LocalInnerClass().show(); } }
數組:相同類型數據的有序集合,數組也是對象。
例如:
int[] a = {1,2,3}; //靜態初始化基本類型數組
Man[] mans = {new Man(1,1),new Man(2,2)}; //靜態初始化引用類型數組
例如:
int[] a = new int[2]; //動態初始化數組,先分配空間
a[0] = 1; //給數組元素賦值
a[1] = 2; //給數組元素賦值
例如:
int[] a = new int[2]; //默認值:0,0
boolean[] b = new boolean[2]; //默認值:false,false
String[] s = new String[2]; //默認值:null,null
總結:默認初始化---->數組元素至關於對象的屬性,遵照對象屬性默認初始化的規則。
當程序出現錯誤,程序安全的、繼續執行的機制。
包裝類:能夠把基本類型、包裝類對象、字符串三者進行互相轉化
當數字在[-128,127]之間的時候,返回緩存數組中的某個元素。
public class Test{ public static void main(String[] args){ //當數字在[-128,127]之間的時候,返回的是緩存數組中的某個元素 Integer i1 = 123; //自動裝箱;編譯器:Integer i1 = Integer.valueOf(123); Integer i2 = 123; //自動裝箱;編譯器:Integer i1 = Integer.valueOf(123); System.out.println(i1 == i2); // true;是由於123都是從緩存中取的同一個元素 System.out.println(i1.equals(i2)); // true } }
String類:不可變字符序列,會產生新對象的。
StringBuilder類:可變字符序列;效率高,可是線程不安全;添加字符序列,返回自身對象。
StringBuffer類:可變字符序列;效率低,可是線程安全;添加字符序列,返回自身對象。
public class Test{ public static void main(String[] args){ //編譯器作了優化,在編譯的時候,右邊是字符串常量,不是變量,因此直接將字符串作了拼接 String str1 = "hello" + " java"; //至關於 str1 = "hello java"; String str2 = "hello java"; System.out.println(str1 == str2); //true String str3 = "hello"; String str4 = " java"; //編譯的時候不知道變量中存儲的是什麼,因此沒辦法在編輯的時候作優化 String str5 = str3 + str4; System.out.println(str2 == str5); //false } }
public class Test { public static void main(String[] args) { String str = ""; long num1 = Runtime.getRuntime().freeMemory(); long time1 = System.currentTimeMillis(); for(int i = 0;i < 5000;i++){ str += i; } long num2 = Runtime.getRuntime().freeMemory(); long time2 = System.currentTimeMillis(); System.out.println("String佔用內存:" + (num1 - num2)); System.out.println("String佔用時間:" + (time2 - time1)); System.out.println("==================================="); StringBuilder sb = new StringBuilder(""); long num3 = Runtime.getRuntime().freeMemory(); long time3 = System.currentTimeMillis(); for(int i = 0;i < 5000;i++){ sb.append(i); } long num4 = Runtime.getRuntime().freeMemory(); long time4 = System.currentTimeMillis(); System.out.println("StringBuilder佔用內存:" + (num3 - num4)); System.out.println("StringBuilder佔用時間:" + (time4 - time3)); System.out.println("==================================="); StringBuffer sb2 = new StringBuffer(""); long num5 = Runtime.getRuntime().freeMemory(); long time5 = System.currentTimeMillis(); for(int i = 0;i < 5000;i++){ sb2.append(i); } long num6 = Runtime.getRuntime().freeMemory(); long time6 = System.currentTimeMillis(); System.out.println("StringBuffer佔用內存;" + (num5 - num6)); System.out.println("StringBuffer佔用時間:" + (time6 - time5)); } }
效率測試結果以下:
java.io.File類:表明文件和目錄。
枚舉類型隱形地繼承自java.lang.Enum。枚舉實質上仍是類,而每一個被枚舉的成員實質就是一個枚舉類型的實例。他們默認都是public static final修飾的。能夠直接經過枚舉類型名使用。
enum 枚舉名 { 枚舉體(常量列表) }
泛型是將類型基於一個佔位符形式來定義,在泛型中,不可使用基本類型,只能用對象類型來定義泛型。
總結一下:
![]()
編譯時採用泛型寫的類型參數,編譯器會在編譯時去掉。
泛型類是把泛型定義在類上。
泛型接口和泛型類的聲明方式一致。泛型接口的具體類型須要在實現類中進行聲明。
泛型方法是指將方法的參數類型定義成泛型,以便在調用時接受不一樣類型的參數。類型參數能夠有多個,用逗號隔開,如:<K,V>。類型參數通常放到返回值前面。
+ 非靜態方法
+ 靜態方法
靜態方法沒法訪問類上定義的泛型;若是靜態方法操做的引用數據類型不肯定的時候,必需要將泛型定義在方法上。
在泛型方法中,泛型也能夠定義可變參數類型。
通配符和上下限定
+ 通配符的上限限定
上限限定表示通配符的類型是T類以及T類的子類或者T接口以及T接口的子接口。
+ 通配符的下限限定
下限限定表示通配符的類型是T類以及T類的父類或者T接口以及T接口的父接口。該方法不適用泛型類。
數組也是一種容器,能夠放置對象或基本類型數據
總之,容器的底層都是基於數組來完成的。容器中數據都是存儲在內存的。
List:有序(元素存入集合的順序和取出的順序一致)、可重複
Vector:底層使用數組實現的。線程安全,效率低。Vector的使用與ArrayList是相同的。初始容量是10,如要擴容以2倍擴容。
Stack:棧容器,是Vector的一個子類,它實現了一個標準的後進先出(LIFO:Last In First Out)的棧。
//棧容器使用案例 public class StackTest { public static void main(String[] args) { StackTest st = new StackTest(); st.symmetry(); } //匹配符號的對稱性 public void symmetry(){ String str = "...{.....[....(....)....]....}..(....)..[...]..."; //實例化Stack Stack<String> stack = new Stack<>(); //假設修正法 boolean flag = true; //假設是匹配的 //拆分字符串獲取字符 for(int i = 0;i < str.length();i++){ char c = str.charAt(i); if(c == '{'){ stack.push("}"); } if(c == '['){ stack.push("]"); } if(c == '('){ stack.push(")"); } //判斷符號是否匹配 if(c == '}'||c == ']'||c == ')'){ if(stack.empty()){ flag = false; break; } String x = stack.pop(); if(x.charAt(0) != c){ flag = false; break; } } } if(!stack.empty()){ flag = false; } System.out.println(flag); } }
Set特色:無序,不可重複。無序指Set中的元素沒有索引,只能遍歷查找;不可重複指不容許加入重複的元素。
無序:
![]()
不重複:
![]()
Map接口定義了雙例集合的存儲特徵,它不是Collection接口的子接口。雙例集合的存儲特徵是以key與value結構爲單位進行存儲的。
數據結構是以某種特定的佈局方式存儲數據(存儲結構上差別)的容器。
線性表、棧、隊列、串(一堆數組)等
二叉樹、紅黑樹、B樹、哈夫曼樹等
有向圖、無向圖、簡單圖等
棧是一種只能從一端存取數據且遵循"後進先出(LIFO)"原則的線性存儲結構
鏈表結構是由許多節點構成的,每一個節點都包含兩部分:
單向鏈表
雙向鏈表
雙向循環鏈表
使用樹結構存儲的每個數據元素都被稱爲「結點」。
某個結點所擁有的子樹的個數
樹中節點的作大層次數
度爲0的結點,也叫終端結點。
度不爲0的結點,也叫非終端結點或內部結點。
也可稱之爲子樹或者子結點,表示當前節點下層的直接結點。
也可稱之爲父結點,表示當前結點的直接上層結點。
沒有雙親結點的結點。在一個樹形結構中只有一個根節點。
從當前結點上層的全部結點。
當前結點下層的全部結點。
同一雙親的孩子。
Java中正則表達式爲String類型,被驗證的內容一樣爲String類型。經過String類中的matches方法實現內容的匹配校驗。如:」被驗證內容「.matches("正則表達式")
在定義限定內容規則是,若是沒有指定長度限定,那麼默認長度爲1。
[a]:表示當前內容必須是字母a
[a-z0-9]:表示內容能夠是a-z之間的任意字母或者0-9之間的任意數字,不分前後
[^abc]:表示內容不能是a或b或c。
在正則表達式中能夠經過一些預約義字符來表示內容限定。目的是爲了簡化內容限定的定義
經過多個內容限定與長度限定來組合定義
| :或者 ,如:a|b (a或b)
\\.:任意字符 ,如:-|\\. (-或任意一個字符)
輸入流:數據流從數據源到程序(InputStream、Reader結尾的流)
![]()
輸出流:數據流從程序到目的地(OutputStream、Writer結尾的流)
![]()
![]()
InputStream/OutputStream和Reader/Writer類是全部IO類的抽象父類
InputStream: 字節輸入流
OutputStream: 字節輸出流
Reader: 讀取的字符流抽象類,數據單位爲字符
Writer: 輸出的字符流抽象類,數據單位爲字符
按流的方向分類:
輸入流:InputStream、Reader結尾的流
輸出流:OutputStream、Writer結尾的流按處理的數據單元分類:
字節流:以字節爲單位獲取數據,FileInputStream、FileOutputStream
字符流:以字符爲單位獲取數據,Reader/Writer結尾的流,如FIleReader、FileWriter按處理對象不一樣分類
節點流:直接從數據源或目的地讀寫數據,如:FileInputStream、FileReader、DataInputStream
處理流:也叫包裝流,不直接鏈接到數據源或目的地,是」處理流的流「。經過對其餘流的處理提升程序的性能,如:BufferedInputStream、BufferedReader。
總結:
File類是Java提供的針對磁盤中的文件或目錄轉換對象的包裝類。一個File對象能夠表明一個文件或目錄。
方式一:
public class FileDemo { public static void main(String[] args) throws Exception{ try(FileInputStream fis = new FileInputStream("images/s1.jpg"); FileOutputStream fos = new FileOutputStream("images/11.jpg"); ){ //建立一個緩衝區 byte[] buff = new byte[1024]; //空間換效率,效率低,但空間節省。 int len = 0; while((len = fis.read(buff)) != -1){ fos.write(buff,0,len); } fos.flush(); }catch (Exception e){ e.printStackTrace(); } } }
方式二:
public class FileDemo { public static void main(String[] args) throws Exception{ try(FileInputStream fis = new FileInputStream("images/s1.jpg"); FileOutputStream fos = new FileOutputStream("images/11.jpg"); ){ //建立一個緩衝區 byte[] buff = new byte[fis.available()]; //效率換空間,佔內存,但效率快 fis.read(buff); fos.write(buff); fos.flush(); }catch (Exception e){ e.printStackTrace(); } } }
public class FileCopyTools { public static void main(String[] args) { copyFile("images/s1.jpg","images/11.jpg"); } /** * 文件拷貝方法 */ public static void copyFile(String src,String des){ try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(des)); ){ int temp = 0; while((temp = bis.read()) != -1){ bos.write(temp); } bos.flush(); } catch (Exception e){ e.printStackTrace(); } } }
字符緩衝流
字符輸入緩衝流
![]()
字符輸出緩衝流
InputStreamReader/OutputStreamWriter用來實現將字節流轉化成字符流。
public class ByteArrayOutputStreamDemo { public static void main(String[] args) { ByteArrayOutputStream bos = null; StringBuilder sb = new StringBuilder(); try{ bos = new ByteArrayOutputStream(); bos.write('a'); bos.write('b'); bos.write('c'); byte[] arr = bos.toByteArray(); for(int i = 0;i < arr.length;i++){ sb.append((char)arr[i]); } System.out.println(sb.toString()); }finally{ try{ if(bos != null){ bos.close(); } }catch (Exception e){ e.printStackTrace(); } } } }
//數據輸出流 public class DataIOStreamDemo { public static void main(String[] args) { try(DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt")));){ dos.writeChar('a'); dos.writeInt(4); dos.writeDouble(Math.random()); dos.writeUTF("您好"); dos.flush(); }catch (Exception e){ e.printStackTrace(); } } }
讀取的順序要與數據輸出流寫入的順序一致,不然不能讀取數據
//數據輸入流 public class DataIOStreamDemo { public static void main(String[] args) { try(DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("data.txt")));){ //直接讀取數據,注意:讀取的順序要與寫入的順序一致,不然不能讀取數據 System.out.println("char:" + dis.readChar()); System.out.println("int:" + dis.readInt()); System.out.println("double:" + dis.readDouble()); System.out.println("utf:" + dis.readUTF()); }catch (Exception e){ e.printStackTrace(); } } }
數據流只能實現對基本數據類型和字符串類型的讀寫,並不能Java對象進行讀寫操做(字符串除外),而對象流除了能實現對基本數據類型進行讀寫操做,還能對Java對象進行讀寫操做。
對象的序列化:把java對象轉換爲字節序列的過程。
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.ObjectOutputStream; //對象輸出流完成基本數據類型的輸出 public class ObjectIOStreamDemo { public static void main(String[] args) { try(ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("data")));){ oos.writeInt(10); oos.writeDouble(Math.random()); oos.writeChar('a'); oos.writeBoolean(true); }catch (Exception e){ e.printStackTrace(); } } }
對象的反序列化:字節序列恢復爲Java對象的過程。
程序:
進程:
線程:
+ 主線程的特色
它是產生其餘子線程的線程。
它不必定是最後完成執行的線程,子線程可能在它結束以後還在運行。
在主線程中建立並啓動的線程,通常稱之爲子線程。
import java.io.IOException; public class StopThread implements Runnable{ private boolean flag = true; @Override public void run() { System.out.println(Thread.currentThread().getName() + "線程開始"); int i = 0; while(flag){ System.out.println(Thread.currentThread().getName() + " " + i++); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "線程結束"); } //勸本身自殺方式終止線程,線程能正常結束。 public void stop(){ this.flag = false; } public static void main(String[] args) throws IOException { System.out.println("主線程開始"); StopThread st = new StopThread(); Thread t1 = new Thread(st); //啓動線程 t1.start(); System.in.read(); st.stop(); System.out.println("主線程結束"); } }
+ yield 方法的使用
class A implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " " + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class JoinThread { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new A()); //啓動A線程 t.start(); //主線程 for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " " + i); //當i=2時,主線程等待A線程結束以後再運行 if(i == 2){ t.join(); } Thread.sleep(1000); } } }
synchronized可阻止併發更新同一個共享資源,實現了同步,可是synchronized不能用來實現不一樣線程之間的消息傳遞(通訊)。
>  > 
在不一樣線程中相同對象中synchronized會互斥。
語法結構:
synchronized(this){ //同步代碼 }
或
public synchronized void accessVal(int newVal){ }
全部線程在執行synchronized時都會同步。因字符串是不變序列,因此會持有相同鎖。
synchronized("字符串"){ //同步代碼 }
在不一樣線程中,擁有相同Class對象中的synchronized會互斥。
synchronized(XX.class){ //同步代碼 }
或
synchronized public static void accessVal(){ //同步代碼 }
在不一樣線程中,擁有相同自定義對象中的synchronized會互斥。放在線程中造成互斥鎖。
synchronized(自定義對象){ //同步代碼 }
死鎖是由於同一代碼塊出現嵌套synchronized形成的,解決方法是避免出現嵌套synchronized語句塊。
角色:
生產者:負責生產數據的模塊
消費者:負責處理數據的模塊
緩衝區:消費者不能直接使用生產者數據,它們之間有個「緩衝區」。生產者將生產好的數據放入「緩衝區」,消費者從「緩衝區」拿要處理的數據。
![]()
緩衝區的好處:
![]()
/** * 定義饅頭類 */ class ManTou{ private int id; public ManTou(int id){ this.id = id; } public int getId(){ return this.id; } } /** * 定義緩衝類 */ class SyncStack{ //定義放饅頭的盒子 private ManTou[] mt = new ManTou[10]; //定義盒子的suoyin private int index; /** * 放饅頭 */ public synchronized void push(ManTou manTou){ while(this.index == this.mt.length){ try { //該方法執行後,線程會將持有的對象鎖釋放,並進入阻塞狀態,其餘須要該對象鎖的線程就能夠繼續運行了。 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); //該方法執行後,會喚醒處於等待狀態隊列中的一個線程 this.mt[this.index] = manTou; this.index++; } /** * 取饅頭 */ public synchronized ManTou pop(){ while(this.index == 0){ try { //該方法執行後,線程會將持有的對象鎖釋放,並進入阻塞狀態,其餘須要該對象鎖的線程就能夠繼續運行了。 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); //該方法執行後,會喚醒處於等待狀態隊列中的一個線程 this.index--; return this.mt[this.index]; } } /** * 定義生產者線程 */ class Producer extends Thread{ private SyncStack ss; public Producer(SyncStack ss){ this.ss = ss; } @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("生產饅頭:" + i); ManTou manTou = new ManTou(i); this.ss.push(manTou); } } } /** * 定義消費者線程 */ class Customer extends Thread{ private SyncStack ss; public Customer(SyncStack ss){ this.ss = ss; } @Override public void run() { for (int i = 0;i < 10;i++) { ManTou manTou = this.ss.pop(); System.out.println("消費饅頭:" + i); } } } public class ProduceThread { public static void main(String[] args) { SyncStack ss = new SyncStack(); new Thread(new Producer(ss)).start(); new Thread(new Customer(ss)).start(); } }
線程併發協做總結
下列的方法均是java.lang.Object類的方法,都只能在同步方法或者同步代碼塊中使用,不然會拋出異常。
OSI七層協議模型:分別是:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層。
應用層、傳輸層、互聯網絡層、網絡接口層(物理 + 數據鏈路層)
總結:發送數據必須同時指定IP地址和端口。
#### URL(Uniform Resource Locator)
在www上,每一信息資源都有統一且惟一的地址。URL由四部分組成:協議、存放資源的主機域名、自願文件和端口號。
#### Socket
#### TCP和UDP協議
Socket類:發送TCP消息
ServerSocket類:建立服務器
表示數據報包。數據報包用來實現將發送的數據進行封包處理的。