Start a Java
Simple code
已下依照執行順序介紹
- Write a Demo Class
- Compiler
- 執行Java
[Write a Demo Class]
/* 檔名: Demo.java*/
public class Demo{
/* Block */
public static void main(String[] args){
System.out.print('java start');
}
}
透過這簡單的範例來說明:
定義類別:
撰寫 Java 程式的第一步都是從定義類別(class)開始
一個類別是一個 Java 程式的基本單位
定義類別時使用 class 關鍵字,後面跟隨著一個類別名稱class ClassName
。
關鍵字指的是程式語言中已經使用的一些單字
當您為類別或程式中的一些元素取名時,不可以使用到這些關鍵字。
例如 class 關鍵字用來表示定義一個類別
鍵字 public
在類別名稱定義前加上一個 public 鍵字,表示所定義的類別是公開的類別,
公開的類別有兩種意義:
- 表示檔案名稱在命名時,主檔名必須與類別名稱同名
上述範例檔名必須為
Demo.java
一個Java 原始檔案中可以定義數個類別,但是只能有一個公開的類別。
也就是一隻java內可以有很多class,但只有一個可以是public
- 表示權限的管理
一個類別被定義為公開的類別,則表示其它的 Java 程式都可以使用這個類別
如果沒有定義類別為公開,則類別只能被同一個套件( package )管理下的其它 Java 程式所使用。
Scope
類別的定義範圍( Scope )由大括號 {}
包括
在括號之間稱為一個區塊( Block ),在區塊之間的定義都屬於同一個類別。
定義主流程
Java 程式的執行起點( Entry point )是從 main 方法(Method)開始,也就是執行這隻java會從main()開始執行
main 的寫法必須是:
public static void main(String[] args)
有三個關鍵字來修飾 main 方法。
- public : 因為一個公開的方法才可以被 Java 虛擬機器執行;
- static : Java 虛擬機器才可以直接呼叫 main 方法,而不用為該類別產生實例;
- void : 表示方法執行完畢不傳回任何值。
String[] args :
- 括號內定義了參數列( Parameter list ),
- 參數列中的參數可以儲存引數( Argument ),在呼叫方法時可以一併給方法一些執行過程中所必要的資訊
簡單來說上方範例:
括號中的 args 來儲存啟動程式時,使用者一併給程式的命令列引數( Command line argument ),目前雖然還沒必要使用命令列引數,但是規定仍要撰寫
細節請參考: http://docs.oracle.com/javase/tutorial/getStarted/application/
[Compiler Java]
javac Demo.java
執行 javac 工具程式並指定要編譯的*.java
檔案,
如果指定的 Java 原始碼檔案沒有任何的錯誤,則編譯完成後不會有任何錯誤訊息出現,在workspace 下應該會出現一個 *.class
檔案。
compiler後的檔案是位元碼( byte-code )格式,在執行 Java 程式時,會被 Java 虛擬機器轉換為目標平台所認識的原生碼( Native code )。
利用-verbose
觀察compiler流程
javac -verbose Demo.java
在執行javac 指令的時候,同時使用-verbose 選項,則執行編譯時的每一個步驟都會被顯示出來
流程如下:
- 語法檢查:編譯器首先會剖析
*.java
原始檔案,進行一些基本的語法檢查, - 搜尋原始碼路徑(java):查看有無指定的相關類別之原始碼
可使用
-sourcepath
選項設定原始碼路徑 - 搜尋類別路徑(class):查看有無指定且已編譯完成的類別檔案
可使用-classpath 選項設定類別路徑
- 類別載入:載入相關類別(例如 System、String 類別)以獲取類別資訊
- 寫入class檔案 : 編譯完成後將編譯結果寫至
*.class
檔案。
路徑
- workspace/src : 原始碼路徑(
*.java
)-sourcepath
- workspace/classes : 類別路徑(
*.class
)-classpath
[執行JAVA]
java Demo
在classes內會有一隻檔案Demo.class,如此才能正確執行
Java 程式是執行於 Java 虛擬機器(JVM)
,
簡單的說, Path 變數之於作業系統的作用 ,就相當於Classpath 變數對於 JVM 的作用。
在這個小節中,您將會學習到:
-classpath 與-sourcepath 選項的作用 如何設定 Classpath 環境變數 如何在系統變數中加入 Classpath 變數
JAVA使用JDK的JRE or 公用JRE執行?
與環境變數Path有關
執行 java 時,作業系統會依 Path 變數中設定的路徑順序來找尋目標程式
用JDK的JRE執行 : 將 JDK 的 bin 資料夾之路徑設定於 Path 變數
如何處理
[變數宣告]
type identifier = [value];
- type : 指Data type(資料型態)
byte、short、int、long char float、double boolean
- identifier :變數名稱
變數的名稱必須能表示出該變數的作用,例如用 ageOfStudent 這樣的名稱來表示
- = : 指定運算子( Assignment operator ),用來將右邊的 value 指定給左邊的變數來儲存。
- value : 值
int ageOfStudent = 18;
char sexOfStudent = 'M';
final
想要指定一個值給變數,之後不再改變它的內容,目的是為了方便使用名稱來取用某個數值
使用 final 關鍵字
使用 final 宣告的變數,通常變數名稱會以全部大寫來表示,這可以提醒程式設計人員所使用的變數可能是使用 final 宣告的變數。
final double PI = 3.14159;
PI = 3.14; // 試圖改變 final 所宣告的變值之值
//出現ERROR Message: cannot assign a value to final variable
陣列
type[] array_identifier;
type[] array_identifier;
type[] array_identifier = {,分隔的值或運算式} ;
array_identifier = new type[value];
//二維
type[][] array_identifier;
array_identifier = new type[number_of_arrays][length];
type[][] array_identifier = {{,分隔的值或運算式},{,分隔的值或運算式}};
- type
表示儲存在陣列中的值為基本資料型態或是物件型態。
- []
用來告知編譯器,您所宣告的是一維陣列參考。
- array_identifier
是您指派給陣列的名稱。
宣告:
char[] status;
int[] ages;
Integer[] scores;
實例化:
int[] ages = {19, 42, 92, 33, 46};
char[] name = {'J', 'a', 'v', 'a'};
Integer[] scores = {new Integer(1),new Integer(2), new Integer(3)};
status = new char[20];
ages = new int[5];
scores = new Integer[5];
//陣列5x4
int[][] yearlySales = new int[5][4]; //box
Integer[][] yearlySales = new Integer[5][4]; //object
int[][] yearlySales = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11}
};
[註解] Comment
- 單行註解( Single-line comment ) :
//
- 傳統註解/多行註解( Traditional comment ) :
/* */
稱之為傳統註解是因為這個註解方式是從 C 語言開始就有的,Java 也採用同樣的註解方式,因為這種註解可以多行
- 文件註解( Document comment ) :
/** */
藉由 JDK 內附的工具javadoc 來產生文件。
事實上,在 Java Standard Edition SDK 上所有的類別函式庫說明文件都是由 javadoc 工具所產生。
文件註解( Document comment )
javadoc -d 文檔存放目錄 -author -version 源文件名.java
//-author 和 -version 兩上選項可以省略。
HTML 格式 : 需要在註解內加上去
生成的文檔是 HTML 格式,
HTML 格式的標識符是在寫注釋的時候寫上去的。
因此,格式化文檔,就是在文檔注釋中添加相應的 HTML 標識。
輸出方式 :
讀取每一行后,刪掉前導的 號及 號以前的空格,再輸入到文檔的
前導的 號允許連續使用多個,其效果和使用一個 號一樣,但多個 號前不能有其它字符分隔,否則分隔符及后面的 號都將作為文檔的內容。
* 文字
這個做為左邊界使用
/**
* This is first line. <br>
***** This is second line. <br>
This is third line.
*/
編譯輸出后的 HTML 源碼則是:
This is first line. <br>
This is second line. <br>
This is third line.
還有一點需要說明,文檔注釋只說明緊接其后的類、屬性或者方法。如下例:
/** comment for class */
public class Test {
/** comment for a attribute */
int number;
/** comment for a method */
public void myMethod() { ...... }
文檔注釋的三部分 :
/**
* show 方法的簡述.
* <p>show 方法的詳細說明第一行<br>
* show 方法的詳細說明第二行
* @param b true 表示顯示,false 表示隱藏
* @return 沒有返回值
*/
public void show(boolean b) {
frame.show(b);
}
標記 | 用于 | 作用 |
---|---|---|
@author | 對類的說明 | 標明開發該類模塊的作者 |
@version | 對類的說明 | 標明該類模塊的版本 |
@see | 對類、屬性、方法的說明 | 參考轉向,也就是相關主題 |
@param | 對方法的說明 | 對方法中某參數的說明 |
@return | 對方法的說明 | 對方法返回值的說明 |
@exception | 對方法的說明 | 對方法可能拋出的異常進行說明 |
[輸出文字]
System.out.print("輸出文字");
System.out.println(); // 換行
表示:請使用 System 的 out 上之 println()方法,顯示您所指定的文字。
- System 類別
- Java SE的類別
- 內有許多member
- out 成員( Member )
- 負責標準輸出( Standard output )
- 只要將所要輸出的文字以雙引號"包括 (單引號會出錯!)
- 使用 out 上的 println()方法
- 可將文字顯示在螢幕上
response.getWriter().write("hihihi");
response.getWriter().append("hihihi");
[取得輸入資料]
java.util.Scanner
DK 5.0 新增, 是 Java SE 中的標準類別
java.util.Scanner scanner = new java.util.Scanner(System.in);
建立 Scanner 實例時,必須給它一個 System.in 作為參數,這是因為實際取得輸入的工作,仍是 System.in 在進行的
建立 Scanner 實例之後,您可以使用各種 nextXXX()方法(Method)取得各種型態的資料
import java.util.*;
public class ScannerDemo{
public static void main(String[] args){
java.util.Scanner scanner = new
java.util.Scanner(System.in);
System.out.print("輸入整數:");
int input1 = scanner.nextInt();
System.out.print("輸入浮點數:");
double input2 = scanner.nextDouble();
System.out.print("輸入布林數:");
boolean input3 = scanner.nextBoolean();
System.out.println("整數輸入:" + input1);
System.out.println("浮點數輸入:" + input2);
System.out.println("布林數輸入:" + input3);
}
}
//這塊不太懂...
[邏輯判斷]
if/else
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int i = 1;
boolean check = true;
System.out.println(check);
if(check){
System.out.println("check is true");
}
System.out.println(check);
if(check){
System.out.println("check is true");
}else{
System.out.println("check is false");
}
System.out.println(check);
if(check)
System.out.println("check is true");
System.out.println(check);
check = (check == true) ? false : true;
System.out.println("check is "+check);
}
}
/*
true
check is true
true
check is true
true
check is true
true
check is false
*/
switch
int level = 9;
switch (level){
case 10:
case 9:
System.out.println("得 A");
break;
case 8:
System.out.println("得 B");
break;
case 7:
System.out.println("得 C");
break;
case 6:
System.out.println("得 D");
break;
default:
System.out.println("得 E(不及格)");
}
while
int input = 3;
int count = 0; // 計數用
while (count < input){ // 判斷次數
System.out.println("Hello!World!");
count++; // 每次執行後遞增
}
do while
int input = 3;
int count = 0; // 計數用
do{
System.out.print("count="+count);
count++; // 每次執行後遞增
System.out.println(" => count="+count);
} while (count < input);
/*
count=0 => count=1
count=1 => count=2
count=2 => count=3
*/
先執行,符合while內條件的繼續執行do內的事件
step 1 : do
step 2 : while = true
step 3 : do (loop)
step 4 : while = true
step 5 : do
step 6 : while = false
step 7 end of while
for
for (initialize[,initialize]; boolean_expression; update[,update]) {
code_block;
}
- initialize: 初始化迴圈內變數
- 只會一開始執行一次
- 多個變數則用逗號分隔
- boolean_expression : 判斷,為true時執行code_block
- update : 變數的更新(增加或減少)。
- code_block執行完之後才處理
- 有多個變數則用逗號分隔。
for(int i = 5,j=0; i > 0; i--,j++){
System.out.println("i="+i+",j="+j);
}
/*
i=5,j=0
i=4,j=1
i=3,j=2
i=2,j=3
i=1,j=4
*/
步驟如下
step 1. 初始化變數i,j
step 2. 判斷 i > 0
step 3. 執行println
step 4. 執行 i-- 與 j++
step 5. 判斷 i > 0 (loop)
step 6. 執行println
step 7. 執行 i-- 與 j++
...
foreach in JAVA
simple foreach
int[] numbers = {2,3,4,5,6};
for (int num : numbers) {
System.out.println(num);
}
/*
2
3
4
5
6
*/
foreach get key value
HashMap map = new HashMap();
map.put("A", "111");
map.put("B", "222");
map.put("C", "333");
map.put("D", "444");
map.put("E", "555");
for (Object key : map.keySet()) {
System.out.println(key + " : " + map.get(key));
}
/*
A : 111
B : 222
C : 333
D : 444
E : 555
*/
二維陣列foreach
int[][] yearlySales = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11}
};
for (int[] row : yearlySales){
for (int element : row){
System.out.print(element + " ");
}
System.out.println();
}
迴圈效能比較
- while
當重複的次數不確定並且必須先測試迴圈條件時,就使用 while 迴圈。
- do while
當重複的次數不確定並且必須先執行某個動作後測試迴圈條件,就使用 do while 迴圈。
- for
for 迴圈比 while 迴圈更簡潔及容易閱讀,原因是因為它被設計成以分開的數字來計數。因此使用 for 迴圈能夠以預先定義的執行次數來一步一步達成我們賦予它們的工作。
break & continue
在迴圈執行的本體中,如果打算離開迴圈的執行流程,您可以使用 break 或 continue 來進行控制
- break
- 可以離開目前正在執行的 while、do while、for 迴圈區塊
break [labelname];
可以跳脫整個迴圈
- continue : 主要使用於 for 迴圈
continue [labelname];
可以跳到label
label
用label為迴圈命名。
label代表的是迴圈的標示記號,撰寫JAVE程式的時候可以利用label指向相對應的迴圈
定義標示名稱有以下2種方式:
label_name: for(){}
後面一定只能放for
label_name:{for(){}}
mylabel:
for(initialize;boolean_expression; update){
}
mylabel:{
//code
for(initialize;boolean_expression; update){
}
}
範例:
int[] numbers = {2,3,4,5,6};
mylabel:
for (int num : numbers) {
System.out.println(num);
if(num==4){
System.out.println("break mylabel");
break mylabel;
}
}
System.out.println("for end");
mylabel:{
HashMap map = new HashMap();
map.put("A", "111");
map.put("B", "222");
map.put("C", "333");
for (Object key : map.keySet()) {
System.out.println(key + " : " + map.get(key));
if(key=="B"){
System.out.println("break mylabel");
break mylabel;
}
}
System.out.println("for end");
} //lanel end
/*
2
3
4
break mylabel
for end
A : 111
B : 222
break mylabel
*/
[是否相等]
當關係運算子"=="
使用於兩個參考名稱之比較時,它比較的是兩個參考名稱是否參考至同一個物件
要比較兩個物件的相等性時,您要使用 equals()方法。不可以使用關係運算子"=="來比較兩個物件是否相等
equals
equals()方法被用來定義兩個物件的相等性,
對於 Integer型態的物件來說,equals()方法定義其內含值(即一開始建立 Integer 物件時所給定的值)是否相同。
Integer iRef1 = 100;
Integer iRef2 = 100;
Integer iRef3 = 200;
Integer iRef4 = 200;
Integer iRef5 = new Integer(100);
Integer iRef6 = new Integer(100);
if (iRef1 == iRef2)
System.out.println("iRef1 == iRef2");
else
System.out.println("iRef1 != iRef2");
if (iRef3 == iRef4)
System.out.println("iRef3 == iRef4");
else
System.out.println("iRef3 != iRef4");
if (iRef3.equals(iRef4))
System.out.println("iRef3 == iRef4");
else
System.out.println("iRef3 != iRef4");
if (iRef5 == iRef6)
System.out.println("iRef5 == iRef6");
else
System.out.println("iRef5 != iRef6");
//iRef1 == iRef2
//iRef3 != iRef4
//iRef3 == iRef4
//iRef5 != iRef6
套件
[package]
使用 package 關鍵字來定義套件以管理類別,
將套件的觀念想像成類似檔案系統資料夾管理的觀念,您可以根據套件的階層很快的找到所需的類別,在不同套件下的類別,即使名稱相同也無所謂,它們是不同的類別。
使用了 package 將 HelloWorld 類別歸類於 com.oracle 套件來加以管理,這麼一來完整的類別名稱將是 com.oracle.HelloWorld
package com.oracle;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello! World!");
}
}
套件被設計為與檔案系統相對應,所以在編譯過後,HelloWorld.class 必須放置於 com 資料夾的 oracle 資料下
每次編譯完類別之後,都還要自行將.class 移動至對應的資料夾下並不方便,您可以在編譯時加入-d 選項,並指定編譯後.class 的目標資料夾,則編譯器就會在指定的資料夾下依套件設定,自動建立與套件管理對應的資料夾,例如您可以這麼下指令:
javac -d . HelloWorld.java
編譯後執行
java com.oracle.HelloWorld
[import ]
如果要使用package
public class HelloWorldDemo {
public static void main(String[] args) {
com.oracle.HelloWorld student =
new com.oracle.HelloWorld(123456, "Duke");
}
}
也可以這樣
import com.oracle.HelloWorld;
public class HelloWorldDemo {
public static void main(String[] args) {
HelloWorld student =
new HelloWorld(123456, "Duke");
}
}
[import static]
import static 語法是 JDK 5.0 所新增的語法,在作用上與 import 類似,import static 可以於程式一開始指定靜態成員的完整名稱,之後在撰寫靜態成員時,可以省略靜態成員之前的套件名與類別名稱等。
import static java.lang.System.out;
public class HelloJava {
public static void main() {
out.println("Hello!Java!");
}
}
參考
CodeData - Java 學習之路
JavaDoc,在Java的注釋上做文章