Java 編程基礎............................................................................................................ - 3 -html
1、 前言....................................................................................................... - 3 -java
1. JAVA 軟件工程師的崗位要求................................................................. - 3 -node
2、 Java概述:............................................................................................ - 4 -es6
1. Java的三種技術架構.............................................................................. - 4 -web
2. JDK、JRE、JVM三者間的關係............................................................. - 4 -正則表達式
3. Java運行環境配置................................................................................. - 5 -sql
4. Java與Javac命令................................................................................. - 6 -shell
5. Java編譯過程........................................................................................ - 7 -數據庫
6. Java內存處理機制................................................................................. - 7 -編程
7. 經常使用DOS命令....................................................................................... - 7 -
3、 Java編程風格與命名規範....................................................................... - 8 -
1. 格式規範................................................................................................ - 8 -
2. 命名規範................................................................................................ - 8 -
4、 語法基本元素......................................................................................... - 9 -
1. 關鍵字................................................................................................... - 9 -
2. 標識符................................................................................................... - 9 -
3. 數據類型、常量和變量......................................................................... - 10 -
4. 運算符和表達式.................................................................................... - 11 -
5、 流程控制.............................................................................................. - 14 -
1. 循環語句.............................................................................................. - 14 -
2. 判斷語句.............................................................................................. - 14 -
3. 跳轉語句.............................................................................................. - 14 -
4. flag 或index標記的用法..................................................................... - 15 -
6、 數組..................................................................................................... - 16 -
1. 數組的經常使用操做................................................................................... - 16 -
2. 二維數組.............................................................................................. - 17 -
Java 面向對象.......................................................................................................... - 19 -
1、 前言..................................................................................................... - 19 -
2、 類和對象.............................................................................................. - 19 -
1. 類和對象的定義................................................................................... - 19 -
2. 類的建立和使用................................................................................... - 19 -
3. 對象的建立和使用................................................................................ - 20 -
4. 成員變量VS局部變量.......................................................................... - 20 -
5. 成員方法VS方法................................................................................. - 21 -
6. 構造方法.............................................................................................. - 22 -
7. 補充幾點.............................................................................................. - 22 -
3、 封裝、繼承和多態................................................................................ - 25 -
1. 封裝..................................................................................................... - 25 -
2. 繼承..................................................................................................... - 26 -
3. 多態..................................................................................................... - 27 -
4、 抽象類和接口....................................................................................... - 30 -
1. 抽象類(abstract).............................................................................. - 30 -
2. 接口(interface)................................................................................ - 31 -
3. 抽象類和接口的對比............................................................................ - 32 -
5、 異常..................................................................................................... - 33 -
1. JAVA異常............................................................................................ - 33 -
2. 處理異常機制....................................................................................... - 34 -
3. 捕獲異常try / catch 和 finally.............................................................. - 34 -
4. 拋出異常 throws和throw.................................................................... - 35 -
5. Java常見異常...................................................................................... - 35 -
6. 自定義異常.......................................................................................... - 36 -
7. Java異常處理的原則和技巧................................................................. - 36 -
8. 補充幾點.............................................................................................. - 36 -
6、 面向對象的幾點猜測............................................................................ - 36 -
Java 高級特性.......................................................................................................... - 37 -
1、 集合框架和泛型................................................................................... - 37 -
1. 集合 框架 API..................................................................................... - 37 -
2. Iterator 迭代器.................................................................................... - 40 -
3. Collections包裝類............................................................................... - 41 -
4. 補充幾點.............................................................................................. - 42 -
5. 泛型..................................................................................................... - 42 -
2、 實用類................................................................................................. - 42 -
1. 枚舉..................................................................................................... - 43 -
2. 包裝類................................................................................................. - 43 -
3. Math類................................................................................................ - 44 -
4. String類.............................................................................................. - 44 -
5. StringBufffer類和StringBulider類...................................................... - 45 -
6. 日期時間類.......................................................................................... - 45 -
7. Random類........................................................................................... - 46 -
3、 輸入/輸出、序列化和反射.................................................................... - 46 -
1. File類的操做....................................................................................... - 46 -
2. Java的流............................................................................................. - 47 -
3. 讀寫文本文檔....................................................................................... - 47 -
4. 讀寫二進制文檔................................................................................... - 50 -
5. 重定向標準 I/O.................................................................................... - 51 -
6. 序列化與反序列化................................................................................ - 51 -
7. 反射機制.............................................................................................. - 52 -
8. 補充幾點.............................................................................................. - 52 -
4、 註解和多線程....................................................................................... - 53 -
1. 註解..................................................................................................... - 53 -
2. 多線程................................................................................................. - 54 -
5、 網絡編程.............................................................................................. - 57 -
1. 網絡基礎知識....................................................................................... - 57 -
2. InetAddress......................................................................................... - 58 -
3. URL類................................................................................................. - 58 -
4. TCP編程............................................................................................. - 59 -
5. UDP編程............................................................................................. - 63 -
6. 注意問題.............................................................................................. - 65 -
6、 XML..................................................................................................... - 65 -
1. XML 基礎............................................................................................ - 65 -
2. XML 註釋............................................................................................ - 65 -
3. XML 解析............................................................................................ - 65 -
7、 GUI...................................................................................................... - 68 -
8、 正則表達式.......................................................................................... - 73 -
1.基礎紮實,具有良好面向對象設計能力和範化的編程風格;熟悉MVC設計模式;
2.熟悉CSS/HTML, JavaScript, XML/XSL, Ajax,Jquery等Web腳本語言技術
3.熟練掌握Oracle/MySQL等主流數據庫,瞭解數據庫內部機制和原理;
4.熟練基於J2EE的相關開源技術以及框架(Spring,SpringMVC,MyBatis,Hibernate);
5.熟練使用Tomcat、Apache,Nginx,servlet等應用和服務器配置;
6.熟練使用Junit編寫測試代碼,Maven代碼管理工具;
7.瞭解UML等建模語言、PowerDesigner等設計經常使用工具;
8.項目工做經驗
1991 年Sun公司的James Gosling等人開始開發名稱爲 Oak 的語言,但願用於控制嵌入在有線電視交換盒、PDA等的微處理器;1994年將Oak語言改名爲Java;
JDK是整個JAVA的核心,包括了Java運行環境JRE(Java Runtime Envirnment)、一堆Java工具(Javac/Java/jdb等)和Java基礎的類庫(即Java API 包括rt.jar)。
在JDK的安裝目錄下有一個名爲jre的目錄,裏面有兩個文件夾bin和lib,在這裏能夠認爲bin裏的就是jvm,lib中則是jvm工做所須要的類庫,而jvm和 lib和起來就稱爲jre。
Java程序的運行環境,Java運行的所需的類庫+JVM(Java虛擬機)。與JDK不一樣,JRE是Java運行環境,並非一個開發環境,因此沒有包含任何開發工具(如編譯器和調試器),只是針對於使用Java程序的用戶。
Java虛擬機的縮寫,是整個Java實現跨平臺的最核心的部分,全部的Java程序會首先被編譯爲.class的類文件,這種類文件能夠在虛擬機上執行。
也就是說class並不直接與機器的操做系統相對應,而是通過虛擬機間接與操做系統交互,由虛擬機將程序解釋給本地系統執行。
只有JVM還不能成class的執行,由於在解釋class的時候JVM須要調用解釋所須要的類庫lib,而jre包含lib類庫。
做用是指定命令搜索路徑,在shell下面執行命令時,它會到PATH變量所指定的路徑中查找看是否能找到相應的命令程序。咱們須要把 jdk安裝目錄下的bin目錄增長到現有的PATH變量中,bin目錄中包含常常要用到的可執行文件如Javac/Java/Javadoc等,設置好 PATH變量後,就能夠在任何目錄下執行Javac/Java等工具了。
做用是指定類搜索路徑,要使用已經編寫好的類,前提固然是可以找到它們了,JVM就是經過CLASSPTH來尋找類的。咱們 須要把jdk安裝目錄下的lib子目錄中的dt.jar和tools.jar設置到CLASSPATH中,固然,當前目錄「.」也必須加入到該變量中。
它指向jdk的安裝目錄,Eclipse/NetBeans/Tomcat等軟件就是經過搜索JAVA_HOME變量來找到並使用安裝好的jdk。
Java_Home:C:\Program Files\Java\jdk1.7.0_07
Path: %Java_Home%\bin;%Java_Home%\jre\bin;
ClassPath:. ; %Java_Home%\bin;%Java_Home%\lib\dt.jar;%Java_Home%\lib\tools.jar
特色:系統默認先去當前路徑下找要執行的程序,若是沒有,再去path中設置的路徑下找
set path=%path%;C:\Program Files\Java\jdk\bin set classpath=XXX
註釋:環境變量的配置已經完成,DOS命令下輸入Java/Javac/Java –version檢測。
若是沒有定義環境變量classpath,Java啓動JVM後,會在當前目錄下查找要運行的類文件;若是指定了classpath,那麼會在指定的目錄下查找要運行的類文件。
還會在當前目錄找嗎?兩種狀況:
Java是分兩部分的:一個是編譯,一個是運行。
待補充~
md |
建立文件夾 |
cd |
進入文件夾 |
del |
刪除文件夾 |
copy |
複製文件 |
rd |
刪除文件夾 |
cd.. |
後退一級 |
cls |
清屏 |
help |
幫助 |
dir |
列出目錄 |
cd\ |
進入根目錄 |
ren |
重命名 |
|
|
詳見經常使用DOS命令大全及其用法
a) 縮進嵌套的代碼
b) 斷開很長的句子
c) 使用空白
d) 不要直接使用Tab控制符
JAVA源文件名必須和源文件中所定義的類的類名相同。且不能爲關鍵字
Package名的第一部分應是小寫ASCII字符,而且是頂級域名之一,一般是com、edu、gov、mil、net、org或由ISO標準316六、1981定義的國家惟一標誌碼。Package名的後續部分由各組織內部命名規則決定,內部命名規則指定了各組件的目錄名,所屬部門名、項目名等。
Class名應是首字母大寫的名詞, 並且大寫中間單詞的首字母。命名時應該使其簡潔而又具備描述性。異常類的命名,應以Exception結尾。Interface的命名規則與Class相同。
常量名的字母應所有大寫,不一樣單詞之間經過下劃線鏈接,而且名字組合應該賦予含義。
普通變量名的首字母小寫,其它每一個單詞的首字母大寫。命名時應該使其簡短而又有特定含義,簡潔明瞭的向使用者展現其使用意圖。
所謂約定變量,是指那些使用後便可拋棄(throwaway)的臨時變量。一般i、j、k、m和n表明整型變量;c、d和e表明字符型變量。
方法名的第一個單詞應是動詞,而且首字母小寫,其它每一個單詞首字母大寫。
選擇有意義的名稱做爲方法的參數名。可能的話,選擇和須要賦值的字段同樣的名字。
詳見Java編程風格與命名規範-ZZ
a) 定義:被JAVA語言賦予了特殊含義的單詞。
b) 特色:關鍵字中全部字母都爲小寫。
c) 注意:goto和const做爲保留字存在,目前並不使用。
a) 含義:標識符就是給類,接口,方法,變量等起名字時使用的連續字符序列。
b) 組成規則:① 英文大小寫字母A~Z和a~z ② 數字字符0~9 ③ $ 和 _
c) 注意事項:① 不能以數字開頭 ② 不能是Java中的關鍵字 ③ 區分大小寫
④ 不能有空格
byte、short、int、long、float、double、char、boolean
數組、類、接口。
分類 |
不一樣類型 |
關鍵字 |
字節數 |
取值範圍 |
默認值 |
整數型 |
字節型 |
byte |
1個字節 |
-27~27-1(-128~127) |
0 |
短整型 |
short |
2個字節 |
-215~215-1(-32768~32767) |
0 |
|
整型 |
Int (默認) |
4個字節 |
-231~231-1 |
0 |
|
長整型 |
long |
8個字節 |
-263~263-1 |
0 |
|
文本型 |
字符型 |
char |
2個字節 |
0~216-1(從0~65536) |
‘\u0000’ |
浮點型 |
單精度浮點型 |
float |
4個字節 |
大約±3.40282347E+38F (有效位數爲6~7位) |
0.0f |
雙精度浮點型 |
Double (默認) |
8個字節 |
大約±1.79769313486231570E+308 (有效位數爲15位) |
0.0d |
|
邏輯型 |
布爾型 |
boolean |
1個字節 |
True/false |
false |
級別從低到高爲:(byte--> short),char (這兩個平級)--> int--> float--> long--> double
補充: 不一樣的字符所佔的字節是不一樣的。詳見輸入輸出章節之字符編碼。
0x 0
不一樣的基本數據類型之間進行運算時須要進行類型轉換,除boolean類型外全部的基本數據類型都須要考慮類型轉換,其主要應用在算術運算和賦值運算時。
正確舉例:String a = integer.toString(2)或int i = integer.parseInt(s);
全部局部變量在使用前都得初始化。詳見類與對象部分。
在程序執行的過程當中其值不能夠發生改變的量,Java中常量可分爲字面值常量和自定義常量。 eg. final double PI = 3.14;
|
3.14 314.0 時 .314
3.14e2 3.14E2 314E2
在計算機內,有符號數有3種表示法:原碼、反碼和補碼。全部數據的運算都是採用補碼進行的。
u [+1] = [00000001]原 = [00000001]反 = [00000001]補
u [-1] = [10000001]原 = [11111110]反 = [11111111]補
參考:
表達式是由運算符與操做數組合而成的,運算符指明對操做數的運算方式。組成表達式的Java操做符有不少種。運算符按照其要求的操做數數目來分,能夠有單目運算符、雙目運算符和三目運算符,它們分別對應於1個、2個、3個操做數。運算符按其功能來分,有算術運算符、賦值運算符、關係運算符、邏輯運算符、位運算符和其餘運算符。
優先級 |
運 算 符 |
含義描述 |
1 |
( ) ,. , [ ] |
強制運算、方法調用 |
2 |
++ , -- , + , ~(位取反) , !(邏輯取反) |
一元運算、字符串相加 |
3 |
New eg.Type a=new Type() |
建立運算符 |
4 |
* , / , % |
算術運算 乘除、取餘 |
5 |
+ , - |
算術運算 加減(正負) |
6 |
<< , >> , >>>(無符號) |
位運算 |
7 |
< , > , <= , >= , instanceof |
比較運算、類運算 |
8 |
= = , ! = , .equals() |
比較運算 |
9 |
& |
邏輯(位)運算 與 |
10 |
^ |
位運算 異或 |
11 |
| |
邏輯(位)運算 或 |
12 |
&& |
邏輯 與(短路) |
13 |
|| |
邏輯 或(短路) |
14 |
?: eg. (關係表達式)?表達式1:表達式2; |
三元 條件運算 |
15 |
= , *= , /= , %= , += , -= |
簡單賦值運算 |
16 |
<<= , >>= , >>>= , &= , ^= , |= |
複雜賦值運算 |
(* , / , % , + , - )
(= , *= , /= , %= , += , -=)
(< , > , <= , >= ,= = , ! =) boolean bo=(i==j);
特色:該運算符的特色是:運算完的結果,要麼是true,要麼是false。
待補充:==與.equals()區別:
(& , | , ^ , ! , && , ||)
邏輯運算符除了 ! 外都是用於鏈接兩個boolean類型表達式。
u 兩邊結果同樣,就爲false;
u 兩邊結果不同,就爲true。
u &:不管左邊結果是什麼,右邊都參與運算(建議短路與);
u &&: 短路與,若是左邊爲false,那麼右邊不參數與運算。
u |:兩邊都運算(建議短路或);
u ||:短路或,若是左邊爲true,那麼右邊不參與運算。
用於操做二進制位的運算符;& , | , ^ ,<< , >> , >>>(無符號)
待補充~
在Java中,流程控制分爲三種基本結構:順序結構、分支結構和循環結構。
If 判斷: |
else If 判斷: |
If 判斷(嵌套): |
switch 判斷: |
||
if (表達式) { //語句1; } else { //語句2; } 類比: (關係表達式)? 表達式1:表達式2; 注:else語句可用 Continue代替; |
if (表達式1) { //語句1; } else if (表達式2) { //語句2; … } else { //語句3; } |
If (表達式1) { if(表達式2) { //語句1; } else { //語句2; } } else { //語句3; } |
switch (表達式) { case 常量1: 語句1; break; case 常量2: 語句2; break; … default: 語句3; } |
||
while循環: |
do-while循環: |
for循環: |
|||
while(表達式) { //循環體; } |
do{ //循環體; } while(表達式); |
for(初始化;條件;迭代) { //循環體; } |
|||
a) 循環是相同動做的集合.
b) 循環次數肯定的狀況,一般選用for循環;
循環次數不肯定的狀況,一般選用while或do-while循環。
c) 初始狀況不知足循環條件時,while循環一次都不會執行;
do-while循環無論任何狀況都至少執行一次。
d) for 循環,若變量在判斷條件內初始化,則做用域爲循環體(大括號)內。
e) 嵌套循環判斷條件:內層循環一圈,外層循環一次。
a) 多重if與switch選擇結構比較
b) else If 順序進行判斷,當前麪條件不知足時才進行下一步,條件知足,跳過剩餘結構,結束判斷語句。
c) switch 後面的小括號中的變量應該是int、short、byte、char、枚舉類型、String。
d) switch 可進行語句合併,以進行連續區間判斷。(省去語句和break)
a) break:結束判斷語句,執行完判斷體後的語句後,終止離本身最近的外層循環。
do { String title = input.next(); if (title.equals("exit")) { break; } } while (true); // 跳出死循環 |
b) continue:結束判斷語句,終止本次循環,不執行判斷體後面語句,進入下一次循環。
public static void main(String[] args) { int i = 0; do { i++; if (i == 3) { // break; // 輸出12 continue; // 輸出1245 } System.out.println(i); } while (i < 5); } |
c) return:結束當前方法的執行並退出,並返回值到調用該方法的語句處。
for (int i = 0; i < 10; i++) { if (i % 2 != 0) return; System.out.print(i); } // 運行結果:0 |
數組是一個變量,存儲相同數據類型的一組數據
步驟 |
舉例 |
解釋 |
聲明 |
int[ ] a; |
告訴計算機數據類型是什麼 |
分配空間 |
a = new int[5]; |
告訴計算機分配幾個連續的空間 |
賦值 |
a[0] = 8; |
向分配的格子裏放數據 |
引用 |
a[0] = a[0] * 10; |
引用數據進行計算 |
數據類型[ ] 數組名 = new 數據類型[大小];
int[ ] scores = {89, 79, 76};
int[ ] scores = new int[ ]{89, 79, 76};
Scanner input = new Scanner (System.in);
for (int i = 0; i < 30; i ++) {
scores[i] = input.nextInt ();}
for (int k = array.length - 1; k >= 0; k--) {// 逆序輸出 System.out.print(array[k] + "\t"); } |
for (int temp : array) {// 用for加強型函數對數組進行順序輸出 System.out.println(temp); } |
數組的增添舉例: String[] phones = new String[] {"iPones4S", "iPones5", null}; // null 不用加雙引號 int index = -1;// 增長監視器 for (int i = 0; i < phones.length; i++) {// 1.增長iPones6 if (phones[i] == null) { index = i; break; } } if (index != -1) { phones[index] = "iPones6"; } else { System.out.println("數組已滿"); } System.out.println(Arrays.toString(phones)); |
註釋:數組的修改與刪除相似
for (int m = 0; m < array.length - 1; m++) { // 冒泡排序 for (int n = 0; n < array.length - 1 - m; n++) { if (array[n] > array[n + 1]) { int temp = array[n]; array[n] = array[n + 1]; array[n + 1] = temp; } } } |
方法名稱 |
說明 |
|
Arrays. |
boolean equals(array1,array2) |
比較array1和array2兩個數組是否相等 |
sort(array) |
對數組array的元素進行升序排列 |
|
String toString(array) |
將一個數組array轉換成一個字符串 |
|
void fill(array,val) |
把數組array全部元素都賦值爲val |
|
copyOf(array,length) |
把數組array複製成一個長度爲length 的新數組,返回類型與複製的數組一致 |
|
int binarySearch(array, val) |
查詢元素值val在數組array中的下標 (要求數組中元素已經按升序排列 |
註釋:import java.util.*;
String[][] str = new String[5][]; int[][] scores = new int[][] { { 90, 85, 54 }, { 76, 80 },{ 87 } }; int[][] scores = { { 90, 85, 54 }, { 76, 80 }, { 87 } }; |
public class Case5 { // 二維數組的遍歷 public static void main(String[] args) { int[][] scores = new int[][] { { 90, 78, 54 }, { 76 , 80 }, { 87 } }; for (int i = 0; i < scores.length; i++) { //外層數組長度 for (int j = 0; j < scores[i].length; j++) {//內層數組長度 System.out.println(scores[i][j]); } } } } |
public class ConstructorMethod { String name; int age; // 成員變量 public ConstructorMethod(String name, int age) { //有參構造方法,構造方法無返回類型 this.name = name; this.age = age; //實例的屬性 = 實參; } public static int Case1() { //成員方法 System.out.println("我是Case1調用"); return 0; } } |
舉例:center.name = "北京中心"; //給name屬性賦值
舉例:center.showCenter(); //調用showCenter()方法
舉例:School center = new School();
基本數據類型爲初始化爲0,布爾類型爲false,引用類型爲null。
public class Test { public static void main(String[] args) { Cat cat = null; //局部變量須要初始化或傳實參 Pet pet = new Cat(); cat = (Cat)cat; } }
class Pet { }
class Cat extends Pet { } |
通常格式:訪問修復符 返回值類型 方法名(參數列表){方法體};
類的訪問權限有Public和Default兩種,類中成員的訪問權限有下列四種:
補充:繼承權限測試. Package 。
繼承權限測試(類之間) & 訪問權限測試(屬性和方法)測試結果:
u 類的訪問修飾符只有public和默認兩種。
u 類中成員 public(公共修飾符) --> protected(子類) --> default(包)--> private(私有)
u 局部變量做用域肯定,故沒有訪問修飾符,訪問修飾符僅針對成員變量和方法。
u 子類對父類的訪問,直接調用屬性或方法(其實隱含this.調用)。
u 非繼承關係或父類對子類的訪問的訪問方式,需用對象或類名訪問。
u 訪問權限是基於繼承決定的,繼承權限也是一種訪問權限。
u 繼承則屬性和方法歸父類和子類共有,但除私有成員不能夠訪問。
u 子類能夠選擇重寫父類的屬性和方法的訪問修飾符,權限不能小於父類
方法重載,就是在同一個類裏中能夠建立多個方法,方法名要同樣,參數列表不一樣,和訪問修飾符 、返回值無關。調用方法時經過傳遞給它們的不一樣參數個數和參數類型來決定具體使用哪一個方法,是一個類中多態性的一種表現。
方法重寫,在子類和父類之間對,父類的函數進行從新定義。子類名稱和參數別表與父類相同,方法體重寫。
所謂構造方法,就是構造對象的方法,經過new + 構造方法, 這樣就建立了一個新的對象。
public class Test { private String name; public Test(){ this.name = "小新"; } public Test(String name) { System.out.println("我是" +this.name); } public static void main(String[] args) { Test test = new Test("小強"); } } //運行結果:我是null(實參沒有該成員變量賦值) |
public class Test { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("args" + i + "=" + args[i]); } } } 輸出結果: args0=args1 args1=args2 |
u int month = 4; u int day = input.nextInt(); 注:做爲形參的變量的初始化即是傳入實參。 |
待補充~
內部類將相關的類組織在一塊兒,從而下降了命名空間的混亂。一個內部類能夠定義在另外一個類裏,能夠定義在函數裏,甚至能夠做爲一個表達式的一部分。內部類能夠直接訪問外部類中的成員。而外部類想要訪問內部類,必需要創建內部類的對象。
http://blog.sina.com.cn/s/blog_accab4a90101gzh2.html
匿名內部類也就是沒有名字的內部類,正由於沒有名字,因此匿名內部類只能使用一次,它一般用來簡化代碼編寫。但使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口。
abstract class Person { public abstract void eat(); }
public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } } |
一個類可使用不包含在任何方法體中的靜態代碼塊,當類被載入時,靜態代碼塊被執行,且只被執行一次,靜態塊經常使用來執行類屬性的初始化。
static { System.out.println ("Hello Everyone"); } |
方法裏不能夠定義static
待補充~
這個關鍵字是一個修飾符,能夠修飾類,方法,變量。
public class Test { private String name; //將類的屬性進行封裝 public String getName() { //並提供可帶判斷條件的訪問方法 return name; }
public void setName(String name) { this.name = name; } } |
將類的屬性隱藏在類內部,不容許外部程序直接訪問,而是經過該類提供的方法來實現對隱藏信息的操做和訪問。
修改屬性的可見性(設爲private,防止錯誤的修改)à建立公有的getter/setter方法(用於屬性的讀寫)à在getter/setter方法中加入屬性控制語句(對屬性值的合法性進行判斷)。
class Person { // 父類 private String name; public static int age; public static String sex;
public Person() { // 會自動生成無參構造器 System.out.println("父類構造器"); }; // 可是考慮繼承的可靠性,建議寫上。
public void setName(String name) { this.name = name; }
public String getName() { return this.name; } }
class Student extends Person { // 子類 private String school;
public Student() { // 子類student中構造 super(); //super只可在子類中使用 System.out.println("子類構造器"); } } public class TestExtendDemo { // 測試類 public static void main(String[] args) { Person.age = 18; Student.age = 19; // 繼承父類的成員屬性和方法可直接調用 Person.sex = "男"; // 靜態變量或方法用類調用 System.out.println(Student.age+Person.sex); Scanner input = new Scanner(System.in); Student someone = new Student(); //建立子類對象的過程 someone.setName(input.next()); // 實例變量和方法用實例調用 System.out.println(someone.getName()); } } |
繼承是面向對象最顯著的一個特性。多個類中存在相同屬性和方法時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和方法,只要繼承那個類便可。繼承是代碼重用的一種方式。Java經過extends關鍵字來實現單繼承。(Is a)
訪問父類屬性:super.name;
調用父類方法:super.print();
緣由:子類的全部構造器中的第一行,其實都有一條隱身的語句super(), super()表示調用父類的無參構造器。子類繼承父類中的屬性,在new 子類的時候,相應的父類的屬性也就拿到了,這就是子類的實例化過程。
然而父類有有參構造器,則無參構造器就不存在了,因此在子類中須在第一行顯式調用super(參數),或者在父類中添加一個無參構造器。之因此須在第一行調用,是由於父類的構造器調用以及初始化過程必定在子類的前面。
而且,父類也被new一個對象出來的說法是錯誤的,舉例抽象類能夠被繼承的,但抽象類不能被實例化。
參考:Java中屬性的隱藏與方法的覆蓋的區別
參考:靜態綁定與動態綁定
u 子類方法重寫時方法名、參數、返回值、返回類型均須相同。訪問權限不小於父類。
解析:確保子類能夠重寫父類。父類不能覆蓋子類。
u 重寫是父子類要麼都靜態,要麼都不靜態。
u 子類能夠定義與父類同名的靜態方法,以便在子類中隱藏父類的靜態方法。
u 父類的私有方法不可訪問,不能被子類重寫。
abstract class Animal { // 由於自己實例化沒有意義,因此通常申明爲抽象類 Animal() { // 會自動生成無參構造器 }; // 可是考慮繼承的可靠性,建議寫上。
abstract void eat();// 抽象方法 } class Cat extends Animal { // 一、繼承父類 public void eat() { // 二、子類方法的重寫 System.out.println("吃魚"); }
public void catchMouse() { //子類私有方法,只能用子類對象調用 System.out.println("抓老鼠"); } }
class Dog extends Animal { // 一、繼承父類 public void eat() { // 二、子類方法的重寫 System.out.println("吃骨頭"); }
public void kanJia() { System.out.println("看家"); } }
class DuoTaiDemo { // 類名與源文件相同,不然沒法運行 public static void main(String[] args) { function(new Cat()); // new Cat() 表示構造一個貓的對象 function(new Dog());
//Animal a; //對象可像變量同樣聲明和傳遞參數 //a= new Cat(); //父類爲抽象類,不能實例化,但能建立引用 Animal a=new Cat(); // 向上轉型 // 相似變量傳參,new Cat()是參數 a.eat(); //3.父類對象引用指向子類對象 PS:須先知足前兩個條件 }
public static void function(Animal a) { //對象可做變量傳遞參數 a.eat(); //3.父類對象引用指向子類對象 PS:須先知足前兩個條件
if (a instanceof Cat) {// 用於判斷對象是否爲指定類的實例 Cat c = (Cat) a; // 向下轉型,由Animal(父)類轉爲Cat(子)類 c.catchMouse(); // 向下轉型,調用子類特有屬性 } else if (a instanceof Dog) { Dog c = (Dog) a; c.kanJia(); } } |
public class Polymorphism { // 多態傳參 ,取例 Think in Java void doStuff(Shape s) { // 形參 s.erase(); // ... s.draw(); }
public static void main(String[] args) {
Circle c = new Circle(); // Circle/Triangle/Line是Shape的子類 Triangle t = new Triangle(); Line l = new Line(); doStuff(c); // 實參 doStuff(t); doStuff(l); } } |
指容許不一樣類的對象對同一消息作出響應。即同一消息能夠根據發送對象的不一樣而採用多種不一樣的行爲方式。(發送消息就是方法調用),與方法不一樣的是對象的屬性則不具備多態性。
動態綁定:是指在程序運行時判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法,是多態實現的具體形式。執行動態綁定的非靜態方法
補充知識:靜態綁定:又稱爲前期綁定在程序編譯時進行了綁定,即在還沒運行時,就已經加載到內存。執行靜態綁定的有變量和靜態方法
接口實現,繼承父類進行方法重寫,同一個類中進行方法重載。當使用多態方式調用方法時,首先檢查父類中是否有該方法,若是沒有,則編譯錯誤;若是有,再去調用子類的該同名方法。
消除類型之間的耦合關係
u 成員變量:在多態中,子父類成員變量同名。
在編譯時期:參考的是引用型變量所屬的類中是否有調用的成員。(編譯時不產生對象,只檢查語法錯誤)
運行時期:也是參考引用型變量所屬的類中是否有調用的成員。
簡單一句話:不管編譯和運行,成員變量參考的都是引用變量所屬的類中的成員變量。再說的更容易記憶一些:成員變量à編譯運行都看 = 左邊。
u 靜態函數
編譯時期:參考的是引用型變量所屬的類中是否有調用的成員。
運行時期:也是參考引用型變量所屬的類中是否有調用的成員。
爲何是這樣的呢?由於靜態方法,其實不屬於對象,而是所屬於該方法所在的類。
調用靜態的方法引用是哪一個類的引用調用的就是哪一個類中的靜態方法。
簡單說:靜態函數à編譯運行都看 = 左邊。
u 成員函數
編譯時期:參考引用型變量所屬的類中是否有調用的方法。
運行事情:參考的是對象所屬的類中是否有調用的方法。
爲何是這樣的呢?由於在子父類中,對於如出一轍的成員函數,有一個特性:覆蓋。
簡單一句:成員函數,編譯看引用型變量所屬的類,運行看對象所屬的類。
更簡單:成員函數à編譯看 = 左邊,運行看 = 右邊。
public abstract class ClassName { int name; abstract void fun(); } |
public interface InterfaceName { public abstract void cry(); } class ClassName implements Interface1,Interface2....{ } |
在軟件工程中,接口泛指供別人調用的方法或者函數。從這裏,咱們能夠體會到Java語言設計者的初衷,它是對行爲的抽象。
接口是抽象方法的集合。若是一個類實現了某個接口,那麼它就繼承了這個接口的抽象方法。這就像契約模式,若是實現了這個接口,那麼就必須確保使用這些方法。
接口主要用來描述類具備什麼功能,自身不能作任何事情。具體實現交由實現接口的那個類來完成。
參數 |
抽象類 |
接口 |
默認的方法實現 |
它能夠有默認的方法實現 |
全部的方法都是抽象的。不存在方法的實現 |
實現 |
子類使用extends關鍵字來繼承抽象類。若是子類不是抽象類的話,它須要提供抽象類中全部聲明的方法的實現。 |
子類使用關鍵字implements來實現接口。它須要提供接口中全部聲明的方法的實現 |
構造器 |
抽象類有構造器,用於子類初始化 |
接口不能有構造器 |
普通類 |
除了不能實例化抽象類以外,它和普通Java類沒有任何區別 |
接口是徹底不一樣的類型 |
訪問修飾符 |
抽象方法能夠有public、protected和default這些修飾符 |
接口方法默認修飾符是public。不可使用其它修飾符。 |
main方法 |
抽象方法能夠有main方法而且咱們能夠運行它 |
接口沒有main方法,所以咱們不能運行它。 |
多繼承 |
抽象方法能夠繼承一個類和實現多個接口 |
接口只能夠繼承一個或多個其它接口 |
速度 |
它比接口速度要快 |
接口是稍微有點慢的,由於它須要時間去尋找在類中實現的方法。 |
添加新方法 |
若是你往抽象類中添加新的方法,你能夠給它提供默認的實現。所以你不須要改變你如今的代碼。 |
若是你往接口中添加方法,那麼你必須改變實現該接口的類。 |
抽象類是對一種事物的抽象,即對類抽象,而接口是對行爲的抽象。抽象類是對整個類總體進行抽象,包括屬性、行爲,可是接口倒是對類局部(行爲)進行抽象。舉個簡單的例子,飛機和鳥是不一樣類的事物,可是它們都有一個共性,就是都會飛。那麼在設計的時候,能夠將飛機設計爲一個類Airplane,將鳥設計爲一個類Bird,可是不能將 飛行 這個特性也設計爲類,所以它只是一個行爲特性,並非對一類事物的抽象描述。此時能夠將 飛行 設計爲一個接口Fly,包含方法fly( ),而後Airplane和Bird分別根據本身的須要實現Fly這個接口。而後至於有不一樣種類的飛機,好比戰鬥機、民用飛機等直接繼承Airplane便可,對於鳥也是相似的,不一樣種類的鳥直接繼承Bird類便可。從這裏能夠看出,繼承是一個 "是否是"的關係,而 接口 實現則是 "有沒有"的關係。若是一個類繼承了某個抽象類,則子類一定是抽象類的種類,而接口實現則是有沒有、具有不具有的關係,好比鳥是否能飛(或者是否具有飛行這個特色),能飛行則能夠實現這個接口,不能飛行就不實現這個接口。
設計層面不一樣,抽象類做爲不少子類的父類,它是一種模板式設計。而接口是一種行爲規範,它是一種輻射式設計。什麼是模板式設計?最簡單例子,你們都用過ppt裏面的模板,若是用模板A設計了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,若是它們的公共部分須要改動,則只須要改動模板A就能夠了,不須要從新對ppt B和ppt C進行改動。而輻射式設計,好比某個電梯都裝了某種報警器,一旦要更新報警器,就必須所有更新。也就是說對於抽象類,若是須要添加新的方法,能夠直接在抽象類中添加具體的實現,子類能夠不進行變動;而對於接口則不行,若是接口進行了變動,則全部實現這個接口的類都必須進行相應的改動。
Java異常處理的目的是提升程序的健壯性。你能夠在catch和finally代碼塊中給程序一個修正機會,使得程序不因不可控制的異常而影響程序的流程。同時,經過獲取Java異常信息,也爲程序的開發維護提供了方便。
RuntimeException類及其子類都被稱爲運行時異常,這種異常的特色是Java編譯器不去檢查它,也就是說,當程序中可能出現這類異常時,即便沒有用try...catch語句捕獲它,也沒有用throws字句聲明拋出它,仍是會編譯經過。
除了RuntimeException類及其子類外,其餘的Exception類及其子類都屬於受檢查異常,這種異常的特色是要麼用try...catch捕獲處理,要麼用throws語句聲明拋出,不然編譯不會經過。
運行時異常表示沒法讓程序恢復運行的異常,致使這種異常的緣由一般是因爲執行了錯誤的操做。
受檢查異常表示程序能夠處理的異常。受檢查異常表示程序能夠處理的異常。若是拋出異常的方法自己不處理或者不能處理它,那麼方法的調用者就必須去處理該異常,不然調用會出錯,連編譯也沒法經過。
固然,這兩種異常都是能夠經過程序來捕獲並處理的,好比除數爲零的運行時異常。
異常處理機制爲:拋出異常,捕捉異常。
import java.util.InputMismatchException; import java.util.Scanner;
public class TryCatch { public static void main(String[] args) { Scanner input = new Scanner(System.in);
try {// 可能會發生異常的程序代碼 System.out.print("請輸入一個數字:"); int a = input.nextInt(); } catch (InputMismatchException e) {// 捕捉異常 System.err.println("數據類型不符!"); e.printStackTrace(); System.err.println(e.getMessage()); // return; 若捕捉到異常會先執行finally, 再return。 } catch (Exception e) {// catch 先寫子類,再寫父類 System.out.println("再捕捉一次!"); System.exit(1); } finally {// 除非執行System.exit(1),不然都會執行 System.out.println("finally 被執行!"); // 應用舉例:確保關閉數據庫,關閉流 }
System.out.println("我仍是被執行了!"); // 若是提早return,則不執行了 } } |
public class Throws {
public static void main(String[] args) throws Exception{ System.out.println(10 / 0); throw new Exception("拋出異常"); //System.out.println("throw後面的代碼再也不執行"); } } |
數組索引越界異常。當對數組的索引值爲負數或大於等於數組大小時拋出。
算術條件異常。譬如:整數除零等。
空指針異常。當應用試圖在要求使用對象的地方使用了null時,拋出該異常。譬如:調用null對象的實例方法、訪問null對象的屬性、計算null對象的長度、使用throw語句拋出null等等
找不到類異常。當應用試圖根據字符串形式的類名構造類,而在遍歷CLASSPAH以後找不到對應名稱的class文件時,拋出該異常。
待補充~
若是出現異常的線程爲主線程,則整個程序運行終止;若是非主線程,則終止該線程,其餘線程繼續運行。
若是父類或者接口中的方法沒有拋出過異常,那麼子類是不能夠拋出異常的,若是子類的覆蓋的方法中出現了異常,只能try不能throws。
若是這個異常子類沒法處理,已經影響了子類方法的具體運算,這時能夠在子類方法中,經過throw拋出RuntimeException異常或者其子類,這樣,子類的方法上是不須要throws聲明的。
越早處理異常消耗的資源和時間越小,產生影響的範圍也越小。
大多集合可以處理任何類型的數據,由於這些集合定義的處理對象使用了Object類型。
全部的Java集合都在java.util包中。
上述類圖中,實線邊框的是實現類,好比ArrayList,LinkedList,HashMap等,折線邊框的是抽象類,好比AbstractCollection,AbstractList,AbstractMap等,而點線邊框的是接口,好比Collection,Iterator,List等。 |
Java 集合框架 |
|||||
接口 |
實現類 |
是否有序 |
是否容許元素重複 |
特色 |
|
Collection |
Collection |
無序 |
不惟一 |
父接口 |
|
List |
ArraysList |
有序 |
不惟一 |
遍歷訪問效率高[Z1] |
|
LinkedList |
有序 |
不惟一 |
插入刪除效率高 |
||
Set |
AbstractSet |
無序 |
惟一 |
|
|
HashSet |
查找效率高 |
||||
Map |
TreeSet |
二叉排序樹 |
key必須惟一 |
|
|
AbstractMap |
否 |
|
|||
HashMap |
查詢指定元素效率高 |
||||
TreeMap |
二叉排序樹 |
|
返回類型 |
方法 |
解釋 |
boolean |
add(E e) |
確保此 collection 包含指定的元素(可選操做)。 |
void |
clear() |
移除此 collection 中的全部元素(可選操做)。 |
boolean |
contains(Object o) |
若是此 collection 包含指定的元素,則返回 true。 |
boolean |
isEmpty() |
若是此 collection 不包含元素,則返回 true。 |
boolean |
remove(Object o) |
今後 collection 中移除指定元素的單個實例。 |
int |
size() |
返回此 collection 中的元素數。 |
boolean |
equals(Object o) |
比較此 collection 與指定對象是否相等。 |
Object[] |
toArray() |
返回包含此 collection 中全部元素的數組。 |
Iterator<E> |
iterator() |
返回在此 collection 的元素上的迭代器 (接口)。 |
Ps:1.傳入均爲形參,不須類型修飾。2.接口不可實例化。方法所有交由實現類實現。
class Arrays { // 除特殊代表,爲 Collection接口全部實現類所的方法 ArrayList<String> list = new ArrayList<String>();
void OwMethod() { list.add("且聽風吟_z"); list.add("山多拉之燈"); list.add(0, "Jake"); // 使用下標肯定添加位置
System.out.println(list.get(1)); // list 特有 System.out.println("下標爲:" + list.indexOf("Jake")); // list 特有 System.out.println(list.set(0, "Captain")); // 替換元素, list 特有 System.out.println("判斷包含元素:" + list.contains("Captain"));
System.out.println("該集合有元素數:" + list.size()); System.out.println("移除元素:" + list.remove("山多拉之燈"));
System.out.println("字符串型式返回元素:" + list.toString()); System.out.println("這是什麼鬼:" + list.toArray() + "\n");
list.clear(); // 沒有返回值 System.out.println("\n判斷是否爲空:" + list.isEmpty()); } } |
Ps:注意元素時對象時的區別
<E> |
get(int index) |
返回列表中指定位置的元素。 |
<E> |
set(int index, E element) |
用指定元素替換列表中指定位置的元素(可選操做)。 |
<E> |
getFirst() |
返回此列表的第一個元素。 |
<E> |
getLast() |
返回此列表的最後一個元素。 |
<E> |
removeFirst() |
移除並返回此列表的第一個元素。 |
class Link { // LinkedList 方法舉例
LinkedList<String> list2 = new LinkedList<String>();
void OwMethod() { list2.add("No.1"); list2.addFirst("我是第一個!"); list2.add("No.2");
System.out.println("LinkedList 返回元素:" + list2.getFirst()); list2.removeFirst(); System.out.println("LinkedList 返回元素:" + list2.toString()); } } |
Link補充:1. 刪除元素後,index後面的元素會自動向前補齊
2.索引若沒有元素,返回-1。
class Set { // HashSet 方法舉例 HashSet<String> list6 = new HashSet<String>();
void OwMethod() { list6.add("cat"); list6.add("dog"); System.out.println(list6.getClass()); } } |
返回類型 |
方法 |
解釋 |
boolean |
containsKey(Object key) |
確保此 collection 包含指定的元素。 |
<V> |
get(Object key) |
返回指定鍵所映射的值。 |
<V> |
put(K key, V value) |
將指定的值與此映射中的指定鍵關聯。 |
Collection<V> |
values() |
返回此映射中包含的值的 Collection集合。 |
Set<K> |
keySet() |
返回此映射中所包含的鍵的 Set集合。 |
class Map { HashMap<Integer, String> list7 = new HashMap<Integer, String>(); // Map要得是對象,不能放int void OwMethod() {
list7.put(1, "car"); // key 不能夠重複 list7.put(2, "truck"); // Value 的值能夠是普通數據也能夠是對象 list7.put(3, "bus"); System.out.println("是否包含key = 1:" + list7.containsKey(1)); System.out.println("key所對應的值:" + list7.get(1)); System.out.println("包含Value的全部元素:" + list7.values()); System.out.println("包含Key的全部元素:" + list7.keySet());
System.out.println("HashMap返回元素:" + list7.toString() + "\n"); } } |
boolean |
hasNext() |
若是仍有元素能夠迭代,則返回 true。 |
Set<K> |
next() |
返回迭代的下一個元素。 |
void |
remove() |
移除迭代器返回的最後一個元素。 |
補充:遍歷集合元素的幾種方法
Collections.sort(list); // Ps:不是必須的 Iterator<String> iter = list.iterator(); //1.調用迭代器,遍歷集合元素 while (iter.hasNext()) { String name = iter.next(); System.out.println(name); }
for (String str : list) { // 2.使用加強for循環,遍歷集合元素 System.out.println(str); } // 3.轉換成字符串,遍歷集合元素 System.out.println("HashMap返回元素:" + list.toString() + "\n"); |
Java.util.Collections 是一個包裝類。它包含有各類有關集合操做的靜態多態方法。此類不能實例化,用於對集合中元素進行排序、搜索以及線程安全等各類操做。
Void |
sort(List<T> list) |
根據天然順序 對指定列表按升序進行排序。 |
<T> |
Max |
根據天然順序,返回給定 collection 的最大元素。 |
<T> |
Min |
根據天然順序,返回給定 collection 的最小元素。 |
<T> |
Max (Comparator) |
重寫比較器,返回給定 collection 的最大元素。 |
<T> |
Fill(list,obj) |
使用指定元素替換指定列表中的全部元素。 |
<T> |
binarySearch |
使用二分搜索法搜索指定列表,以得到指定對象。 |
注:<T>的正式名稱爲類型參數,也可通俗的稱爲佔位符,符號讀做of T。
Collections.sort(list); Iterator<Student> it = list.iterator(); while (it.hasNext()) { Student stu = (Student) it.next(); System.out.println(stu.getNumber()); }
int index = Collections.binarySearch(list, student1); System.out.println("student1的下標是:" + index);
Student stu1 = Collections.max(list); System.out.println("最大值的下標是:" + stu1.getNumber());
// Collections.fill(list, "我被替換了"); // 替換的是什麼東西?? |
接口:public interface Comparable<T>
此接口強行對實現它的每一個類的對象進行總體排序。這種排序被稱爲類的天然排序,類的 compareTo 方法被稱爲它的天然比較方法。
實現此接口的對象列表(和數組)能夠經過 Collections.sort(和 Arrays.sort)
public int compareTo(Object obj) { Student student = (Student) obj; if (this.number == student.number) { // 用對象仍是get均可以 return 0; } else if (this.number > student.getNumber()) { return 1; } else { return -1; } } |
a) 注意API中參數是對象仍是普通數據類型。
b) 集合中的元素能夠是普通數據也能夠是對象。
c) 泛型執行定義了類型,避免了裝箱和拆箱操做,性能有很大提升了。詳見 高級特性à包裝類à裝箱/拆箱。
泛型,即「參數化類型」。一提到參數,最熟悉的就是定義方法時有形參,而後調用此方法時傳遞實參。那麼參數化類型怎麼理解呢?顧名思義,就是將類型由原來的具體的類型參數化,相似於方法中的變量參數,此時類型也定義成參數形式(能夠稱之爲類型形參),而後在使用/調用時傳入具體的類型(類型實參)。
爲何使用泛型? 先來看使用非泛型集合的兩個問題:性能問題和類型安全問題。
性能問題:無論選擇哪一個類型來保存,都不能避免使用非泛型容器帶來的裝箱問題,因此提出了泛型。
類型安全問題:在泛型以前,要解決類型安全問題的惟一方法是手工建立自定義(強類型的)集合類。
API(Application Programming Interface)應用程序編程接口,它是運行庫的集合,預先定義了一些藉口和類。API 提供以下經常使用的包:
public enum Week { MON, TUE, WED, THU, FRI, SAT, SUN; } // 調用 Week. MON |
public enum FORMAT { YYYY_MM_DD_FORMAT("yyyy-MM-dd"), // 爲枚舉元素賦值先定義元素,再定義屬性 DD_MM_YYYY_FORMAT("dd-mm-yyyy");
private String stringValue;
private FORMAT(String stringValue) { this.stringValue = stringValue; } public String getStringValue() { return stringValue; } } // 調用 FORMAT.DD_MM_YYYY_FORMAT.getStringValue() |
基本數據類型 |
包裝類 |
包裝類 |
包裝類 |
byte |
Byte |
Number |
Object |
short |
Short |
||
int |
Integer |
||
long |
Long |
||
float |
Float |
||
double |
Double |
||
char |
Character |
|
|
boolean |
Boolean |
|
大多集合可以處理任何類型的數據,由於這些集合定義的處理對象使用了Object類型。當集合處理的數據是JAVA中的基本類型時,好比int、float、double類型,這些類型在JAVA中屬於值類型,而這些數據進入集合中時,集合可以處理的是Object這樣的引用類型,因此在值類型的數據進入集合的時候,須要將值類型包裝成引用類型,這個過程就是裝箱的過程,從集合中取出數據時,取出的是引用類型,一樣須要把引用類型還原爲值類型,這個過程就是拆箱的過程。
Integer num1 = new Integer(123); // 手動裝箱方式,構造方法 Integer num2 = new Integer("123"); // 除Character類外的基本類型 Character num3 = new Character('a'); Integer num4 = Integer.valueOf(123); Integer num5 = 1; // 自動裝箱 |
int num1_1 = num1.intValue(); // 手動拆箱方式 int num5_1 = num5; // 自動拆箱 |
String sex=Character.toString('男'); // 基本類型->字符串 int num=Integer.parseInt("36"); // 字符串->基本類型 //可用於校驗字符是否合法 sex='男'+""; // 合併轉換字符串的一種方式 |
//獲取隨機數的兩種random()方法: int show1 = (int) (Math.random() * 5.0D) + 1; int show2 = (int) (Math.random() * 10.0D) % 5 + 1; System.out.println(Math.max(show1, show2)); System.out.println(Math.abs(-10)); // 絕對值運算 System.out.println(Math.E + "\n" + Math.PI); // 兩個常量 //Ps:random()返回一個大於等於0小於1的隨機數。 |
在Java中,字符串被做爲String類型的對象來處理。String類位於java.lang包中。字符串是一個字符序列,事實上也是一個字符數組。可用下標索引。
String s1 = "-Java-"; String s1_1 = s1.toLowerCase(); // 轉爲小寫 String s1_2 = s1.toUpperCase(); // 轉爲大寫
String s2 = "渺千山暮雪,"; String s3 = "萬里層雲,"; String s4 = "隻影向誰去?";
String s5 = s2.concat(s3.concat(s4)); // 鏈接字符串 String[] s6 = s5.split("。|,|?"); // 字符串拆分,用數組接收 String s7 = s5.substring(1, 5); // 提取下標區間字段
System.out.println(s1.equals(s1_2)); // 比較字符串,詳見運算符章節 System.out.println(s1_1.equalsIgnoreCase(s1_2)); // 比較字符串,忽略大小寫 System.out.println(s5); for (String temp : s6) { System.out.println(temp); } System.out.println(s7); // indexOf()查詢若不存在返回index = -1 System.out.println(s7.length()); //字符串長度 System.out.println("第一次出現逗號位置的下標:" + s5.indexOf(",")); System.out.println("最後出現逗號位置的下標:" + s5.lastIndexOf(",")); |
StringBuffer s1 = new StringBuffer("仰天大笑出門去"); StringBuffer s2 = s1.append("無人知是荔枝來!");// 效率比concat()高 StringBuffer s3 = s2.insert(7, ","); // 返回StringBuffer,不能用String接收。 int s4 = s3.hashCode(); //StringBuffer 好多方法能夠用 System.out.println(s3); System.out.println(s4); |
註釋:StringBufffer類和StringBulider類處理字符串的方法基本一致。
Date date = new Date(); // 建立日期對象 SimpleDateFormat formater // HH表示24時制 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("當前時間爲:" + formater.format(date));
Calendar t = Calendar.getInstance(); // 抽象類,獲得子類對象 System.out.println("今天是" + t.get(Calendar.YEAR) + "年" + (t.get(Calendar.MONTH) + 1) + "月" + t.get(Calendar.DAY_OF_MONTH) + "日"); // Calendar.DAY_OF_WEEK 中 Sunday是 1 System.out.println("今天是星期" + (t.get(Calendar.DAY_OF_WEEK) - 1)); } |
Random rand = new Random(47); int show1 = rand.nextInt(10); //產生一個大於等於0,小於10的隨機數 System.out.println(show1); //Math.random()方法底層是使用Random類實現的 |
@SuppressWarnings("static-access") public static void main(String[] args) throws IOException { SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
File file1 = new File("I:/myDoc"); // 建立新 File 實例,建立的是引用 file1.mkdir(); // 建立文件夾 file.mkdirs() file1.createTempFile("temp", ".txt", file1); // 建立臨時文件 System.out.println("是目錄:" + file1.isDirectory());
File file2 = new File("I:/myDoc/temp.txt"); // 但是文件,也但是目錄 file2.createNewFile(); //建立文件 System.out.println("是文件:" + file2.isFile());
System.out.println("文件是否存在:" + file2.exists()); System.out.println("名稱:" + file2.getName()); System.out.println("相對路徑: " + file2.getPath()); System.out.println("絕對路徑: " + file2.getAbsolutePath()); System.out.println("文件大小:" + file2.length() + " 字節"); System.out.println("最後修改日期: " + formater.format(file2.lastModified())); } System.out.println("文件是否刪除:" + file2.delete()); |
流,是指一連串流動的字符,是以先進先出的方式發送和接收數據的通道。流分爲輸入和輸出流。輸入/輸出時相對於內存來講的(往裏讀,往外寫)。Java的輸出流主要有OutputStream和White做爲抽象基類,而輸入流主要由InputStream和Reader做爲抽象基類。
字符流處理的單元爲2個字節的Unicode字符,分別操做字符、字符數組或字符串,而字節流處理單元爲1個字節,操做字節和字節數組。因此字符流是由Java虛擬機將字節轉化爲2個字節的Unicode字符爲單位的字符而成的,因此它對多國語言支持性比較好。
若是是音頻文件、圖片、歌曲,就用字節流好點,若是是關係到中文(文本)的,用字符流好點。
全部文件的儲存是都是字節(byte)的儲存,在磁盤上保留的並非文件的字符而是先把字符編碼成字節,再儲存這些字節到磁盤。在讀取文件(特別是文本文件)時,也是一個字節一個字節地讀取以造成字節序列。
字節流可用於任何類型的對象,包括二進制對象,而字符流只能處理字符或者字符串;字節流提供了處理任何類型的IO操做的功能,但它不能直接處理Unicode字符,而字符流就能夠。
字節流在操做的時候是直接與文件自己關聯,不使用緩衝區,字節直接存到文件中;字符流在操做的時候是經過緩衝區與文件操做,字符到緩衝區而後再到文件中,因此字符流中存在一個flush()方法來刷新緩衝區。
//******** 問題:下列步驟數據存儲和轉換的過程是怎麼樣的? 編碼:UTF-8 ******* // 1. 把一個字符串 "蘇A" 輸入緩衝區 (33487)10000010 11001111 (65)01000001 UTF-16 // 1. 在緩衝區加高位轉換成UTF=8 11101000/10001011/10001111/01000001 // 2. 轉換成byte[] //用長度爲4的字節數組接受 Byte1 = 11101000 Byte2 = ... // 3 .而後存入文本 // 把四個字節數組存入文本(閱讀文本時,解碼器解碼) // 4. 而後從文本讀取 //把文檔內容以字節(符)型式讀入內存,並轉換成char // 注:蘇A == (\u82cf--16進製表達) ((232) 11101000 (139) 10001011 (143) 10001111) (65)01000001 // 若是不知道編碼方式,可能一樣的二進制數,解碼方式有誤,致使解碼失敗。 // IO操做的是序號,經過字庫表,對應顯示正確的字符。 public class Keep_Stream_Test {
public static void main(String[] args) throws IOException {
int date, temp; String line; String str = "蘇A"; //UTF-8 漢字一個字符約三個字節 char a = 'C'; // 一個整型表明一個字符,故能夠互相轉換 byte[] words = str.getBytes(); // 把字符串內容寫進字節數組 System.out.println(System.getProperty("file.encoding")); // 得到本地平臺的字符編碼類型 /** * 字節流寫入數據 * */ FileOutputStream fos1 = new FileOutputStream("I:/text1.txt"); fos1.write(552); // 讀寫的是序號 // 往裏讀,往外寫 // 非正確演示 fos1.write(words, 0, words.length);// 把字節數組存儲的內容寫進流 /** * 字符流寫入數據 * */ FileWriter fw = new FileWriter("I:/text1.txt", true);//不覆蓋原文件 BufferedWriter bw = new BufferedWriter(fw); // 裝飾者模式 bw.write("-南京"); bw.write(')'); bw.flush(); // 往外寫時才用 /** * 字節流讀取數據 * */ FileInputStream fis1 = new FileInputStream("I:/text1.txt"); BufferedInputStream bis1 = new BufferedInputStream(fis1); System.out.println("文件大小:" + bis1.available() + "字節\n"); while ((date = fis1.read()) != -1) { // 把文本內容以字節型式讀入內存 System.out.print(date); System.out.print((char) date); System.out.println("\t" + Integer.toBinaryString(date)); } // 此處對應關係與編碼方式有關,多字節解碼方式有誤 // 沒有緩衝區,讀一個字節,轉一個。so若是漢字是單字節就不會出錯鳥~ System.out.println('\n'); /** * 字符流讀取數據 * */ FileReader fr1 = new FileReader("I:/text1.txt"); BufferedReader br1 = new BufferedReader(fr1); while ((date = br1.read()) != -1) { // 把文檔內容以字符型式讀入內存 System.out.print(date); System.out.print((char) date); System.out.println("\t" + Integer.toBinaryString(date)); } while ((line = br1.readLine()) != null) { // 把文檔內容以字符型式(每次一行)讀入內存,返回字符串。這一段讀不出流 只可用一次。 System.out.print(line); // 因爲字符流有緩衝區,因此2個字符讀(Unicode)與一行行讀均可以,最終按 編碼方式處理。 } /** * 字符流讀取數據 InputStreamReader 是字節流通向字符流的橋樑 * */ InputStreamReader isr = new InputStreamReader(fis1, "UTF-8"); // 轉換流 BufferedReader br2 = new BufferedReader(isr);// 緩衝流 while ((temp = br2.read()) != -1) { System.out.print((char) temp); // 流使用一次就不能再用了?? } System.out.println('\u82cf');// 十六進制表示一個字符 System.out.println((byte) a); } } |
u 緩衝流:緩衝流要「套接」在相應的節點流之上,對讀寫的數據提供了緩衝的功能。
² 字節緩衝流有BufferedInputStream/ BufferedOutputStream,字符緩衝流有BufferedReader/BufferedWriter,字符緩衝流分別提供了讀取和寫入一行的方法ReadLine和NewLine方法。使用字符緩衝流的時候,必定先flush,再close。
u 轉換流:用於字節數據到字符數據之間的轉換。
² 字符流InputStreamReader/OutputStreamWriter。其中,InputStreamReader須要與InputStream「套接」,OutputStreamWriter要與OutputStream「套接」。
u 數據流:提供了讀寫Java中的基本數據類型的功能。
² DataInputStream和DataOutputStream分別繼承自InputStream和OutputStream,須「套接」在InputStream和OutputStream類型的節點流上。
u 對象流:用於直接將對象寫入寫出。
² 對象流類有ObjectInputStream和ObjectOutputStream,自己這兩個方法沒什麼,可是其要寫出的對象有要求,該對象必須實現Serializable接口,來聲明其是能夠序列化的。不然,不能用對象流讀寫。
u 還有一個關鍵字比較重要,transient,因爲修飾實現了Serializable接口的類內的屬性,被該修飾符修飾的屬性,在以對象流的方式輸出的時候,該字段會被忽略。
兩個類的構造方法的形式和參數都是相同的,參數爲File對象或表示路徑的String。
FileInputStream以字節流方式讀取,FileReader把文件轉換爲字符流讀入。
PrintWriter提供的print/println/printf等方法方便使用,並封裝了字節流與字符流之間的轉換。BufferedWriter提供緩衝。詳見TCP編程章節例程。
File流以文件做爲參數,處理流以節點流或其子類做爲參數。
Java輸入、輸入、IO流 類層次關係梳理 http://www.cnblogs.com/LittleHann/p/3678685.html
/** * 二進制文件讀取操做 * */ FileInputStream fis3 = new FileInputStream("I:/text1.txt"); DataInputStream dis1 = new DataInputStream(fis3); /** * 二進制文件寫入操做 * */ FileOutputStream fos2 = new FileOutputStream("I:/text2.txt"); DataOutputStream dos1 = new DataOutputStream(fos2); int temp2; while ((temp2 = dis1.read()) != -1) { // 讀取文件並寫入文件 dos1.write(temp2); } dos1.writeUTF("Hello"); // 將一個字符串寫入文件 dos1.flush(); |
Java的標準輸入/輸出分別經過System.in和System.out來表明,在默認的狀況下分別表明鍵盤和顯示器,當程序經過System.in來得到輸入時,其實是經過鍵盤得到輸入。當程序經過System.out執行輸出時,程序老是輸出到屏幕。
/** * System.out 重定向向文件輸出 * */ PrintStream ps = new PrintStream(new FileOutputStream("work")); System.setOut(ps); System.out.println("Hello World!"); /** * System.in 重定向從文件輸入 * */ FileInputStream fis = new FileInputStream("work"); System.setIn(fis);
Scanner sc = new Scanner(System.in); while (sc.hasNextLine()) { System.out.println(sc.nextLine()); } |
序列化是將對象的狀態寫入到特定的流中的過程,反序列化則是從特定的流中獲取數據從新構建對象的過程。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c:\\myDoc\\stu.txt")); Student stu = new Student("安娜", 30, "女"); // 對象序列化 oos.writeObject(stu);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream( "c:\\myDoc\\stu.txt")); // 對象反序列化 Student stu1 = (Student) ois.readObject(); System.out.println("姓名爲:" + stu1.getName()); System.out.println("年齡爲:" + stu1.getAge()); System.out.println("性別爲:" + stu1.getGender()); Ps:class Student implements java.io.Serializable |
補充:靜態數據不能被序列化,由於靜態數據不在堆內存中,是存儲在靜態方法區中。用transient 關鍵字修飾非靜態數據也不會被序列化。
其實就是動態加載一個指定的類,並獲取該類中的全部的內容。並且將字節碼文件封裝成對象,並將字節碼文件中的內容都封裝成對象,這樣便於操做這些成員。簡單說:反射技術能夠對一個類進行解剖。反射技術大大的加強了程序的擴展性。
參考資料:
咱們在計算機屏幕上看到的是實體化的文字,而在計算機存儲介質中存放的實際是二進制的比特流。那麼在這二者之間的轉換規則就須要一個統一的標準。
字符是各類文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。均佔一個字符,但字節長度因爲編碼方式的不一樣而不一樣。
字符集(Charset):是字符的集合。常見字符集有:ASCII字符集、ISO-8859-1字符集(兼容ASCII) 、GB2312字符集(兼容ASCII) 、GBK字符集(兼容GB2312)、BIG5字符集、GB18030字符集(兼容GBK)、Unicode(兼容ISO-8859-1)字符集等。
字符不必定適合做傳輸、儲存等處理,有時須經編碼(encode)後才能應用。如Unicode(UTF-八、UTF-1六、UTF-32)、GBK等方式編碼。
對於一個字符集來講要正確編碼轉碼一個字符須要三個關鍵元素:字庫表(character repertoire)、編碼值(coded character set)、字符編碼(character encoding form)。其中字庫表是一個至關於全部可讀或者可顯示字符的數據庫,字庫表決定了整個字符集可以展示表示的全部字符的範圍。用一個編碼值(數值代碼)來對應字庫中的每個字符。字符編碼,將編碼值(數值代碼)以必定編碼方式轉化成二進制數,以便與進行傳輸、儲存等處理。過程:字符à編碼值à二進制值。
蘇A 的 存 儲 形 式 爲 : ASCII 碼: (33487) 10000010 11001111 (65) 01000001 UTF-8: (\u82cf)( (232) 11101000 (139) 10001011 (143) 10001111) (65) 01000001 |
符號:英文標點佔一個字節,全角兩個字節。中文標點佔兩個字節,全角四個字節。
參考文章:十分鐘搞清字符集和字符編碼,字符集和字符編碼(Charset & Encoding)
全部的文件在內存和磁盤中都是二進制格式的,因此文本文件與二進制文件的區別並非物理上的,而是邏輯上的。這二者只是在編碼層次上有差別。
文本文件是基於字符編碼的文件,常見的編碼有ASCII(雙字節字符集)、Unicode(可變字節字符集)編碼等。二進制文件是基於值編碼的文件,二進制讀取只可正對二進制文件。
用ASCII方式處理文件,一個字節(8 Bite)放一個ASCII字符,於是便於對字符進行逐個處理,也便於輸出字符,但通常佔儲空間較多,並且要花費較多的轉換時間。二進制文件是把內存中的數據按其在內存中的存儲形式原樣輸出到磁盤上存放,用二進制形式輸出數值,能夠節省外存空間和轉換時間。
文本文件的讀取須要按照相應的編碼方式進行解碼。
5678 的 存 儲 形 式 爲 : ASCII 碼: 00110101 00110110 00110111 00111000 (四個字節) 二進制: 00010110 00101110 (兩個字節) |
註釋:ASCII碼是8 Bite的編碼,Unicode碼元通常佔16 Bite。
待補充~
註解一種標記
Annotation //註解
@Deprecated
@SuppressWarnings("deprecation") 消除警告
@Override 重寫
自定義註解
好比A註解
public @interface A {
}
元註解
@Retention
@Target
待補充~
進程:正在進行中的程序。其實進程就是一個應用程序運行時的內存分配空間。
線程:其實就是進程中一個程序執行控制單元,一條執行路徑。進程負責的是應用程序的空間的標示。線程負責的是應用程序的執行順序。
public class Thread_Demo {
public static void main(String[] args) { Demo1 d1 = new Demo1(); // Runnable實現類,只有run()方法 Thread t = new Thread(d1); // Thread對象調用start()方法 t.start();
Demo2 d2 = new Demo2(); d2.start(); //Thread對象調用start()方法 } }
class Demo1 implements Runnable { // 實現Runnable接口方式實現多線程
public void run() { System.out.println("Runnable"); } }
class Demo2 extends Thread { // 繼承Thread類實現多線程 public void run() { System.out.println("Thread"); } |
運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
u 等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
u 同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
u 其餘阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程從新轉入就緒狀態。
當多條語句在操做同一個線程共享數據時,一個線程對多條語句只執行了一部分,還沒執行完,另外一個線程參與進來執行,致使共享數據的錯誤。
解決辦法:對多條操做共享數據的語句,只能讓一個線程都執行完,在執行過程當中,其餘線程不執行。
同步代碼塊: public class ThreadDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t, "窗口一"); Thread t2 = new Thread(t, "窗口二"); Thread t3 = new Thread(t, "窗口三"); Thread t4 = new Thread(t, "窗口四"); t1.start(); t2.start(); t3.start(); t4.start(); } }
class Ticket implements Runnable { private int ticket = 100;
public void run() { while (true) { synchronized (new Object()) { // synchronized關鍵字,用來修飾方法或代碼塊的時,保證同時最多隻有一個線程執行 該段代碼。 if (ticket <= 0) break; System.out.println(Thread.currentThread().getName() + "---賣出"+ ticket--); } } } } |
同步函數: public class ThreadDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t, "窗口一"); Thread t2 = new Thread(t, "窗口二"); Thread t3 = new Thread(t, "窗口三"); Thread t4 = new Thread(t, "窗口四"); t1.start(); t2.start(); t3.start(); t4.start(); } }
class Ticket implements Runnable { private int ticket = 100;
public synchronized void saleTicket() { if (ticket > 0) System.out.println(Thread.currentThread().getName() + "賣出了" + ticket--); }
public void run() { while (true) { saleTicket(); } } } |
等待喚醒機制: |
生產消費機制: |
參考資料:
網絡編程的目的就是指直接或間接地經過網絡協議與其餘計算機進行通信。網絡編程中有兩個主要的問題,一個是如何準確的定位網絡上一臺或多臺主機,另外一個就是找到主機後如何可靠高效的進行數據傳輸。在TCP/IP協議中IP層主要負責網絡主機的定位,數據傳輸的路由,由IP地址能夠惟一地肯定Internet上的一臺主機。而TCP層則提供面向應用的可靠的或非可靠的數據傳輸機制,這是網絡編程的主要對象,通常不須要關心IP層是如何處理數據的。
目前較爲流行的網絡編程模型是客戶機/服務器(C/S)結構。
是目前世界上應用最爲普遍的協議,是以TCP和IP爲基礎的不一樣層次上多個協議的集合,也成TCP/IP協議族、或TCP/IP協議棧
IP網絡中每臺主機都必須有一個惟一的IP地址,IP地址是一個邏輯地址。
爲進行網絡中的數據交換(通訊)而創建的規則、標準或約定。(=語義+語法+規則)。
不一樣層具備各自不一樣的協議。
IP地址用來標識網絡上的計算機,而端口號用來指明該計算機上的應用程序。
一臺計算機要發送數據到另外一臺計算機,數據首先必須打包,打包的過程稱爲封裝。
封裝就是在數據前面加上特定的協議頭部。
網絡上具備惟一標識的IP地址和端口組合在一塊兒才能構成惟一能識別的標識符套接字。
u 通訊的兩端都有Socket。
u 網絡通訊其實就是Socket間的通訊。
u 數據在兩個Socket間經過IO傳輸。
針對網絡通訊的不一樣層次,Java提供了不一樣的API,其提供的網絡功能有四大類:
// 使用域名建立對象 InetAddress inet1 = InetAddress.getByName("www.163.com"); System.out.println(inet1); // 使用IP建立對象 InetAddress inet2 = InetAddress.getByName("127.0.0.1"); // 127.0.0.1是一個回送地址,指本地機,通常用來測試使用 System.out.println(inet2); // 得到本機地址對象 InetAddress inet3 = InetAddress.getLocalHost(); System.out.println(inet3); // 得到對象中存儲的域名 String host = inet3.getHostName(); System.out.println("域名:" + host); // 得到對象中存儲的IP String ip = inet3.getHostAddress(); System.out.println("IP:" + ip); |
// 建立一個URL的實例 URL baidu = new URL("http://www.baidu.com"); URL url = new URL(baidu, "/index.html?username=tom#test"); // ?表示參數,#表示錨點 System.out.println(url.getProtocol()); // 獲取協議 System.out.println(url.getHost()); // 獲取主機 System.out.println(url.getPort()); // 若是沒有指定端口號,根據協議不一樣使用默認端口。getPort()方法的返回值爲 -1 System.out.println(url.getPath()); // 獲取文件路徑 System.out.println(url.getFile()); // 文件名,包括文件路徑+參數 System.out.println(url.getRef()); // 相對路徑,就是錨點,即#號後面的內容 System.out.println(url.getQuery()); // 查詢字符串,即參數 |
URL url_2 = new URL("http://www.baidu.com"); InputStream is = (InputStream) url_2.openStream(); // 經過openStream方法獲取資源的字節輸入流 InputStreamReader isr = new InputStreamReader(is, "UTF-8"); // 將字節輸入流轉換爲字符輸入流,若是不指定編碼,中文可能會出現亂碼 BufferedReader br = new BufferedReader(isr); // 爲字符輸入流添加緩衝,提升讀取效率 String data = br.readLine();// 讀取數據 while (data != null) { System.out.println(data);// 輸出數據 data = br.readLine(); } br.close(); isr.close(); is.close(); |
TCP協議是面向鏈接的、可靠的、有序的、以字節流的方式發送數據,經過三次握手方式創建鏈接,造成傳輸數據的通道,在鏈接中進行大量數據的傳輸,效率會稍低。
|
① 建立ServerSocket和Socket
② 打開鏈接到Socket的輸入/輸出流
③ 按照協議對Socket進行讀/寫操做
④ 關閉輸入輸出流、關閉Socket
① 建立ServerSocket對象,綁定監聽端口
② 經過accept()方法監聽客戶端請求
③ 鏈接創建後,經過輸入流讀取客戶端發送的請求信息
④ 經過輸出流向客戶端發送鄉音信息
⑤ 關閉相關資源
public class DemoTCP_Server { public static void main(String[] args) throws IOException { /** * 基於TCP協議的Socket通訊,實現用戶登陸,服務端 */ // 一、建立一個服務器端Socket,即ServerSocket,指定綁定的端口,並監聽此端口 ServerSocket serverSocket = new ServerSocket(10086); // 二、調用accept()方法開始監聽,等待客戶端的鏈接 Socket socket = serverSocket.accept(); // 三、getInputStream()方法獲取輸入流,並讀取客戶端信息 InputStream is = socket.getInputStream(); // 返回InputStream InputStreamReader isr = new InputStreamReader(is); // 轉化流處理 BufferedReader br = new BufferedReader(isr); String info = null; while ((info = br.readLine()) != null) { System.out.println("我是服務器,客戶端說:" + info); } socket.shutdownInput(); // 關閉輸入流 // 四、獲取輸出流,響應客戶端的請求 OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os); pw.write("歡迎您!"); pw.flush();
// 五、關閉資源,注意順序 pw.close(); os.close(); br.close(); isr.close(); is.close(); socket.close(); serverSocket.close(); } } |
① 建立Socket對象,指明須要鏈接的服務器的地址和端口號
② 鏈接創建後,經過輸出流想服務器端發送請求信息
③ 經過輸入流獲取服務器響應的信息
④ 關閉響應資源
public class DemoTCP_Clinet { // 客戶端 public static void main(String[] args) throws IOException {
// 一、建立客戶端Socket,指定服務器地址和端口 Socket socket = new Socket("localhost", 10086); // 二、獲取輸出流,向服務器端發送信息 OutputStream os = socket.getOutputStream();// 字節輸出流 PrintWriter pw = new PrintWriter(os);// 將輸出流包裝成打印流 pw.write("用戶名:admin;密碼:123"); pw.flush(); socket.shutdownOutput(); // 關閉客戶端的輸出流。至關於給流中加入一個結束標記-1 // 三、獲取輸入流,並接收服務器端的反饋信息 InputStream is = socket.getInputStream(); // BufferedReader br = new BufferedReader(new InputStreamReader(is)); Scanner input = new Scanner(new InputStreamReader(is)); while (input.hasNextLine()) { //用Scanner接收輸入流,對比服務端方法優劣 System.out.println("我是客戶端,服務器說:" + input.nextLine()); }
// 四、關閉資源 input.close(); is.close(); pw.close(); os.close(); socket.close(); } } |
PrintWriter做爲一個便捷的字節流與字符流之間的轉換工具,已經封裝了轉換的方法,直接使用它回寫的時候,不用再使用getBytes()轉換成字節流。
如用byte數組接收,將獲得的字節流寫入數組後,得把它轉化爲一個String的對象(用String(數組名,第一個索引,長度))。
如用緩衝流接收時,須要用InputStreamReader轉化。綜合來講,仍是PrintWriter比較方便。
shutdownInput():關閉Socket的輸入流,程序還能夠經過該Socket的輸出流輸出數據。
客戶端鏈接到服務器後,開始發送數據,發送完成後無須再次發送數據,只須要讀取服務器響應數據便可,當讀取響應完成後,該Socket鏈接也被關閉了。
Scanner接收InputSteam對象,調用nextLine()方法讀取流文件。
① 服務器端建立ServerSocket,循環調用accept()等待客戶端鏈接
② 客戶端建立一個socket並請求和服務器端鏈接
③ 服務器端接受客戶端請求,建立socket與該客戶創建專線鏈接
④ 創建鏈接的兩個socket在一個單獨的線程上對話
⑤ 服務器端繼續等待新的鏈接
public class DemoThread_Clinet { // 客戶端 public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost",10086); socket.close(); } } |
public class DemoThread_Server extends Thread {// 服務器端 Socket socket = null; public DemoThread_Server(Socket socket) { // 以Sockeet爲參的構造方法 this.socket = socket; }
public void run() { }
public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(10086); Socket socket = null; int count = 0;// 記錄客戶端的數量 while (true) { socket = serverSocket.accept(); // 阻塞狀態,接收客戶端請求,而後往下執行,新增線程 DemoThread_Server serverThread = new DemoThread_Server(socket); serverThread.start(); count++; System.out.println("客戶端鏈接的數量:" + count); } } } |
UDP協議(用戶數據報協議)是無鏈接的、不可靠的、無序的,速度快。進行數據傳輸時,首先將要傳輸的數據定義成數據報(Datagram),大小限制在64k,在數據報中指明數據索要達到的Socket(主機地址和端口號),而後再將數據報發送出去。
① 建立DatagramSocket,指定端口號
② 建立DatagramPacket
③ 接受客戶端發送的數據信息
④ 讀取數據
public class DemoUDP_Server { /** * 服務器端,實現基於UDP的用戶登陸 * */ public static void main(String[] args) throws IOException {
// 一、建立服務器端DatagramSocket,指定端口 DatagramSocket socket = new DatagramSocket(8888); // 二、建立數據報,用於接受客戶端發送的數據 byte[] data = new byte[1024]; DatagramPacket packet = new DatagramPacket(data, data.length); // 三、接受客戶端發送的數據 socket.receive(packet);// 此方法在接受數據報以前會一直阻塞 // 四、讀取數據 String info = new String(data, 0, data.length); System.out.println("我是服務器,客戶端告訴我" + info);
// 一、定義客戶端的地址、端口號、數據 InetAddress address = packet.getAddress(); int port = packet.getPort(); byte[] data2 = "歡迎您!".getBytes(); // 二、建立數據包,包含響應的數據信息 DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port); // 三、響應客戶端` socket.send(packet2); // 四、關閉資源 socket.close(); } } |
① 定義發送信息
② 建立DatagramPacket,包含將要發送的信息
③ 建立DatagramSocket
④ 發送數據
public class DemoUDP_Clinet { // 客戶端
public static void main(String[] args) throws IOException {
// 一、定義服務器的地址、端口號、數據 InetAddress address = InetAddress.getByName("localhost"); int port = 8888; byte[] data = "用戶名:admin;密碼:123".getBytes(); // 二、封包,包含發送的數據信息 DatagramPacket packet = new DatagramPacket(data, data.length, address, port); // 三、建立DatagramSocket對象 DatagramSocket socket = new DatagramSocket(); // 四、向服務器發包 socket.send(packet);
// 一、建立數據包,用於接受服務器端響應數據 byte[] data2 = new byte[1024]; DatagramPacket packet2 = new DatagramPacket(data2, data2.length); // 二、接受服務器響應的數據 socket.receive(packet2); String reply = new String(data2, 0, packet2.getLength()); System.out.println("我是客戶端,服務器說:" + reply); // 四、關閉資源 socket.close(); } } |
參考資料:
<?xml version = "1.0" encoding="UTF-8"?> <PhoneInfo> <Brand name="華爲"> <Type name="U8650"></Type> <Type name="HW123"></Type> <Type name="HW321"></Type> </Brand> <Brand name="蘋果"> <Type name="Iphone5"></Type> <Type name="Iphone6"></Type> <Type name="Iphone6s"></Type> </Brand> </PhoneInfo> |
public class ParseXMLDemo { // Document、NoteList、Note、Element 接口 private Document document;
public static void main(String[] args) throws Exception { ParseXMLDemo pd = new ParseXMLDemo(); pd.getDocument(); pd.showInfo(); System.out.println("------------------"); pd.add(); pd.delete(); pd.update(); pd.showInfo(); pd.saveXML("E:/JAVA/U1/U2-1/src/chapter06/new.xml"); }
public void getDocument() throws Exception { // 得到DOM樹 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.parse("E:/JAVA/U1/U2-1/src/chapter06/XMLDemo.xml"); // 一、建立解析器工廠 二、建立解析器 三、操做xml對象 }
public void showInfo() {// 獲取手機品牌和屬性 NodeList brands = document.getElementsByTagName("Brand"); for (int i = 0; i < brands.getLength(); i++) { Node node = brands.item(i); Element eleBrand = (Element) node;// 節點強轉元素 System.out.println(eleBrand.getAttribute("name"));
NodeList types = node.getChildNodes(); for (int j = 1; j < types.getLength(); j++) { Node typeNode = types.item(j); if (typeNode.getNodeType() == node.ELEMENT_NODE) {//元素節點 Element eleType = (Element) typeNode; System.out.println("\t" + eleType.getAttribute("name")); } } } }
public void saveXML(String path) throws Exception { TransformerFactory factory = TransformerFactory.newInstance(); factory.setAttribute("indent-number", "4");// 設置縮進 Transformer transformer = factory.newTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");//轉換器 transformer.setOutputProperty(OutputKeys.INDENT, "yes");//開啓縮進 // StreamResult result=new StreamResult(new FileOutputStream(path)); DOMSource source = new DOMSource(document);// 設置源 StreamResult result = new StreamResult(new OutputStreamWriter( new FileOutputStream(path), "UTF-8"));// 設置目標 transformer.transform(source, result);// 轉換 }
public void add() throws Exception {// 添加 Element element1 = document.createElement("Brand"); element1.setAttribute("name", "三星"); Element element2 = document.createElement("Type"); element2.setAttribute("name", "Note3"); element1.appendChild(element2); document.getElementsByTagName("PhoneInfo").item(0) .appendChild(element1); this.saveXML("E:/JAVA/U1/U2-1/src/chapter06/new.xml"); }
public void update() throws Exception {// 修改 NodeList brands = document.getElementsByTagName("Brand"); for (int i = 0; i < brands.getLength(); i++) { Node brand = brands.item(i); Element eleBrand = (Element) brand; // 修改的是元素的屬性 eleBrand.setAttribute("id", i + ""); // i轉爲String this.saveXML("E:/JAVA/U1/U2-1/src/chapter06/new.xml"); } }
public void delete() throws Exception {// 刪除 NodeList brands = document.getElementsByTagName("Brand"); for (int i = 0; i < brands.getLength(); i++) { Node brand = brands.item(i); Element eleBrand = (Element) brand; if ("華爲".equals(eleBrand.getAttribute("name"))) { eleBrand.getParentNode().removeChild(eleBrand); } this.saveXML("E:/JAVA/U1/U2-1/src/chapter06/new.xml"); } } } |
|
在內存中分配連續的空間,
遍歷訪問效率高,可是在添加和刪除
非尾部元素時會致使後面的全部元素的移動,
致使須要從新判斷後面元素的下標,
這就形成ArrayList對插入、刪除、等操做性能低下。