一個簡單的Java程式
// HelloJava.java
public class HelloJava {
public static void main(String[] args) {
System.out.println("Hello Java!");
}
}
- Java是區分大小寫的
- 關鍵字public稱為訪問修飾符,這些修飾符用于控制程式的其他部分對這段代碼的訪問級別
- Java類名的標準命名規范:駱駝命名法,類名以大寫字母開頭,如果名字由多個單詞組成,每個單詞的第一個字母都應該大寫,
- 源代碼的檔案名必須與公共類的名字相同,并用.java作為擴展名,因此存盤上面這段代碼的檔案名必須是HelloJava.java
使用命令列工具編譯運行Java程式
- java -version:查看Java SE的版本資訊
javac HelloJava.java:編譯.java源檔案,生成后綴為.class的位元組碼檔案java HelloJava:使用Java解釋器將位元組碼檔案翻譯成機器代碼
Java程式的執行程序

Java程式的運行必須經過撰寫、編譯和運行3個步驟
- 編輯:是指在Java開發環境中進行程式代碼的輸入,最終形成后綴名為.java的Java源檔案,
- 編譯:是指使用Java編譯器對源檔案進行錯誤排査的程序,編譯后將生成后綴名為.class的位元組碼檔案,不像C語言那樣生成可執行檔案,
- 運行:是指使用Java解釋器將位元組碼檔案翻譯成機器代碼,執行并顯示結果,
什么是位元組碼檔案?
位元組碼檔案是一種和任何具體機器環境及作業系統環境無關的中間代碼,它是一種二進制檔案,是Java源檔案由Java編譯器編譯后生成的目標代碼檔案,編程人員和計算機都無法直接讀懂位元組碼檔案,它必須由專用的Java解釋器來解釋執行,因此Java是一種在編譯基礎上進行解釋運行的語言,
Java解釋器負責將位元組碼檔案翻譯成具體硬體環境和作業系統平臺下的機器代碼,以便執行,因此Java程式不能直接運行在現有的作業系統平臺上,它必須運行在被稱為Java虛擬機的軟體平臺之上,
Java虛擬機(JVM)是運行Java程式的軟體環境,Java解釋器是Java虛擬機的一部分,在運行Java程式時,首先會啟動JVM,然后由它來負責解釋執行Java的位元組碼程式,并且Java位元組碼程式只能運行于JVM之上,這樣利用JVM就可以把Java位元組碼程式和具體的硬體平臺以及作業系統環境分隔開來,只要在不同的計算機上安裝了針對特定平臺的JVM,Java程式就可以運行,而不用考慮當前具體的硬體平臺及作業系統環境,也不用考慮位元組碼檔案是在何種平臺上生成的,
JVM把這種不同軟、硬體平臺的具體差別隱藏起來,從而實作了真正的二進制代碼級的跨平臺移植,JVM是Java平臺架構的基礎,Java的跨平臺特性正是通過在JVM中運行Java程式實作的,Java的這種運行機制可通過下圖說明:

