Java語法簡介
25 April 2020
Java Introduction
編譯過程
Java為兩階段編譯
- 先將java code轉成byte code
- JVM(Java virtual machine)將byte code batch形式轉成Machine code在JVM裡執行
source code -> byte code(object code)
優點
- JVM好處在於相容性高,在不同電腦不用擔心因為版本、不同CPU等等問題導致Java code不相容不能執行。
- 只要把byte code給對方,對方也不用重新編譯
- JVM隔離執行環境,相較直接在本機執行安全,不用擔心把程式把資源吃光
hello world
public class <filename>{
public void static main(String[] args){
....
}
public <filename>(...){...} // constructor
}
編譯指令
編譯檔案成bytecode
$ javac test.java
產生一個test.class,此為bytecode
注意java code內的class名稱要跟檔案名稱相同
執行
class loader把需要的class load進程式 其實是interpreter把bytecode改成Machine code跑
$java test
不用寫test.class
Reference
基本語法
Datatype
boolean | 1 byte |
---|---|
char | single char 2 byte(unicode) |
byte | 1 byte, -128~127 |
short | 2 byte, -32768~32767 |
int | 4 byte, -2147483648~2147483647 |
long | 8 byte |
float | 4 byte |
double | 8 byte |
byte->short->int->long->float->double 左邊的值可以assign給箭頭右邊,反向,右邊值assign給左邊要做casting
final
= constant
運算
- 運算時,Data自動轉成bytes數最大的data type,但最小是int,也就是說如果整個算式最大的是byte,short,會自動轉成int
- int/int 出來結果是整數去掉小數部分
- ++在變數後是最在整個運算完後處理,++在變數前是在整個運算前處理, 令n = 2
- 2*(n++) = 4, n = 3
- 2*(++n) = 6, n = 3
((result = (++n)) + (other = (2*(++n))))
If n = 2, result = 3 other = 8, output = 11
題外話
- 關於a = a++的討論 解答
- public static final int a; 宣告一個constant a,宣告在全域,這個a是不能改的(有final)
String class
string這個class是沒有辦法修改的!!!(沒有method修改)
要修改的話要用StringBuffer這個class。
在Java output將data轉成string
所以會有以下情況
System.out.println(“100”+42 ) -> 10042
System.out.println(100+42) -> 142
method
"hello".length() -> 5
不會有\0
$ a.equals("hello")
return [true,false]
$ a.equalsIgnoreCase("hellO")
忽略大小寫
$ a.toLowerCase, a.toUpperCase()
$ a.trim()
去除空格、tab、換行
$ a.charAt('h')
同strchr
$ a.substring(st,[ed])
回傳st-ed的substring
沒ed的話回傳st位置開始到最後的字串,
$ a.indexOf(substring,[st],[ed])
回傳從st開始到ed為止,符合substring的位置,沒有符合的回傳-1
st,ed可有可無
$ a.compareTo
同strcmp,a大的話回傳+,a小的話回傳-
IO
System.out : Object
System.out.println : 等於C的puts
System.out.print : 沒換行
System.out.printf : 同C printf
package & class
java.text.NumberFormat
- java.text為package,內含很多class
- NumberFormat是這個package裡的一個class
- 兩種情況不用import
- java.lang下不用
- class在同目錄檔案裡
$ import java.text.* import java.text這個package內的所有class
import整個package跟import很少class沒有效率上的差別
EX : DecimalFormat,用於格式化數字
同System.out.printf的格式化
import java.text.DecimalFormat
DecimalFormat ob = new DecimalFormat("000.000") => 輸出的東西都符合這個type
ob.format("12.34") -> 012.340
小數點後數字超過format數量會4捨五入
小數點錢超過會error,就不format
0 -> digit # -> optional digit(可有可無)
Input
可以選擇用BufferReader 或 Scanner
Scanner感覺比較常用,因為她有做casting的部分(就是可以直接向scanf讀入int而不限定只能讀入char,byte)
import java.util
Scanner keyboard = new Scanner(System.in);
int a = keyboard.nextInt();
keyboard.nextDouble()...
keyboard.next() : 讀一個string,非空格、換行字元
keyboard.nextline() : 一次讀一個line,讀到\n,但不包括\n
注意 !!! readint後注意nextline來換行
Scanner keyboard = new Scanner(System.in)
int n = keyboard.nextInt();
String s1 = keyboard.nextLine();
String s2 = keyboard.nextLine();
input :
2
heads are better than
1 head
原本希望 n = 2, s1 = heads are better than, s2 = 1 head
但是nextInt沒有讀到end of line,導致s1 = 空白,s2 = heads are better than
所以nextInt後,要先一次nextLine去掉讀掉那行的end of line
keyboard.useDelimeter(“設定delimeter”)
讀擋
import java.io.FileInputStream;
import java.io.FileNotFoundException;
Scanner fileIn = null;
try{
fileIn = new Scanner(new FileInputStream("filepath"))
}
catch(FileNotFoundException e){
System.exit(0);
}
File.hasNextLine(); 檢查是不是end of file
File.next.... 同input IO讀
File.close()
Debug
- 開發小的程式後就馬上測試
- code review
- assert
- 一般情況,assertion是turn off的,跑的時候要打指令 java -enableassertions test才能跑有assertion的code
- assert boolean,若後面為false,會噴error,程式停止
Psuedorandom
並非完全random,用一個seed跑出其他random值
import java.util.Random
Random test = new Random();
test.nextInt([n]); :跑出0-n之間的隨機數
test.nextDouble(); 跑出一個0-1的double
Math.random()輸出0~1的double值,原理基本上就是利用Random Object的nextDouble
int num = (int)(Math.random()*6)+1;
input處理
- Scanner讀進
- Stringtokenizer split string
- Wrapper class把string轉成特定型態
package
EX : java.lang, java.util這種為package,package內可以有很多class
import整個package跟import一個class沒有效能上的差距
import Package_Name.Class
import Package_Name.*
- java.lang是基本的package,不用特別import
寫Package
把所有寫的class檔放在同個資料夾內,每個class檔開頭加上
package <Package_Name>;
創好後要加入CLASSPATH來定義java package的path
$ set CLASSPATH = ...;...
export CLASSPATH
import自己寫的package
- 要知道package name
- 要知道Package path,以CLASSPATH這個env參數為base path
$ CLASSPATH = /usr/jimmy/ $ package directory = /usr/jimmy/Desktop/pacckage/ $ import= import Desktop.pacckage.*
CLASSPATH設定
java import package會看CLASSPATh裡面的路徑,因此如果希望先看current directory的話,classpath第一個設定現在目錄,如果沒設定current directory就不會找目前資料夾下的class
沒設定classpath default為 . 設定的話會覆寫
CLASSPATH = .;/usr/jimmy/Desktop....
javac -classpath .;... test.class
注意
假設有兩個package,其中一個在另一個的子目錄裡,那import母目錄的package不會順便import子目錄裡的class,所以一個import package只會import一個package,這個package裡面的package不會被import
兩package
Desktop/A
Desktop/A/B
import Desktop.A.* 不會import B package
另外設定classpath參數記得設定current directory!!!
default package
current directory裡的class都屬於default package,因此在同一個目錄下的class,不用特別去import他就可以使用
Name clash
假設有兩個class名字依樣但在不同package,在使用它時就要include package name避免ambiguity
packageA.test = new packageA.test()
packageB.test = new packageB.test();
Javadoc
java API的說明、文件,做好encapsulation,分開API跟實作的文件。 class是實做的檔案,API文件就是說明的文件。
$ javadoc -d <Document_directory> Package_Name
Reference
String format
Javadoc
String operation
Java tutorial chinese
Java FileIO