Java語法簡介

25 April 2020

Java Introduction

編譯過程

Java為兩階段編譯

  1. 先將java code轉成byte code
  2. JVM(Java virtual machine)將byte code batch形式轉成Machine code在JVM裡執行

source code -> byte code(object code)

優點

  1. JVM好處在於相容性高,在不同電腦不用擔心因為版本、不同CPU等等問題導致Java code不相容不能執行。
  2. 只要把byte code給對方,對方也不用重新編譯
  3. 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

java jdk path

基本語法

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

運算

  1. 運算時,Data自動轉成bytes數最大的data type,但最小是int,也就是說如果整個算式最大的是byte,short,會自動轉成int
  2. int/int 出來結果是整數去掉小數部分
  3. ++在變數後是最在整個運算完後處理,++在變數前是在整個運算前處理, 令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

題外話

  1. 關於a = a++的討論 解答
  2. 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

可以選擇用BufferReaderScanner
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

  1. 開發小的程式後就馬上測試
  2. code review
  3. 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處理

  1. Scanner讀進
  2. Stringtokenizer split string
  3. 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

  1. 要知道package name
  2. 要知道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