Java語言這種“一次撰寫,多端運行”的方式,有效地解決了目前大多數高級程式設計語言需要針對不同系統來編譯產生不同機器代碼的問題,即硬體環境和操作平臺的異構問題,大大降低了程式開發、維護和管理的開銷,
Java程式通過JVM可以實作跨平臺特性,但JVM是不跨平臺的,也就是說,不同作業系統之上的JVM是不同的,Windows平臺之上的JVM不能用在 Linux平臺,反之亦然,
注釋(Comments)
// 行注釋
/*
塊注釋
*/
JDK包含一個很有用的工具,叫做javadoc,它可以由源檔案生成一個HTML檔案
/**
*/
/**
*
*
*/
上面兩種格式都是合法的,第二種是大部分IDE會提供的格式,
在檔案注釋的第一句應該是概要性的句子,javadoc工具自動將這些句子抽取出來生成概要頁
類注釋必須放在import陳述句之后,類定義之前,每個方法注釋必須放在所描述的方法之前,
常用的javadoc標記
- @author:指定Java程式的作者,
- @version:指定源檔案的版本,
- @deprecated:不推薦使用的方法,
- @param:方法的引數說明資訊,
- @return:方法的回傳值說明資訊,
- @see:“參見”,用于指定交叉參考的內容,
- @exception:拋出例外的型別,
- @throws:拋出的例外,和@exception同義,
需要指出的是,這些標記的使用是有位置限制的,上面這些標記可以出現在類或者介面檔案注釋中的有@see、@deprecated、@author、@version等;可以出現在方法或構造器檔案注釋中的有@see、@deprecated、@param、@return、@throws和@exception等;可以出現在成員變數的檔案注釋中的有@see和@deprecated等,
關鍵字(Keywords)
Java語言中有一些具有特殊用途的單詞被稱為關鍵字(keywords),當定義識別符號時,不要讓識別符號和關鍵字相同,否則將引起錯誤,
| abstract | continue | for | new | switch |
|---|---|---|---|---|
| assert | default | if | packa | synchronized |
| boolean | do | goto | private | this |
| break | double | implements | protected | throw |
| byte | else | import | public | throws |
| case | enum | instanceof | return | transient |
| catch | extends | int | short | try |
| char | final | interface | static | void |
| class | finally | long | strictfp | volatile |
| const | float | native | super | while |
其中goto和const這兩個關鍵字也被稱為保留字,意思是,Java現在還未使用這兩個關鍵字,但可能在未來的Java版本中使用這兩個關鍵字,
以下字符序列不能用作關鍵字:
- true、false不能用作關鍵字,它們是boolean型字面量
- null不能用作關鍵字,它是null字面量
- var也不是關鍵字,而是作為識別符號和lambda形式引數
資料型別
Java是一種強型別語言,這意味著必須為每一種變數宣告一種型別,Java中支持的資料型別分為兩類:基本型別(Primitive Type)和參考型別(Reference Type),
基本型別包括boolean型別和數值型別,數值型別有整數型別和浮點型別,整數型別包括byte、short、int、long、char,浮點型別包括float和double
參考型別包括類、介面和陣列型別,還有一種特殊的null型別,所謂參考資料型別就是對一個物件的參考,物件包括實體和陣列兩種,
空型別(null type)就是null值的型別,這種型別沒有名稱,因為null型別沒有名稱,所以不可能宣告一個null型別的變數或者轉換到null型別,空參考(null)是null型別變數唯一的值,空參考(null)可以轉換為任何參考型別,

?? 在 Java 中 boolean 型別占多少位元組 | Binkery 技術博客
| 基本型別 | 位數 | 位元組 | 默認值 | 取值范圍 | 其他 |
|---|---|---|---|---|---|
| byte | 8 | 1 | 0 | -128~127 | |
| short | 16 | 2 | 0 | -32768~32767 | |
| int | 32 | 4 | 0 | 2147483648 ~ 2147483647 | |
| long | 64 | 8 | 0L | 9223372036854775808 ~ 9223372036854775807 | 初始化long型變數,須后加‘l’或‘L’ |
| char | 16 | 2 | 'u0000’ | 0 ~ 65535 | |
| float | 32 | 4 | 0f | 1.4E-45 ~ 3.4028235E38 | 初始化float型變數,須后加‘f’或‘F’ |
| double | 64 | 8 | 0d | 4.9E-324 ~ 1.7976931348623157E308 | |
| boolean | 1 | false | true、false |
Java語言支持一些特殊的轉義字符序列,
| \n | 換行 (0x0a) |
|---|---|
| \r | 回車 (0x0d) |
| \f | 換頁符(0x0c) |
| \b | 退格 (0x08) |
| \0 | 空字符 (0x0) |
| \s | 空格 (0x20) |
| \t | 制表符 |
| " | 雙引號 |
| ' | 單引號 |
| \ | 反斜杠 |
| \ddd | 八進制字符 (ddd) |
| \uxxxx | 16進制Unicode字符 (xxxx) |
型別轉換
自動型別轉換

整型的默認型別是int,浮點數的默認型別是double,
- 有多種型別的資料混合運算時,系統首先自動將所有資料轉換成容量最大的那種資料型別,然后再進行計算,
- byte,short,char之間不會相互轉換,他們三者在計算時首先轉換為int型別,
- boolean型別不能與其它資料型別運算,
- 當把任何基本資料型別的值和字串(String)進行連接運算時(+),基本資料型別的值將自動轉化為字串(String)型別,
強制型別轉換
double x = 9.997;
int nx = (int) x;
如果想要對浮點數進行舍入運算,以便得到最接近的整數,那就需要用到Math.round()方法:
double x = 9.997;
int nx = (int)Math.round(x);
?? 如果試圖將一個數值從一種型別強制轉換為另一種型別,而又超出了目標型別的表示范圍,結果就會截斷成一個完全不同的值,例如,(byte)300的實際值為44
流程控制
-
if陳述句
if(logic expression){ statement }if(logic expression){ statement }else{ statement }if(logic expression){ statement }else if{ statement }else if{ statement } ... else{ } -
switch陳述句
switch (expression){ case condition1: { statement(s) break; } case condition1: { statement(s) break; } ... case conditionN: { statement(s) break; } default: statement(s) } -
while回圈
[init_statement] while(test_expression){ statement; [iteration_statement] } -
do-while回圈
[init_statement] do{ statement; [iteration_statement] }while(test_expression)do-while回圈與while回圈的區別在于:while回圈是先判斷回圈條件,如果條件為真則執行回圈體;而do-while回圈則先執行回圈體,然后才判斷回圈條件,如果回圈條件為真,則執行下一次回圈,否則終止回圈,
-
for回圈
for(init_statement;test_expression;iteration_statement){ statement }程式執行for回圈時,先執行回圈的初始化陳述句init_statement,初始化陳述句只在回圈開始前執行一次,每次執行回圈體之前,先計算test_expression回圈條件的值,如果回圈條件返true,則執行回圈體,回圈體執行結束后執行回圈迭代陳述句,因此,對于for回圈而言,回圈條件總比回圈體要多執行一次,因為最后一次執行回圈條件回傳false,將不再執行回圈體,
-
for-each回圈
for(Type var:array){ statement } -
break
?? break用于switch陳述句中,終止switch陳述句break用于回圈時,跳出回圈
public class BreakTest { public static void main(String[] args) { for(int n = 0; n < 3; n++){ if(n == 1){ break; } System.out.println("n = " + n); } System.out.println("================"); // 嵌套回圈,break在內層 for(int i = 0; i < 3; ++i){ for(int j = 0; j < 3; j++){ if(i==1){ break; } System.out.println("i = "+ i +", j = " + j); } } System.out.println("================"); // 嵌套回圈,break在外層 for(int i = 0; i < 3; ++i){ if(i==1){ break; } for(int j = 0; j < 3; j++){ System.out.println("i = "+ i +", j = " + j); } } } }?? 在有break陳述句的嵌套回圈中,break只能跳出當前回圈,即如果break陳述句在外層,則會跳出整個回圈;而如果break陳述句在內層,則只會跳出當前所在的內層回圈,
-
continue
?? continue用在回圈中,跳出本次回圈,繼續執行下一次回圈
public class ContinueTest { public static void main(String[] args) { for(int n = 0; n < 3; n++){ if(n == 1){ continue; } System.out.println("n = " + n); } System.out.println("================"); // 嵌套回圈 for(int i = 0; i < 3; ++i){ for(int j = 0; j < 3; j++){ if(i ==1 && j == 1){ continue; } System.out.println("i = "+ i +", j = " + j); } } } }
陣列
Java的陣列要求所有的陣列元素具有相同的資料型別,既可以存盤基本型別的資料,也可以存盤參考型別的資料
?? 因為Java語言是面向物件的語言,而類與類之間可以支持繼承關系,這樣可能產生一個陣列里可以存放多種資料型別的假象,例如有一個水果陣列,要求每個陣列元素都是水果,實際上陣列元素既可以是蘋果,也可以是香蕉(蘋果、香蕉都繼承了水果,都是一種特殊的水果),但這個陣列的陣列元素的型別還是唯一的,只能是水果型別,
定義陣列
type[] arrayName; // 推薦使用
type arrayName[l;
陣列是一種參考型別的變數,因此使用它定義一個變數時,僅僅表示定義了一個參考變數(也就是定義了一個指標),這個參考變數還未指向任何有效的記憶體,因此定義陣列時不能指定陣列的長度,而且由于定義陣列只是定義了一個參考變數,并未指向任何有效的記憶體空間,所以還沒有記憶體空間來存盤陣列元素,因此這個陣列也不能使用,只有對陣列進行初始化后才可以使用,
陣列初始化
初始化,就是為陣列的陣列元素分配記憶體空間,并為每個陣列元素賦初始值,
一旦陣列的初始化完成,陣列在記憶體中所占的空間將被固定下來,因此陣列的長度將不可改變,即使把某個陣列元素的資料清空,但它所占的空間依然被保留,依然屬于該陣列,陣列的長度依然不變,
陣列的初始化有如下兩種方式:
-
靜態初始化:初始化時由程式員顯式指定每個陣列元素的初始值,由系統決定陣列長度,
arrayName = new type[] {element1,element2,element3,element4 ...}; -
動態初始化:初始化時程式員只指定陣列長度,由系統為陣列元素分配初始值,
arrayName = new type[length];- 陣列元素的型別是基本型別中的整數型別(byte、short、int、long),則陣列元素的值是0,
- 陣列元素的型別是基本型別中的浮點型別(float、double),則陣列元素的值是0.0,
- 陣列元素的型別是基本型別中的字符型別(char),則陣列元素的值是'\u0000',
- 陣列元素的型別是基本型別中的布爾型別(boolean),則陣列元素的值是false,
- 陣列元素的型別是參考型別(類、介面和陣列),則陣列元素的值是null,
使用陣列
Java語言的陣列索引是從0開始,陣列最常用的用法就是訪問陣列元素,包括對陣列元素進行賦值和取出陣列元素的值,訪問陣列元素都是通過在陣列參考變數后緊跟一個方括號[],方括號里是陣列元素的索引值
所有的陣列都提供了一個length屬性,通過這個屬性可以訪問到陣列的長度,一旦獲得了陣列的長度,就可以通過回圈來遍歷該陣列的每個陣列元素,
package com.ch04;
public class ArrayTest {
public static void main(String[] args) {
// 定義(宣告)陣列
int[] array1;
int[] array2;
// 靜態初始化
array1 = new int[]{1, 3, 5, 7, 9};
// 動態初始化
array2 = new int[5];
// 輸出陣列array1中的最后一個元素
System.out.println(array1[array1.length-1]); // 9
// 根據陣列的length屬性遍歷陣列array2
for(int i = 0; i < array2.length; i++){
System.out.print(array2[i]); // 00000
}
System.out.println();
// 讓array2指向array1參考的陣列
array2 = array1;
// 再次遍歷陣列array2
for(int i = 0; i < array2.length;i++){
System.out.print(array2[i]); // 13579
}
}
}
從上面的輸出結果也可以看出,使用動態初始化陣列時,系統為int陣列默認的初始化值為0
深入理解Java陣列
陣列參考變數只是一個參考,這個參考變數可以指向任何有效的記憶體,只有當該參考指向有效記憶體后,才可通過該陣列變數來訪問陣列元素,

結合上方代碼分析!
package com.ch04;
class Person{
public int age;
public double height;
// 定義一個info()方法
public void info(){
System.out.println("My age is " + age + ", and my height is " + height);
}
}
public class ArrayTest1 {
public static void main(String[] args){
// 定義(宣告)陣列,其型別是Person
Person[] P;
// 動態初始化
P = new Person[2];
// 創建person1物件
Person person1 = new Person();
person1.age = 20;
person1.height = 188.5;
// 創建person2物件
Person person2 = new Person();
person2.age = 22;
person2.height = 166.5;
// 將person1賦給第一個陣列元素,person2賦給第二個陣列元素
P[0] = person1;
P[1] = person2;
// 輸出結果一樣,因為P[1]和person2指向同一個Person實體
person2.info(); // My age is 22, and my height is 166.5
P[1].info(); // My age is 22, and my height is 166.5
}
}
可以看到輸出結果相同,(結合下圖分析)因為P[1]和person2指向記憶體的同一片區域,因此通過這兩種方式訪問得到的結果是相同的

操作陣列的工具類:Arrays
Java提供的Arrays類里包含的一些static修飾的方法可以直接操作陣列,這個Arrays類里包含了如下幾個static修飾的方法(static修飾的方法可以直接通過類名呼叫),
int binarySearch(type[] a, type key):使用二分法查詢key元素值在a陣列中出現的索引;如果a陣列不包含key元素值,則回傳負數,呼叫該方法時要求陣列中元素已經按升序排列,這樣才能得到正確結果,int binarySearch(type[] a, int fromIndex, int toIndex,type key):這個方法與前一個方法類似,但它只搜索a陣列中fromIndex到toIndex索引的元素,呼叫該方法時要求陣列中元素已經按升序排列,這樣才能得到正確結果,type[] copyOf(type[] original, int length):這個方法將會把original陣列復制成一個新陣列,其中length是新陣列的長度,如果length小于original陣列的長度,則新陣列就是原陣列的前面length個元素;如果length大于original陣列的長度,則新陣列的前面元素就是原陣列的所有元素,后面補充0(數值型別)、false(布爾型別)或者null(參考型別),type[] copyOfRange(type[] original, int from, int to):這個方法與前面方法相似,但這個方法只復制original陣列的from索引到to索引的元素,boolean equals(type[] a, type[] a2):如果a陣列和a2陣列的長度相等,而且a陣列和a2陣列的陣列元素也一一相同,該方法將回傳true,void fill(type[] a, type val):該方法將會把a陣列的所有元素都賦值為val,void fill(type[] a, int fromIndex, int toIndex, type val):該方法與前一個方法的作用相同,區別只是該方法僅僅將a陣列的fromIndex到toIndex索引的陣列元素賦值為val,void sort(type[] a):該方法對a陣列的陣列元素進行排序,void sort(type[] a, int fromIndex, int toIndex):該方法與前一個方法相似,區別是該方法僅僅對fromIndex到toIndex索引的元素進行排序,String toString(type[] a):該方法將一個陣列轉換成一個字串,該方法按順序把多個陣列元素連綴在一起,多個陣列元素使用英文逗號(,)和空格隔開,
Java 8增強了Arrays類的功能,為Arrays類增加了一些工具方法,這些工具方法可以充分利用多CPU并行的能力來提高設值、排序的性能,下面是Java 8為Arrays類增加的工具方法,
void parallelPrefix(xxx[] array, XxxBinaryOperator op):該方法使用op引數指定的計算公式計算得到的結果作為新的陣列元素,op計算公式包括left、right兩個形參,其中left代表新陣列中前一個索引處的元素,right代表array陣列中當前索引處的元素,新陣列的第一個元素無須計算,直接等于array陣列的第一個元素,void parallelPrefix(xxx[] array, int fromIndex, int toIndex, XxxBinaryOperator op):該方法與上一個方法相 似,區別是該方法僅重新計算fromIndex到toIndex索引的元素,void setAll(xxx[] array, IntToXxxFunction generator): 該方法使用指定的生成器(generator)為所有陣列元素設定值,該生成器控制陣列元素的值的生成算void parallelSetAll(xxx[] array, IntToXxxFunction generator):該方法的功能與上一個方法相同,只是該方法增加了并行能力,可以利用多CPU并行來提高性能,void parallelSort(xxx[] a):該方法的功能與Arrays類以前 就有的sort()方法相似,只是該方法增加了并行能力,可以利用多CPU并行來提高性能,void parallelSort(xxx[] a, int fromIndex, int toIndex):該方法與上一個方法相似,區別是該方法僅對fromIndex到toIndex索引的元素進行排序Spliterator.OfXxx spliterator(xxx[] array):將該陣列的所有元素轉換成對應的Spliterator物件,Spliterator.OfXxx spliterator(xxx[] array, int startInclusive, int endExclusive):該方法與上一個方法相 似,區別是該方法僅轉換startInclusive到endExclusive索引的元素,XxxStream stream(xxx[] array):該方法將陣列轉換為Stream,Stream是Java 8新增的流式編程的API,XxxStream stream(xxx[] array, int startInclusive, int endExclusive):該方法與上一個方法相似,區別是該方法僅將fromIndex到toIndex索引的元素轉換為Stream,
上面方法串列中,所有以parallel開頭的方法都表示該方法可利用CPU并行的能力來提高性能,上面方法中的xxx代表不同的資料型別,比如處理int[]型陣列時應將xxx換成int,處理long[]型陣列時應將xxx換成long,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/451992.html
標籤:其他
上一篇:背包問題(1):基本模型和解法
