網頁

2015年6月11日 星期四

[轉載]用於JAVA基礎安裝及配置

Java: A simple, object-oriented, network-savvy, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, dynamic language.

在Sun Microsystems的 Java語言白皮書裡提到, Java語言有以下特點
  • 簡單(Simple):指的是去除了C/C++中較少使用或可能不安全的功能,例如指標,運算子重載,多重繼承等。
  • 物件導向的(Object-oriented):利用OOP的三種基本特性:PIE(多型,繼承,封裝),來設計出可重複使用的元件,使系統有彈性易於維護。
  • 網路的(Network-Savvy):提供容易使用的API來撰寫網路程式
  • 直譯式的(Interpreted):bytecode在JVM上執行時,JIT負責轉換為機器碼。
  • 穩健的(Robust):捨棄了對記憶體的指標運作。
  • 安全性(Secure) : 資源回收處理 (Garbage Collection)由JVM自行作記憶體管理,例外處理 (Exception) 可預防突發錯誤的產生。
  • 結構中立(Architecture Neutral):程式執行在虛擬機器上。
  • 可攜的(Portable): Write once, run anywhere指的是由JVM與不同的作業系統溝通。
  • 高效率的(High Performance):利用HotSpot, JIT技術改善效能。
  • 多執行緒的(Multithreaded):Java程序可發出多隻並行的輕量化行程。
  • 動態的(Dynamic):Java程式執行時動態的連結類別庫。
應該還可加入以下特點
  • Unicode :可支援萬國碼,變數與類別名稱皆可使用中文

JAVA的版本

  • 版本代號與發行日期可參考 http://zh.wikipedia.org/wiki/Java
  • Java從JDK 1.5的版本之後,改名為Java 5。Java的各種版本已經更名以取消其中的數字「2」:J2EE更名為Java EE, J2SE更名為Java SE,J2ME更名為Java ME。新增加的功能請參考:http://www.sitepoint.com/print/introducing-java-5
  • Java自第二版(1.2)開始分為三個版本,類別函式庫名稱也由 JDK(Java Development Kit) 改 Java 2 SDK(Software Development Kit)
    • J2EE(Enterprise Edition)
    • J2SE(Standard Edition)
    • J2ME(Micro Edition)

下載與安裝

jdk的安裝說明

Java Development Kit 5.0 官方安裝說明,若需要step by step的版本請參考:Java Programming程式發展環境建置指南
  • 下載的Java套件中內含 JDK與JRE,JDK部分請安裝在 d:\jdk 目錄, JRE部分照預設安裝即可
  • 以下以 Java 1.5 來解釋安裝的項目 安裝完畢預設會產生以下目錄
    • d:\jdk //JDK位置
      • bin(開發工具)
        • 編譯器(Java Compiler, javac)─將 Java 原始檔(*.java)編譯為 位元檔(*.class)
        • 直譯器(Java Interpreter, java)─執行 Java 程式(*.java)
        • 反組譯器(Javap)─可對.class進行反組譯
        • 檢視器(Java AppletViewer, appletviewer)─用來執行與測試 Java 小程式(applet)
        • 除錯器(Java Debugger, jdb)─幫助發現程式的bugs
        • 文件器(Java Documentation Generator, javadoc)─由 java 原始檔中製作可由導覽器瀏覽之文件說明檔
        • 壓縮器(Java Archive Tool, jar)─將多個java程式檔(*.class) 壓縮為 ZIP 格式的檔案 (*.jar) //用法與tar相同
      • demo //範例程式
      • include //C語言的標頭檔
      • jre((Java Runtime Interpreter) //開發時期的JRE
      • lib(java other source jar) //工具程式會使用的類別函式庫
    • C:\Program Files\Java\j2re1.4.2_05 //執行時期的JRE位置
  • 設定環境變數
    • 從我的電腦-->系統內容-->進階-->環境變數
    • 在環境變數中新增 JAVA_HOME 變數值為 d:\jdk //為了讓Tomcat能找到java
    • 編輯原本的 Path , 在後面加上 ;%JAVA_HOME%\bin //讓電腦可以編譯執行java)
    • 新增 classpath 變數值為 .; //以後可再視情況修改(d:\jdk\lib\rt.jar;d:\jdk\lib\tools.jar;)對jdk1.3以上的版本,引用java.*,sun.*等系統class不需要設置classpath
  • 測試
    開啟命令列模式輸入 java -version 看看有無顯示版本

Class Path的說明

  • 就如同 Path 為作業系統指定搜尋路徑一樣, Classpath為Java執行時期環境設定搜尋類別與其它資源的路徑。
  • 每一個 Classpath 都應以檔名或目錄名稱作結束。
  • 設定環境變數可使用 set classpath=e:\peter\proj; //等號兩邊不可有空白
  • 要指定多個class path項目時的順序很重要,Java解碼器(interpreter)會以class path變數中的順序於目錄中尋找classes

JAVA平台架構

J2SE 平台架構圖

J2SE平台架構圖

JAVA程式語言

java語言是高階語言,特別的是它同時有編譯(compiler)與直譯(interpreter)的行為

可應用層面

  • Application
  • Applet, Servlet, JSP
  • J2ME

語言編譯流程

HelloWorld.javaascii的java原始檔
javac HelloWorld.java
編譯(compiler)
HelloWorld.class產生java的bytecode
java HelloWorld
VM(Virtual Machine)可執行在各種平台
  1. class loader
  2. bytecode verifier
  3. 直譯(interpreter)
Hello, World程式執行結果

JAVA平台(Java Platform)

  • JAVA VM(Virtual Machine)
    • 軟體平台
    • HotSpot
    • JIT(Just In-Time)
  • JAVA API(Application Programming Interface)
    • Swing,AWT
    • Sound,Input Methods,Java 2D,Accessibility
    • RMI,JDBC,JNDI,CORBA
    • .....

Java程式架構

Java程式有2大類
  • 應用程式(Application): Java應用程式是可以獨立執行的程式
  • 小程式(X-let)
    • 瀏覽器端執行的小程式(Applet):Java applet是嵌在HTML中的程式
    • 伺服器端執行的小程式(Servlet)

Application的結構

/** 第一支Java程式
只有註解可以放在 package 區之前
*/

//package 宣告區 //可無此宣告區,若未指定package則預設package為目前目錄
package exam.test;
//import 敘述區 //可無此敘述區,預設一定會 import java.lang;
import java.awt.Button; //引入指定的class
import java.util.*; //引入指定的package
//class, interface, enum 定義區
//int x; // 發生編譯錯誤
public class HelloWorld
{
     public static void main( String[] args ) // 程式執行進入點
     {
          System.out.println( "Hello World " ); //因為預設 import 了 java.lang , 所以代表這個 System.out.println 在其之下

          //b = 200; // 發生編譯錯誤
          tmp obj = new tmp();
          obj.i = 6;
          System.out.println( obj.i );
     }
}

class tmp
{
     int i = 5;
}
請以文書編輯器鍵入上方程式區塊內容,並特別注意下列幾點
  • 註解可使用「/*......*/」與「//...............」,如要變成說明文件, 請依循 javadoc 這個工具的規則「/**........*/
  • 必須以 .java 作為副檔名存檔
  • 類別名稱必須與主檔名相同
  • 每個檔案可以有許多的 class, 但只能有一個是 public
  • 若程式中有多個class, 則編譯時亦會產生多個 .class 檔案
  • Java會區分識別字的大小寫
  • 必須以分號作為每一行的結束

命名方式

撰寫程式時常遇到要為類別,函數,變數,常數命名的情況,Java 中的命名必須符合其識別字(Identifier)的規範
  • Identifier可使用 Unicode,因此可以使用中文,但須注意中間不可有空白,開頭不可有數字,不可為關鍵字(Keywords)
  • 建議Class Name首字大寫 ,Variable Name 和 Method Name 請首字小寫
  • 建議名稱若由數個英文字組成,第二個英文字以後首字大寫(camelcase) ,而不要使用匈牙利命名法 (Hungarian Notation)
  • 建議名稱必須有意義

package宣告區

  • 意指程式本身屬於屬於何類套件?
  • 若未指定package則預設package為目前目錄
  • Java中同性質的classes可被組織為packages,它們對應於檔案系統的目錄結構,可觀看JDK目錄中的 src.zip。
  • JDK目錄中的 src.zip ,其 java.awt.Button.java程式碼中的package設定,為 package java.awt。
  • package 名稱就像是我們的姓,而 class 名稱就像是我們的名字 。package 名稱有很多的,就好像是複姓。比如說 java.lang.String,就是複姓 java.lang,名字為 String 的類別;java.io.InputStream 則是複姓 java.io,名字為 InputStream的類別,所以不同的package之中可以有相同的 class 名稱。
  • classpath+程式內的package = 檔案完整路徑
    • 假設在e:\peter\proj\下有 2 個目錄 1.disp  2.sql
    • disp目錄下的.java程式須加入 package disp;
    • sql目錄下的.java程式須加入 package sql; 
      javac e:\peter\proj\disp\demo.java //javac 完整路徑\java檔名
      java disp.demo //java package名稱.java檔名

import敘述區 = 引入何套件

  • Java的 import 與 C 的 include 意義相仿而實質不大相同,java的import只是告知vm要到哪裡尋找套件,並不會佔用記憶體。
  • 若我們想使用java.io這個套件中的FileReader,需在程式中指定為 import java.io.FileReader
  • 若想在程式中引入java.io整個套件 : import java.io.*
  • import 僅能引用該層,下一層必須另行 import ,例如 import java.io.File,只能使用 File ,不能使用位於上層的FileReader
  • 因為 java.lang 這個套件實在是太常用到了,幾乎沒有程式不用它的, 所以不管你有沒有寫 import java.lang;,編譯器都會自動幫你補上
  • java的API中會有相同名稱的class在不同package的情形,例如  java.util 與 java.sql 都有 Date 這個class 這時引入 時若都採取import整個 package 的方式,則編譯會出錯,建議放棄其中之一的 import 敘述,程式碼中直接使用完整路徑取用 class即可。
  • 常用的套件
    • java.lang //預設引用的套件,包括了基本語言特性與處理陣列與字串的函式
    • java.io
    • java.util
    • javax.swing
    • java.awt //JDK1.1提出的GUI
    • java.awt.event //GUI的事件驅動器
    • java.awt.image //GUI的Image

class, interface, enum 區 = 類別宣告

  • class的名稱與檔案名稱必須相同
  • 每個檔案可已有許多的 class 存在, 但只能有一個是 public

Applet的結構

繼承關係

  • Object
    • Componet
      • Container
        • Panel
          • Applet

語法

class類別html語法
import java.awt.*;
import java.applet.*;

public class appletest extends Applet
{
  //元件區 
String s1 = "";
 ButName=this.getParameter("ButtonName"); //接收參數 

 public void init() //可視為建構函數 
 {
  s1=s1+"init()->";
 }
 public void start() //可視為main程式進入點 
 {
  s1=s1+"start()->";
 }
 public void stop()
 {
  s1=s1+"stop()->";
 }
 public void destroy()
 {
  s1=s1+"destroy()->";
 }
 public void paint(Graphics g) //載入時重畫Applet或call repaint() 
 {
   g.drawString("Hello World!", 25, 25);
 }
}
<html>
<head>
</head>
<body>
 <applet code="appletest.class" width=500 height=150>
  <param name = "ButtonName" value = "B1">
  alt="您的瀏覽器不支援Applet"
 </applet>
</body>
</html>
/*
  • Applet程式需用html包起來在瀏覽器或appletviewer執行
  • 所有的Applet程式必須extends Applet
  • 載入時呼叫class的init()與start()
  • 離開時呼叫stop()與destroy()
  • Applet不可作IO的動作
  • 若改用import javax.swing.JApplet (由AWT改用Swing) 則瀏覽器中會出現灰色的區塊代表Applet並未被執行,原因是瀏覽器只支援到JDK1.1.x,因此必須安裝Java Plugin(JRE)
  • 其他瀏覽器若無法執行也要安裝Java Plugin(JRE)
*/

編輯java程式

一般而言編寫java程式可選擇以下三種類型的編輯器
  • 整合式編輯器:如Eclipse, JCreator LE 等。
  • 視覺化編輯器:如Jbuilder, IntelliJ IDEA, Visual Cafe, Workshop, Forte for Java等。
  • 純文字編輯器:如免費軟體的Crimson 與 ConText 與 NotePad 或共享軟體的 UltraEdit 或 EditPlus 等 。
筆者的建議是初學使用純文字的編輯器,其中筆者偏好的是 Crimson ,日後可改用火紅的Eclipse。
以下假設SDK已安裝在d:\jdk,接下來為大家介紹如何設定Crimson與UltraEdit作為編寫java的IDE環境 。

設定Crimson作為編寫java的IDE環境

  • 自訂編譯的功能選單
    • Tools/Configure User Tools......
      • Menu Text欄位中填入 編譯java
      • Command欄位中填入 d:\jdk\bin\javac.exe
      • Argument欄位中填入 $(FileName)
      • Initial dir欄位中填入 $(FileDir)
      • Hot key欄位中直接按下鍵盤的[Ctrl]+[1]
      • 核取 Capture output 與 Save before execute
      • 選取第2個Empty
      • Menu Text欄位中填入 執行java
      • Command欄位中填入 d:\jdk\bin\java.exe
      • Argument欄位中填入 $(FileTitle)
      • Initial dir欄位中填入 $(FileDir)
      • Hot key欄位中直接按下鍵盤的[Ctrl]+[2]
      • 取消 Close on exit 的核取鈕
      • 按下ok
  • 筆者定義好的設定檔 ,放在crimson的tools目錄即可(下載後記得要調整sdk的位置)

設定UltraEdit作為編寫java的IDE環境

  • 設定存檔時的檔案類型
    • Advanced/Configuration/File Types
      • 檔案類型填入 *.java
      • 描述填入 java code
      • 按下insert
  • 自訂編譯的功能選單
    • Advanced/Tool Configuration/
      • 命令列填入 d:\jdk\bin\javac "%f"
      • 功能表填入 編譯java
      • 擷取命令列輸出:核取 Output to List Box 與 Show DOS Box 與 Capture Out
      • 按下insert
      • 命令列填入 d:\jdk\bin\ java %n
      • 工作目錄填入 %p
      • 功能表填入 執行java
      • 取消核取: Save Active File
      • 擷取命令列輸出:核取 Output to List Box 與 Show DOS Box 與 Capture Out
      • 按下insert

Java資料型態

  • Java的資料型態大小不會像C/C++一樣隨著平台不同而不同,它在所有平台上都是一樣的。
  • 由於Java在char的型態部分採用Unicode, 換句話說, 可以用中文取變數名稱。
  • Java的變數可以指向二種資料型態 1.原生資料型態 2.參考資料型態。
  • 參考資料型態(wrapper class)定義在 java.lang 的套件中。
  • 原生資料型態中的整數資料型態(byte, short, int, long)可使用10進位(13), 8進位(015)與16進位(0xd)表示。
  • 原生資料型態中的浮點數資料型態(float, double),預設浮點數為double型態。
  • 原生資料型態除boolean之外彼此間可轉型(自動轉型或強制轉型)。
  • 原生資料型與參考資料型態之間必須利用物件的靜態方法來轉型。
  • 在運算子(operators)為「+= , -=, *= , /=」時會發生不明確(隱含)轉型的情況,原來需強制轉型的資料會變成自動轉型。
  • Primitive Types / simple type範圍wrapper class /refrence type / composition type
    byte (1byte)-128 ~ 127Byte
    short (2bytes)-32768 ~ 32767Short
    int (4bytes)-2147483648 ~ 2147483647Integer
    long (8bytes)-9223372036854775808 ~ 9223372036854775807Long
    float (4bytes)+-3.4028237*10+38 ~ +-1.30239846*10-45Float
    double (8bytes)+-1.76769313486231570*10+308 ~ 4.94065645841246544*10-324Double
    char (2bytes)Unicode charactersCharacter
    boolean (1bytes)true或falseBoolean
      String
  • Java的常數主要藉由修飾子 final 來限定變數的值不能改變
  • 常數
    數值
         整數:final int a=10
         浮點:final double d1=1.23 (預設)
                final float d2=1.23f
    字元:final char var = 'A'
                final char var = '\u0041'
    字串:final String var = "hello"
    布林:final boolean flag = true
  • Primitive Data Types的轉型
    自動轉型強制轉型
    double d;
    d=123;
    d為double型態
    123 為int型態
    小轉大,系統自動轉型
    int a;
    a= (int) 123.123;
    a為int型態
    123.123 為double型態
    大轉小,需強制轉型 ,否則會編譯錯誤
  • Primitive Data Type 與 Wrapper class型態的轉換
    基本資料型態轉包裝類別包裝類別轉基本資料型態
    Integer i = new Integer(10);
    Float f = new Float(10.1);
    利用java.lang的wrapper class,傳入primitive type,傳回對應wrapper class 的實例Integer.valueOf(i);
    Double.valueOf(f);
    利用java.lang的wrapper class,傳入wrapper class 的實例,傳回對應的 primitive type
public class DataType
{
   public static void main(String args[])
   {
     int i; //變數宣告以資料型態開頭,後接變數名稱
     i=3; //等號稱為指定敘述(Assignment Statement),左邊是Lvalue代表變數名稱,右邊是Rvalue代表運算式(Expressions)
     System.out.print("oringinal i is ");
     System.out.println(i);
     i = 4; // 4 在此稱之為Integer Literal
     System.out.printf("i be changed to %d\n\n",i); //Java 1.5起支援printf() 
     final int j = 3;
     System.out.print("oringinal j is ");
     System.out.println(j);
     // j = 4; //對常數指定值會造成編譯錯誤
     System.out.printf("i be changed to %d\n\n",j);

     int a1 = 100;
     long n1 = a1; // 自動轉型成功 小數值轉大數值( int 轉 long )
     long n2 = 100;
     //int a2 = n2; // 自動轉型失敗 大數值轉小數值 ( long 轉 int )
     int a2= (int)n2; // 欲將大數值轉小數值需使用 強制轉型 ( long 轉 int )
     int a3 = (int)123.23; // double 轉 int 
     int a4 = (int)123.23F; // float 轉 int 
     byte a5 = 'A'; // char 轉 byte 

     double d = 123.3;
     //a1 = a1 + d; //自動轉型失敗
     a1 += d; // 採不明確型態轉換成功

/*參考型態轉原生型態*/
     //a2 = "123"; // 自動轉型失敗 (String 轉 int)
     //a2 = (int)"123"; // 強制轉型失敗 (String 轉 int)
     a2 = Integer.parseInt( "123" ); //利用靜態物件的方法
   }
}

String與基本資料型態(int byte...等)之間的轉換

由 基本資料型態轉換成 String

Tip:如何尋找API ? 1.傳入為基本資料型態 2.回傳 String 型態 3.一定是static 4.API的解釋為所需
String 類別中已經提供了將基本資料型態轉換成 String 的靜態(static)方法,有下列幾種
  • String.valueOf(boolean b) : 將 boolean 變數 b 轉換成字串
  • String.valueOf(char c) : 將 char 變數 c 轉換成字串
  • String.valueOf(char[] data) : 將 char 陣列 data 轉換成字串
  • String.valueOf(char[] data, int offset, int count) :
    將 char 陣列 data 中 由 data[offset] 開始取 count 個元素 轉換成字串
  • String.valueOf(double d) : 將 double 變數 d 轉換成字串
  • String.valueOf(float f) : 將 float 變數 f 轉換成字串
  • String.valueOf(int i) : 將 int 變數 i 轉換成字串
  • String.valueOf(long l) : 將 long 變數 l 轉換成字串
  • String.valueOf(Object obj) : 將 obj 物件轉換成 字串, 等於 obj.toString()
double d = 123.35;
String str = String.valueOf(i);

由 String 轉換成 數字的基本資料型態

Tip:如何尋找API ? 1.傳入為 String 型態 2.回傳 基本資料型態 3.一定是static 4.API的解釋為所需
要將 String 轉換成基本資料型態,大多需要使用基本資料型態的包裝類別(wrapper class)的靜態(static)方法,但須注意的是,若轉換失敗時會丟出例外:NumberFormatException
  • Byte.parseByte(String s) : 將 s 轉換成 byte
    • Byte.parseByte(String s, int radix) : 將以 radix 為基底的 s 轉換為 byte
      比如說 Byte.parseByte("11", 16) 會得到 17
  • Double.parseDouble(String s) : 將 s 轉換成 double
  • Double.parseFloat(String s) : 將 s 轉換成 float
  • Integer.parseInt(String s) : 將 s 轉換成 int
  • Long.parseLong(String s) : 將 s 轉換成 long
try
{
     String str = "3000";
     int i = Integer.parseInt(str);
}
catch (NumberFormatException e)
{
     System.out.println(" 轉換整數時失敗!! " + e);
}

字串

字串常數

  1. 為了效率的關係,以string literals所定義相同的 字串常數 都會放入所謂的string pool內作共享記憶體的處理.(同一個實體) , 但由new所產生的string並不會放入string pool內
    String s1 = "java";
    String s2 = "java";
    String s3 = new String("java");
    String s4 = new String("java");
    System.out.println( s1 == s2 ) ;
    System.out.println( s3 == s4 ) ;
  2. 設定字串常數才能在編譯時期作最佳化,若設定變數則需在runtime時期才能決定
  3. string沒有append()方法
  4. toUpperCase()會回傳同一個實體
  • == 比較variables的內容。
    • 對於primitive variables而言就是單純的比較二變數的content。
    • 對於reference variables而言就是比較二變數內存的類別位址,換言之,唯有當兩個參考指向同一物件時,==運算子的結果才為true。
  • equals 另一種比較的做法是equals,equals在類別為wrapper classes時,是比較兩個物件是否為相同類型的類別後再比較其內容值是否相同,是就傳回true,否就傳回false。
    • 當要測試的類別是自定類別時,要依自定類別所提供的equals來決定如何比較,如果自定類別沒有覆蓋Object的equals類別的話,就以Object的equals來比較。
    • Object的equals的比較方式如同==。

String 類別

  • String Class以final修飾,因此不能再被繼承
  • String object的內容是不可改變的(immutable)
  • 字串相加用 +
  • 以+來連結數字與字串時,運算式只要遇到字串,其後的數字相加亦視為字串相加
  • 常用函數有charAt(),compareto(),length(),replace(),split(),Substring(),toLowerCase(),toUpperCase,trim()
    需注意變數內存的類別位址,換言之,唯有當兩個參考指向同一物件時,==運算子的結果才為true。
  • 另一種比較的做法是equals,equals在類別為wrapper classes時,是比較兩個物件是否為相同類型的類別後再比較其內容值是否相同,是就傳回true,否就傳回false。
    • 當要測試的類別是自定類別時,要依自定類別所提供的equals來決定如何比較,如果自定類別沒有覆蓋Object的equals類別的話,就以Object的equals來比較。
    • Object的equals的比較方式如同==。

String Buffer 類別

  1. StringBuffer Class以final修飾,因此不能再被繼承
  2. StringBuffer object的內容是可以改變的(mutable)
  3. StringBuffer並非wrapper classs因此並沒有override equals()方法
  4. 字串相加用 append
  5. 轉成字串用 toString()
  6. 常用函數有 length(), append(), insert(), delete(), CharAt(),replace(), reverse(),capacity()
  7. 配置字元空間原則 : 以16字元的倍數往上加
    1. StringBuffer SB=new StringBuffer(); //預設配置16字元的空間容量
    2. StringBuffer SB=new StringBuffer("Hello"); //配置21字元的空間容量
    3. System.out.println(SB.capacity()); //可使用capacity()方法驗證

陣列

定義

  1. 陣列是一種特殊的類別(class)必須使用new才能建立實體
  2. 宣告方式可以有2種
    1. 型態[ ] 變數,例如: int[] arr1, int[ ][ ][ ] arr3;
    2. 型態 變數[ ] ,例如: int arr1[ ];

配置

  1. new operator 使用new()配置實體
    陣列變數=new 陣列元素型態[個數]
    arr1=new int[3], arr2=new int[2][3][2]; //arr1與arr2的元素內容預設初始化為 0
  2. array initializers 定義時立即配置
    1. int arr3[ ]=new int[ ]{1,3,5}, int[ ][ ] arr4=new int[ ][ ]{{1,3,5}{2,4,6}};
    2. int arr5[ ]={1,3,5}, arr6[ ][ ]={{1,3,5},{2,4,6}};
  3. 多維陣列的動態配置(不對等的配置),但要注意維度相同才能指定
    int [][][] arr7;
    arr7=new int[2][][];
    arr7[0]=new int[3][2];
    arr7[1]=new int[2][2];

存取

  1. 陣列中有一個final 成員變數 length , 用來記錄陣列大小(陣列不可被 resize,除非利用arraycopy.....)
  2. arr1 [0] =2; // arr1:陣列變數 [0]:索引 合稱為 元素
  3. 索引 (index)從0開始, runtime時若超過範圍, 會發生IndexOutOfBoundsException
  4. index只能用byte, short, int, char四種data type
  5. 多維陣列的最後一維代表元素

運算子

  • 不同的運算子(operators)出現時, 視其優先權(Precedence)決定運算順序
  • 相同優先權的運算子出現時, 視其結合性(Associativity)決定運算順序

設定op

=int a,b,c,d;
a=10;
a=b=c=10 //right association
+=,-=,*=,/=,%=
int a=100 ;
double d=123.3;
a+=d; //不明確轉型 a=223
a=a+d; //編譯錯誤,因型態不符 

算術(Arithmetic Operators)

*,/
int a=100, b=22, c;
double d=12.3;

c=a*b;
c=a/b;
c=a*d; //編譯錯誤,因型態變大了
++,--
int a=10;
b=a++; //b=10
int a=10;
c=++a; //c=11

比較(Comparison Operators)

比較的結果一定為 boolean 型態
==,!=Equality Operators
>,>=,<,<=Relational Operators

邏輯(Boolean Operators)

其operands必須為 boolean型態, 比較的結果也一定為 boolean 型態
!,&&,|| 

位元(Bitwise Operators)

其operands必須為 byte, short ,int, long char等
~, &, |, ^~10 => 0101 =>5
10 & 7 => 1010 & 0111 => 0010 => 2
10 | 7 => 1010 | 0111 => 1111 => 15
10^7 => 1010 ^ 0111 => 1101 => 13 

移位(Shift Operators)

其operands必須為 byte, short ,int, long char等
<<, >>,>>>10 << 2 => 1010 << 2 => 101000 => 40 //右邊bits填0
-10 << 2 => 10110 << 2 => 1011000=> -40 //右邊bits填0
2147483647 << 1 => 01......1 <<1 => 11.......10 =>-2 //int最大值左移
-1>>>1 => 11......1>>>1 => 01.....1 => 2147483647 //-1右移後補0
-1>>1 => 11......1>>1 => 11.....1 => -1 //-1右移後視正負號補1或0
public static void main(String [] args) {
int a = -10 ;
System.out.println("a = " + a); //-10
System.out.println("a = " + Integer.toBinaryString(a)); //11111111111111111111111111110110
System.out.println("a = " + (a >> 1)); //-5
System.out.println("a = " + Integer.toBinaryString(a >> 1)); //11111111111111111111111111111011
System.out.println("a = " + (a >>> 1)) ;//2147483643
System.out.println("a = " + Integer.toBinaryString(a >>> 1)); //01111111111111111111111111111011
}

statement敘述句

單行敘述句

以 ; 分號為結尾 ,不以enter為結尾
2個敘述句,分寫2行
int a;
a=10;
2個敘述句,只寫1行
int a; a=10;
1個敘述句,分寫多行
int a
=
200;

區塊敘述句

以大括號包括的範圍 {} //如果大括弧中有許多的單行敘述,都還是算在區塊中的,整個算一個

分支選擇敘述句

 單一雙向多向
語法if (expression)
  statement
if (expression)
  statement_true
else
  statement_false 
switch (expression)
{
  case value_1:
    [statement_1;]
    [break;]
  case value_2:
    [statement_2;]
    [break;]
    ...
  default:     [statement_1;]
    [break;]
  case value_2:
    [statement_2;]
    [break;]
    ...
  default:
    statement
}
備註expression必須為boolean型態expression必須為boolean型態
  • expression必須為int literals (array的index也是)
  • int literals 可用來初始化 byte, short, int, char這四種type
  • case的值範圍受限於expression
  • 若執行到break會跳出{}

迴圈敘述句

計次 : for

語法for( init_Statement ; condition ; incre_statement 
   statement
範例for( int x=1,y=1; a<=5; x+=1,y+=2)
  System.out.println( "x="+x+"y="+y) ;
int a=1; 
for( ;a<=5; )
{
  System.out.println( "Hello World" ) ;
   a++; 
}
備註init_Statement與 incre_Statement 皆可單獨存在

前測 : while

語法while( expression 
  statement
範例a=sum=0;
while( a<=100 )
{
  a=a+1;
  sum=sum+a;
}
System.out.println( "sum="+sum) ;
a=sum=0;
while( a<=100 )
  sum=sum+a++;
System.out.println( "sum="+sum) ;

後測 : do while

語法do 
  statement 
while( 
expression ;
範例int a=1;
int sum=0;
do
{
  sum=sum+a;
  a=a+1;
}
while( a<= 100) ;
System.out.println( "sum="+sum) ;
int a=1;
int sum=0;
do
  sum=sum+a++;
while( a<= 100) ;
System.out.println( "sum="+sum) ;

跳耀敘述句

label

多與break或continue合用,可跳出多層迴圈(multi-level loop)

break

針對 for, while, do while,switch迴圈作跳離

continue

針對 for, while, do while本次迴圈略過其後的敘述句,然後回到重複執行的條件處判斷是否繼續進入迴圈

return

中斷目前程序的執行, 跳回上一層的呼叫點 , 但不可中斷有回傳型態的函數

類別(Class)與物件(Object)

類別包含了
  • 欄位(Fields) = 資料成員( data members ) = 成員變數(variables) = 屬性(atributes)
    • 類別變數(class variables):類別所擁有的變數,只有一份,且不考慮是否有實例,必須宣告有static
    • 物件變數(instance variables):類別的實例所擁有的變數,有多少個物件就有幾個變數
  • 方法(Methods) = 成員函數( member functions) = 操作(operations)
    • 類別方法(class methods):類別所擁有的方法,只有一份,且不考慮是否有實例,必須宣告有static
    • 物件方法(instance methods):類別的實例所擁有的方法,有多少個物件就有幾個方法
  1. 由類別定義所產生的實作稱之為 物件(object) ,也稱為類別的 實例(instance)
  2. Java objects都透過object reference而被取用。
  3. 方法的所有引數都以call by value方式傳遞。
[封裝] [修飾字] class 類別名稱 [extends 父類別] [implements 父介面類別] 
public class j92070303
{
   //成員變數,系統會給初值(int=0;String="";object=null;char='\u0000') 
   static w;
   [封裝] [修飾字] 資料型態 變數1[=初值][,變數2,.......]; 
   string name="peter", blood="A";
   int a;

   //成員函數 
   [封裝] [修飾字] 回傳資料型態 函數名([傳入參數列])
  int max(int a, int b)
  {
     //定義區域變數,系統未給初值,故若直接引用會錯誤 
    int x=100 ;
     //實作區 
    a=b;
    System.out.println(x) ; //區域變數a 
    System.out.println(this); //成員變數a 
     //return 回傳值 
    return a;
  }
  public static void main(String[] p)
  {
    System.out.println("Hello") ;
  }
   ...
}

Inner Classes(內部類別)/巢狀類別(Nested class)

  • 在類別中還可以定義類別,稱之為內部類別(Inner class)
  • Inner class中不可有單獨的static 變數
  • Inner class中不可有 static block , 但可有initial block.(不可有static member)
  • Inner class中不可有 Interface , 因 Interface視為隱含的static
  • Member classes have access to the private fields and methods of the enclosingclass and other member classes.
  • 方法內的inner class只能存取在方法內的 final 變數
  • 呼叫 inner class的要訣:型態.型態 or 實體.實體 
    class D
    {
       D() {System.out.print("D");}
       class Z
       {
          Z()
          {
             System.out.print("Z");
          }
       }
       public static void main(String args[])
       {
          new D().new Z(); //實體.實體 
       }
    }
  • 內部類別的四大類
    1. Static Member Class
    2. Member Class
    3. Local Class
    4. Anonymous Class

介面(Interface)

  • 介面可宣告為物件型態,但不可建立物件實體(new)故不區分所謂的類別成員或物件成員也沒有建構函數
  • 介面是一些方法標記(Signature)的集合而沒有實作,比抽象類別更抽象
  • 方法標記(Signature)包括了 方法名稱,參數個數,參數型態,方法傳回型態與但不包括方法丟出的例外
  • 介面的成員變數可用的封裝與修飾字為 public / static / final , 預設為public,其目的在提供所謂的介面常數以方便使用
  • 介面的存在是為了讓類別實作(繼承)其成員函數, 可用的封裝與修飾字為 public / abstract , 預設為public,故其成員函數不可加上final, static等修飾字
  • 實作介面的類別必須implement其成員函數,若不implement則此類別必須宣告為abstract class
  • 介面是軟體開發上實作軟體元件的可插入性(Pluggability)的關鍵

介面(Interface)與抽象類別(Abstract Class)的區別

  1. 抽象類別可以提供某些方法的部分實作讓所有繼承的子類別一下子就得到了這個新的具體方法,但介面作不到這一點。
  2. 因為單一繼承所以一個抽象類別的實作只能由這個抽象類別衍生,但任一個實作介面所規定的方法的類別都可以具有這個介面的型態且能實作任意多個介面。
  3. 從程式碼的重構角度來看,將一個單獨的具體類別添加一個介面的實作較添加一個抽象類別作為抽象類別容易多了。
  4. 介面是定義混和型態(Mixin Type)的理想工具,混和型態就是在一個類別的主型態之外的次要型態。

封裝等級 / 存取限制(Access Modifier)

可針對class與成員(變數與函數)作封裝
  • 類別class
    • 類別的封裝只有 public 與 none(無)
    • 一個程式檔中只能有一個public class,且其檔名與public class名相同,未指定public的class,其檔名不必與class名相同
    • public class允許不同的package存取,未指定public的class就只能在同一個package存取(若2個class皆未宣告package,但位於同一個目錄,視為同一個package)
    • 不同package的class要如何引用呢 ?
      • import package
      • 直接指定package.class來使用
  • 成員
    • 成員的封裝類型有 private default access(none) protected, public
    • 每一個成員僅能加一個封裝

private

private的成員變數僅提供 同一個類別 的成員函數作存取,就算是同一個檔案但不同class也不可存取,不同package不可存取
private的成員變數如何讓其他class存取呢? 利用同一個類別且宣告為public的成員函數作存取

default access (none)

default access(none) 為在同package(default package)可存取,若子類別繼承後但不在同package則不可存取 //若2個class皆未宣告package,但位於同一個目錄,視為同一個package)

protect

protected為在同類別,同package才可存取,在不同package,子類別繼承後才可以存取
protected為在同一父類別(superclass)下才可以存取

public

public不受限制都可存取

修飾字

可針對class與成員(變數與函數)作修飾

final

final class

  1. 該class不可再被繼承
  2. 其內之成員函數也視為final而不能有abstract
  3. 不可再被宣告為abstract

final method (成員函數)

  1. 無法被子類別overridden
  2. 不可再被宣告為abstrac

final variable

成員變數物件變數區域變數
  1. 無論是否使用一定要初始化
  2. 初始化後其值不可再被改變
  3. 通常在定義時初始化若不在定義時初始化則必須在static initializer初始化
  1. 無論是否使用一定要初始化
  2. 初始化後其值不可再被改變
  3. 通常在定義時初始化若不在定義時初始化則必須在constructor或在instance block {}初始化
  1. 不一定要初始化
  2. 初始化後其值不可再被改變
  3. 通常在定義時初始化若不在定義時初始化則至少到 使用前一定要初始化
public class test {
 static final int a;   //blank final class variable 
 static{
  a=100;
 }

 final int b;     //blank final instance variable 
      // {
      //  b=200;
      // }
 test() {
  b=200;
 }

 public static void main(String args[]) {
  final int c;    //blank final local variable 
  c=300;

  test obj=new test();
  System.out.println(test.a+" "+obj.b+" "+c);
 }
}

static

當執行 java xxx.class
  1. 將xxx.class載入至記憶體中的program區
  2. 配置class中的class variable
  3. 執行class variable initializer
  4. 執行static initializer
  5. 執行類別的constructor
  6. 尋找main的函數並執行

static initializer (static free-floating block)

  
說當載入時或該class具有實體時會立即執行 static block (static initializer) 的部分,且僅執行一次
class person
{
 static String s;
 static
 {
  s="hello";
 }
}

static variable

  1. 變數加上static成為類別變數(不加為物件變數),當class載入時立即配置實體
  2. 類別變數記憶體中只有一份,物件變數可以有許多複本
  3. static 不可修飾 local variable
  4. 如何引用成員變數:
    1. 類別.成員
    2.物件.成員

static method

  1. static method不可直接叫用非static的成員
  2. static method不可使用this 與 super關鍵字
  3. static method不可被子類別的 非static method overridden
class A
{
 int nA;     //物件變數 
 static int sA;   //類別變數 

 public static void fun1()
 {
  int a;
  a=10;
  nA=na+1;   //此行會錯誤,因static fun內引用任何變數均需要有實體或也是static 
  sA=sA+1;
 }
}

abstract

class成員函數
該class不可被建立實體(new),
其物件變數可參考子類別實體
abstract class myShape
{  
  public abstract void draw();
}
class myCircle extends myShape
{     
  public void draw(){} //實作draw 
  {
   System.out.println("O") ;
  }
}
class myRectangle extends myShape
{     
  public void draw(){} //實作draw 
  {
   System.out.println("口") ;
  }
}
public class test
{
 public static void main(String para [])
 {
  myShape drawObj;
  drawObj=new myCircle();
  drawObj.draw();
  drawObj=new Rectangle();
  drawObj.draw();
 }
}
  1. 該函數不可有body{},且以分號;結尾
  2. 所屬類別必須宣告為abstract class
  3. 不可有final, static等修飾字
  4. 其子類別必須實作該abstract methods,否則子類別也會變成abstract class
  5. 左側的程式碼解釋(多型的範例) : 以abstract class宣告物件變數,以實作的子類別new給此物件變數,此時在記憶體中會有binding的效應
    draw() --> draw(){}

方法 (成員函數)

定義語法

[封裝] [修飾字] 回傳型態 函數名稱(傳入參數列) //傳入參數列:型態 參數1,型態 參數2,......
{
}

呼叫執行過程

class person
{
 public String name;
 public char blood;

 Public void set blood( char c )
 {
  blood=c;
 }
}
class person
{
 public String name;
 public char blood ;

 Public void set blood( person this char blood )
 {
   this.blood blood ;
 }
}
public class j92072711
{
 Public static void main(String para[])
 {
  person Obj1=new person();
  Obj1.setBlood('O');
  person Obj2=new person();
  Obj2.setBlood('A');
 }
}
public class j92072711
{
 Public static void main(String para[])
 {
  person Obj1=new person();
  Obj1.setBlood( Obj1 ,'O' );
  person Obj2=new person();
  Obj2.setBlood( Obj2 ,'A' );
 }
}

參數傳遞

this

傳值

一般用於primitive type

傳參考

一般用於非primitive type

多載/同名異式/多型(overload)

定義

  • 同一class內
  • 函數名稱相同
  • 傳入參數型態或個數不同
  • 不考慮回傳型態

呼叫

  • 參數型態最接近者(可轉型者)
  • 參數個數一致

覆載(override)

定義

  • 用於繼承的class內(父子類別)
  • 回傳型態相同與函數名稱與參數型態與參數個數要相同
    • 回傳型態不同時,編譯時會錯誤
    • 函數名稱或參數型態或參數個數不同時則視為不同的函數
  • 其封裝型態的可見度不可縮小,必須大於等於父類別的封裝

呼叫

  • 參數型態最接近者(可轉型者)
  • 參數個數一致

建構函數(建構子/ constractor)

定義

  1. 在建構物件實體時會立即呼叫
  2. 無回傳值,因有回傳值就變成一般函數
  3. 函數名與類別同名
  4. 可加封裝,但不可加修飾字
  5. 可以overload( 不可能有override,因為 建構函數一定與class同名,但不同的class名稱一定不一樣 )
  6. 若class內未定義任何建構函數,則有 預設建構子 ,故若有自行加入建構子,則需自行加入預設建構子
  7. 匿名類別不可有建構函數

建構函數的繼承呼叫

  1. 子類別的建構函數中,預設會執行父類別的建構函數super()
  2. super(?) : 指定呼叫父類別的建構函數,若寫出來則一定要在第一行 //注意其與 super. 的不同
  3. 若有繼承關係如下 : Object -> class A -> class B -> class C,
    則若呼叫new c(10)時則依序執行object() -> A() -> B() -> C(int)的建構函數
  4. this(?) : 指定呼叫自己的建構函數,且一定要在第一行 //注意其與 this. 的不同
  5. this()與super()不可同時存在(因為要在第一行)
  6. Object類別中的建構函數只有 Object(){}

繼承

  • 父類別又稱超類別(super class)或基礎類別,子類別(sub class)又稱擴充類別。
  • 子類別因繼承了父類別所以其基礎就會無形中擴大,也因為有擴大效果所以當時在制定 java 語言的繼承關鍵字時就是使用 extends 而不是使用 inherit。
  • Java 的繼承機制是子類別包含著父類別,因此子類別可以看見父類別,但父類別看不到子類別。

繼承類型

類別繼承(同類繼承) = 實作繼承(Implementation Inheritance)

class A extends B //class A 繼承 class B
  1. 子類別自動擁有父類別所有的成員
  2. 若子類別的成員變數與父類別同名會造成hide效果
  3. 若子類別的成員函數與父類別同名會造成override的效果
  4. 若只宣告class A則預設繼承Object
  5. 若在子類別中要使用父類別的成員要以super.父成員
  6. 子類別的建構函數中,預設會執行父類別的建構函數super()
  7. 子類別的實體中同時存在有父類別的實體,可利用轉型技巧取出

介面繼承(同類繼承)

interface I1 extends I2[,I3,I4.....] //interface I1 繼承 interface I2[,I3,I4....]
  1. 若未extends父介面,則不會自動extends Object
  2. 介面成員變數,一定是final+static(要給初值)
  3. 介面成員函數,則不可有body{},以;作結尾
  4. 可建立物件變數,但不可建立物件實體,若有需要則需參考子類別實體
  5. 其子類別若未實作該methods,子類別會變成abstract class
  6. 介面不可加上final,static修飾字,介面成員函數不可加上final,static修飾字
  7. 封裝與class相同

類別實作介面繼承(不同類繼承) = 介面繼承(Interface Inheritance)

class A implements I1,I2[,I3.....] //class A 實體 interface I1,I2[,I3....]
  1. 可實作多個介面
  2. 子類別自動擁有父類別所有的成員

繼承說明

  1. 繼承後子類別將擁有父類別全部的成員,存取問題看封裝。
  2. 物件的轉型因繼承的關係而有直系與旁系的區分,若進行旁系轉型會有編譯錯誤,直系轉型只能由子代往父代轉否則會有執行時期的錯誤。
  3. 有2個class, class A, class B extends A, 則2者有 is a 的關係(A繼承B)。
  4. 有2個class, class A, class B implements A, 則2者有 is a 的關係(A實作自B)。
  5. 有2個class, class A, class B{A obj=new A()} , 則2者有 has a 的關係。
  6. has a的關係在大部份的Design Pattern書籍中,將之說成Delegate(委派)。
  7. 設計類別時,在一般情況下應儘量使用委派(delegate)而少用繼承。
    1. 以委派取代繼承的時機:某個subclass只使用super classes 介面中的一部份,或是根本沒用到繼承而來的資料。
    2. 以繼承取代委派的時機:當在二個classes中使用delegate,並經常為二個classes間寫作許多簡單的delegate function。
  8. 有2個class, class A, class B extens A, 若父類別A有例外,則子類別B的例外可省略,就算有寫例外也不能大於父類別。
  9. 有2個class, class A, class B extens A, 若父類別A有一個public的成員,則子類別B的成員也不能大於父類別(寫的並不精確)。

例外(Exception)

  • exception是一種信號,代表某種意外狀況或錯誤。
  • "throw an exception"是發出信號,表示現已發生某種意外狀況或錯誤,當java interpreter 執行到一個 throw statement,它會馬上停止正常的程式執行,而去尋找適當的"exception handler",來處理throw statement所丟出的意外狀況 。
  • "exception handler"指的是某種處理意外狀況或錯誤的機制,它會 catch an exception 。
  • exception的分類
    • compiler會去檢查exception是否有適當處置,稱為 checked exceptions 
    • compiler不會去檢查exception是否有適當處置,稱為 unchecked exceptions 
  • 一個overriding method所丟出的exceptions,不能超過overridden method所丟出exceptions的範圍,否則會發生compiler error。

Exception classes的階層 (The Exception Hierarchy)

  • java.lang.Object
    • java.lang.Throwable
      • java.lang.Error //如JVM的錯誤,可以捕捉,但無法補救,故通常不處理,屬於unchecked exception
      • java.lang.Exception //以下除了RuntimeException 皆屬於checked exceptions
        • java.lang.RuntimeException //程式的bug,程式設計師自己小心寫作就可避免, 屬於unchecked exception
          • java.lang.ArithmeticException
          • java.lang.NullPointerException
          • ........
        • java.io.EOFException
          • FileOutFowerdException
          • ........
        • SQLException
        • .......

編譯期例外

Exception中除了RuntimeException屬於unchecked Exception,其餘的稱為Checked Exception,如 IOException
public class demo
{
 public static void main(String[] p)
 {
  throw new RuntimeException; //編譯時不會錯誤 
  new FileReader("c:\\ccc"); //編譯時會錯誤 
 }
}
public class demo
{
 public static void main(String[] p)
 {
  throw new RuntimeException //編譯時不會錯誤 
  try
  {
   new FileReader("c:\\ccc")
  }
  catch (IOException e)
  {
  }
 }
}

執行期例外

  • RuntimeException(unChecked Exception):在編譯階段可不使用try...catch仍然會過
  • 因為IOException是由JVM管理,所以不需作處理

自訂例外

發生來源

  • 程式引發 : 如 10 / 0                     //會產生例外實體
  • 設計師引發 : throw 例外物件實體. 例如.throw New IOException  //會產生例外實體

捕捉&處理

  • 對於 exception我們有2種方式可以處理
    • 處理(handling):使用try-catch-finally statement,自行處理checked exception
      • catch block 可以有0 ~ n個
      • finally block 可以有0 ~ 1個
    • 宣告(declaring):使用throws子句,需告自己(函數)可能會丟出某種exceptions,而將exceptions丟給caller處理 //函數本體中仍可能有例外的出現,如程式引發或設計師引發等,此時也還是要try-catch-finall statement , 且其例外也不能超過throws的例外
  • catch的順序需注意繼承順序(子->父),否則會因為多型的緣故, 父類別型態=子類別實體 給接走了

處理(handling)

語法範例
try
{
   程式碼區塊
}
catch(例外類別 變數) //捕捉1 
{
   例外處理
}
catch(例外類別 變數) //捕捉2 
{
   例外處理
}
finally
{
   一定會執行到的code
}
若例外未被捕捉處理則交由系統
import java.io.*;
public class test
{
 public static void main(String[] p)
 {
  int x,y=0;
  try
  {
   if(y==0)
    throw new ArithmeticException();    //自行控制例外 
   else
    x=10 / y;             //new ArithmeticException(但永遠不會發生此例外) 
   System.out.println("x="+x);
   FileWriter FW=new FileWriter("c:\\c");
  }
  catch(IOException e)           //e = new ArithmeticException(無捕捉到 
  {
   System.out.println("IOException e catch"+ e.getMessage() );
  }
  catch(ArithmeticException e)       //e= new ArithmeticException(補捉到) 
  {
  System.out.println("ArithmeticException e catch"+e.getMessage() );
  }
  catch(RuntimeException e)      //ArithmeticException的父類別(需注意不能與子類別互換位置) 
  {
  System.out.println("RuntimeException e catch"+ e.getMessage() );
  }
  finally
  {
   System.out.println("絕對會執行");
  }
 }
}

宣告(declaring)=函數指明丟出例外

語法範例
try
{
   fun1();
}
catch(例外類別 變數) //捕捉1 
{
   例外處理
}
catch(例外類別 變數) //捕捉2 
{
   例外處理
}
finally
{
   一定會執行到的程式碼
}
若例外未被捕捉處理則交由系統 void fun1() throws 例外的class 
{
  fun1()的程式碼可能會有例外
}
import java.io.*
public class test {

  static void fun1() throws ArithmeticException //指明丟出例外 
  {
   int x,y=1;
   if(y==0)
    throw new ArithmeticException();   //自行控制例外 
   else
    x=10 / y;   //new ArithmeticException(但永遠不會發生此例外) 
   System.out.println("x="+x);
  }
public static void main(String[] p)
  {
   try
   {
    fun1();
   }
   catch(Exception e)           //懶人做法 
   {
    System.out.println("Exception e catch");
   }
   finally
   {
    System.out.println("絕對會執行");
   }
  }
}

輸入與輸出(java.io.*)

Java 將 I/O 分為高階 I/O 與低階 I/O ,高階 I/O 在使用上提供更多的讀寫方法,如讀寫 int 、 double 、 String 的資料型態,而低階的 I/O 大部份只提供 write 、 read 的 byte[] 存取,因為程式大部份的資料都是以字串或其它主要型態資料來運算,因此低階的 I/O 在使用上不利於程式設計,所以 Java 將許多好用的方法全部集合成高階 I/O; 換言之,低階 I/O 的主要工作是負責與媒體資料作存取,高階 I/O 類別主要作資料型態的轉換及提供一些特殊的功能。在使用 Java I/O 時要謹記的一個重要原則是,在建立一個 I/O 之前必需先用低階 I/O 類別來存取媒體資料 ( 如檔案或 pipe) ,之後再使用高階 I/O 來控制低階 I/O 類別的動作,這種一層又一層的架構稱 I/O Chain 。

File

File 可針對目錄與檔案作用

語法

File fileObj=new File( String directoryPath, String filename );

常用方法

檔案/目錄存在 : renameto(), delete(), lists()
檔案/目錄不存在 :mkdir(), createnewfile()
import java.lang.*;
import java.io.*;

public static void main(String[] p)
{
try
{
File f1 = new File( "d:\\cc" );
System.out.println( f1.isDirectory() );
if( !f1.isDirectory() ) // 若目錄不存在 則...
{
f1.mkdir();
File file1 = new File( "d:\\cc\\f1.txt" );
System.out.println( file1.isFile() );
if( !file1.isFile() ) // 若檔案不存在 則...
file1.createNewFile();

String[] flist = f1.list();
for( int x=0; x< flist.length; x++)
{
System.out.println( flist[x] );
}
System.out.println( "暫停 按下enter繼續" );
BufferedReader in
= new BufferedReader(new InputStreamReader(System.in));
in.readLine(); // 暫停

file1.delete();
}
f1.delete();
}
catch( Exception rr )
{
System.out.println( rr.getMessage() );
}

}
if( !file1.isFile() ) // 若檔案不存在 則...
file1.createNewFile();

String[] flist = f1.list();
for( int x=0; x< flist.length; x++)
{
System.out.println( flist[x] );
}
System.out.println( "暫停 按下enter繼續" );
BufferedReader in
= new BufferedReader(new InputStreamReader(System.in));
in.readLine(); // 暫停

file1.delete();
}
f1.delete();
}
catch( Exception rr )
{
System.out.println( rr.getMessage() );
}

}

Stream

以byte(byte[])為讀取單位:InputStream, OutputStream
以double byte(char[])為讀取單位:Reader,Writer
Base classNon Buffer subclassBuffer subclass
InputStream
InputStream 是宣告從某特定來源讀取輸入的類別
InputStream 是 java.io 裏大部分輸入資料流的基礎類別 
FileInputStream, PipedInputStreamBufferedInputStream(InputStream子類別實體)
OutputStreamFileOutputStream, PipedOutputStreamBufferedOutputStream(OuputStream子類別實體)
ReaderFileReader, PipedReaderBufferedReader(Reader子類別實體)
WriterFileWriter, PipedWriterBufferedWriter(Writer子類別實體)
FileInputStream,FileOutputStream範例FileReader,FileWriter範例
模擬copy
import java.lang.*;
import java.io.*;

public class demo
import java.io.*;

public class demo
{
 public static void main(String[] p)
 {
  try
  {
   byte[] b=new byte[1];
   FileInputStream FIS=new FileInputStream( p[0] );
   FileOutputStream FOS=new FileOutputStream( p[1] );
 
   while(FIS.read(b)!=-1)
    FOS.write(b);

   FIS.close();
   FOS.close();
  }
  catch(Exception e)
  {
   System.out.println( e.getMessage() )
  }
 }
}
import java.lang.*;
import java.io.*;

public class demo
{
 public static void main(String[] p)
 {
  try
  {
   char[] c=new char[1];
   FileReader FR=new FileReader(p[0] );
   FileWriter FW=new FileWriter(p[1] );

   while(FR.read(c)!=-1)
   {
    c[0]=Character.toUpperCase(c[0]);
    FW.write(c);
   }

   FR.close();
   FW.close();
  }
  catch(Exception e)
  {
   System.out.println( e.getMessage() )
  }
 }
}
BufferedInputStream,BufferedOutputStream範例BufferedReader,BufferedWriter範例
 
import java.lang.*;
import java.io.*;

public class demo
{
 public static void main(String[] p)
 {
  try
  {
   String rStr;
   FileReader FR=new FileReader("c:\\config.sys");
   BufferedReader BR=new BufferedReader(FR);
   FileWriter FW=new FileWriter("c:\\config.dot");
   BufferedWriter BW=new BufferedWriter(FW);

   while(rStr=BR.readline()!=null)
   {

    BW.write(rStr,0,rStr.length());
    BW.newLine();
   }

   BR.close();
   BW.close();
   FR.close();
   FW.close();
  }
  catch(Exception e)
  {
   System.out.println( e.getMessage() )
  }
 }
}

執行緒(Thread)

  • 一個OS有多個process在執行,稱為多工(multiprocessing/multitasking),屬於OS所控制
  • 一個process可以有多個thread執行(一個程式執行多個動作),屬於program所控制,但OS也要支援
  • 一般程式的main() 也是一個thread稱為main thread,main() method可以直接或間接產生許多的threads並同時執行,這就是所謂的multithreading多執行緒
  • Timer與TimerTask這2個class就是應用Thread來實作
  • java.lang 有關執行緒的class與interface
    • Thread (implements Runnable)
      • run(),currentThread(),getName(),start(),Thread(),Thread(Runnable),join(),sleep()
    • Runnable
      • public void run(); //只有一個run方法且為public
public class j93110401
{
 public static void main ( String[] args )
 {
  Thread thisThread = Thread.currentThread();
  System.out.println( "thisThread.getName()="+thisThread.getName() ) ;
 }
}

建立執行緒(Creations of Threads)

  • 配合currentThread()與getName()可以在同一個class內建立多個執行緒
  • 建立執行緒有兩種方式

1.繼承 Thread class

  1. 自定class繼承自Thread
  2. 自定class中 override Thread的run() method
    1. 在run()內可以有while(.T.)
  3. 建構自定的class實體
  4. 呼叫實體的start()方法,就會產生一個執行緒 //只能呼叫一次start()

2.實作 Runnable (implementing Runnable interface)

由於java並不允許多重繼承,因此若不是Thread類別的子類別,都要以此方法來建立執行緒
  1. 自定class implements Runnable
  2. 實作Runnable的run()
    1. 在run()內可有while(.T.)
  3. 建構一Thread的物件實體(必須將自定class的實體傳入Thread物件的建構函數)
    1. Thread th2 = new Thread (自定的class物件)
  4. 執行Thread物件實體.start()

控制執行緒(Controlling Threads)

  • 當一個thread被new出來後,必須執行start()之後,才會進入runnable(排隊)狀態
  • thread何時自runnable(排隊)變到running(存活)或由running變到runnable是由JVM的thread scheduler決定(JVM的分時多工處理)
  • 程式設計師可以呼叫yield method使thread由running變到runnable
  • 若thread遇到下列狀況,會由running變到blocked state
    • 呼叫sleep method
    • 呼叫wait method
    • 呼叫join method
    • 遇到I/O裝置 blocked
    • 進入synchronized block時其lock被其他thread取走
  • 當thread的block 狀態解除後, thread會回到runnable狀態,而非running狀態
  • boolean isAlive() method可用來測試一個thread是否是 running的,因為一個thread的run()結束時,thread就死了,且不能restart。

yield與sleep與wait

  • yield指的是參與排隊但交出控制權(running -> runnable)
  • sleep指的是不參與排隊,休息指定的秒數後才繼續參與排隊(running->blocked->runnable)
  • wait指的是不參與排隊,等待其他執行緒notify或notifyall後才繼續參與排隊,但注意wait要在一個迴圈中才能再參與排隊(running->blocked->runnable)

wait()、notify() 和 notifyAll() 方法

  • 因為使用輪詢(poll ,它可能消耗大量 CPU 資源,而且具有計時不精確的特性),Object 類別包括了一些方法,可以讓執行緒相互通知事件的發生如notify(),notifyall(),wait()。
  • Object 類別定義了 wait()、notify() 和 notifyAll() 方法。要執行這些方法,必須擁有相關物件的鎖。
  • Wait() 會讓呼叫執行緒休眠,直到用 Thread.interrupt() 中斷它、過了指定的時間、或者另一個執行緒用 notify() 或notifyAll() 喚醒它。
  • 當對某個物件呼叫 notify() 時,如果有任何執行緒正在透過 wait() 等待該物件,那麼就會喚醒其中一個執行緒。當對某個物件呼叫 notifyAll()時,會喚醒所有正在等待該物件的執行緒。
  • 這些方法是更複雜的鎖定、佇列和concurrency程式碼的元件。但是,notify() 和 notifyAll() 的使用很複雜。尤其是,使用notify() 來代替 notifyAll() 是有風險的。除非您確實知道正在做什麼,否則就使用 notifyAll()。
  • 與其使用 wait() 和 notify() 來編寫您自己的排程程式、執行緒池、佇列和鎖,倒不如使用 util.concurrent package,這是一個被廣泛使用的開放源碼toolkit,裡面都是有用的concurrency實用程式。JDK1.5 將包括 java.util.concurrent package;它的許多類別都衍生自 util.concurrent。

加入(join)執行緒

  • Thread API 包括等待另一個執行緒完成的方法︰join()。當呼叫 Thread.join() 時,呼叫執行緒將阻斷,直到目標執行緒完成為止。
  • Thread.join() 通常由使用執行緒的程式使用,以將大問題劃分成許多小問題,每個小問題指派一個執行緒。本章末的範例建立十個執行緒,啟動它們,然後使用Thread.join() 等待它們全部完成。

守護程式(Daemon)執行緒

  • 我們提到過當 Java 程式的所有執行緒都完成時,這個程式就離開,但這並不完全正確。隱藏的系統執行緒,如垃圾收集執行緒和由 JVM 建立的其它執行緒會怎麼樣?我們沒有辦法停止這些執行緒。如果那些執行緒正在執行,那麼Java 程式怎麼離開呢?
  • 這些系統執行緒稱作守護程式(Daemon)執行緒。Java 程式實際上是在它的所有非守護程式執行緒完成後退出的。
  • 任何執行緒都可以變成守護程式執行緒。可以透過呼叫 Thread.setDaemon() 方法來指明某個執行緒是守護程式執行緒。您也許想要使用守護程式執行緒作為在程式中建立的背景執行緒,如計時器執行緒或其它延遲的事件執行緒,只有當其它 非守護程式執行緒正在執行時,這些執行緒才有用。

同步(Synchronized)

同步區塊(Synchronized block)
同步方法(Synchronized method)

圖形化使用者介面(GUI)

  • 所有會用到的控制與 GUI 的基本元素都是 Component(元件)類別的子類別
  • Component 類別很少會被直接使用,通常都是利用它的子類別產生的物件來繼承
  • AWT元件類別 (Andrew's Windows Toolkit )(Another Windows Toolkit )
    • Java最早的圖形化類別
    • AWT package 中含有很多的類別與子類別。大部份的控制元,像按鈕和文字欄位都是從
      Component 類別繼承下來的。
  • Swing元件類別
    • Java 1.2以後提供,較AWT漂亮
  • Frame(框架)類別用來建立標準的應用程式視窗,它直接繼承 Window 類別
  • Frame 的類別繼承表
      java.lang.Object
       java.awt.Component
        java.awt.Container
         java.awt.Window
          java.awt.Frame
 AWTSwing
Class名java.awt.*javax.swing.*
表單名FrameJFrame
元件-按鈕ButtonJButton
元件-標題LabelJLable
元件-畫布Canvas 
元件-核取方塊CheckboxJCheckBox
元件-單選鈕ChoiceJRadioButton
元件-標題LabelJLable
元件-列表ListJList
元件-捲動軸Scrollbar 
繼承關係與
常用方法屬性
  • Object
    • Component //setVisible(),setBounds(x,y,w,h),setBackground(color)
      • Container //add(元件), setLayout()
        • Window //setCursor(Cursor),setIConImage()
          • Frame //setTitle()
  • Object
    • Component //setVisible(),setBounds(x,y,w,h) ,setBackground(color)
      • Container //add(元件), setLayout()
        • javax.swing.JComponent //JLabel, JButton,....
範例
import java.awt.* ;
import java.lang.* ;
public class j92083101 extends Frame
{
 Button B1;
 public j92083101()
 {
  this.setLayout(null);
  B1=new Button("B1");
  B1.setBounds(50,30,60,25);
  this.add(B1);
  this.setBackground(Color.red);
  this.setBounds(100,100,300,300);
  this.setVisible(true);
 }
 public static void main(String[] args)
 {
  j92083101 Form1=new j92083101();
 }
}
import java.awt.*; // Frame 
import javax.swing.*; //JFrame 
public class j93111103 extends JFrame
//元件區 
static j93111103 Form1;
Button B1;
JButton JB1;

public j93111103() // 表單 & 元件 初始化 
// 用 this 跟用 Form1 都是同一個表單物件實體 
JPanel ContentPane = (JPanel )this.getContentPane(); //取得 ContentPane 用 Container getContentPane() 

ContentPane.setLayout( null ); // 取消元件在 ContentPane 配置的方式

this.setTitle( "first Form" ); //== new Frame( "first Form" )
this.setCursor( new Cursor( Cursor.HAND_CURSOR ) ); // setCursor(Cursor cursor)-->

//this.setBackground( Color.RED ); // setBackground(Color c) --> Color.RED == new Color( 255,0,0 )
ContentPane.setBackground( Color.RED );

B1 = new Button( "B1" );
B1.setBounds( 50,50, 60,25 );
ContentPane.add( B1 ); // 元件要加入 JFrame 的 ContentPane 才行

JB1 = new JButton( "JB1" , new ImageIcon( "Tips.gif" ) );
JB1.setBounds( 50,80, 100,100 );
ContentPane.add( JB1 ); // 元件要加入 JFrame 的 ContentPane 才行

this.setBounds( 100,100, 300,300 ); // 這裡要用 JFrame 的框架(this)
this.setVisible( true ); // 這裡要用 JFrame 的框架(this)
}
public static void main( String[] dd )
{ Form1 = new j93111103(); }
}
高度起算從標題列的頭開始從畫面頂端開始

傾聽的事件

  1. 在myFrame加入可傾聽表單關閉事件 //元件.addwindowListener(傾聽實體)
  2. 實作的方式
    1. 使用WindowListener類別 : 自訂class實作Listener介面 //要實作全部的事件函數
    2. 使用WindowAdapter類別 : 自訂class繼承Adapter //override需要的事件函數
  3. 將自定的class實體置入addwindowListener() //Listener有Window,Mouse,MouseMotion,Key等
    WindowListenerWindowAdapter
    import java.awt.*;
    import java.lang.*;
    import java.awt.event.*;

    public class j92083101 extends Frame
    {
     Button B1;

     public j92083101()
     {
      this.setLayout(null);

      B1=new Button("B1");
      B1.setBounds(50,30,60,25);
      this.add(B1);

      this.addWindowListener(new myWindowListener());
      this.setBackground(Color.red);

      this.setBounds(100,100,300,300);
      this.setVisible(true);
     }
     class myWindowListener implements WindowListener
     {
      public void windowOpened(WindowEvent e){}
      public void windowClosing(WindowEvent e)
      {
       System.exit(0);
      }
      public void windowClosed(WindowEvent e){}
      public void windowIconified(WindowEvent e){}
      public void windowDeiconified(WindowEvent e){}
      public void windowActivated(WindowEvent e){}
      public void windowDeactivated(WindowEvent e){}
     }
     public static void main(String[] args)
     {
      j92083101 Form1=new j92083101();
     }
    使用WindowAdapter可以不用實做沒有用到的方法
    import java.awt.*;
    import java.lang.*;
    import java.awt.event.*;

    public class j92083101 extends Frame
    {
     TextField custno;
     Button B1;

     public j92083101()
     {
      this.setLayout(null);

      B1=new Button("B1");
      B1.setBounds(50,30,60,25);
      this.add(B1);

      this.addWindowListener(new myWindowListener());
      this.setBackground(Color.red);

      this.setBounds(100,100,300,300);
      this.setVisible(true);
     }
     class myWindowListener extends WindowAdapter
     {
      public void windowClosing(WindowEvent e)
      {
       System.exit(0);
      }
      }
     public static void main(String[] args)
     {
      j92083101 Form1=new j92083101();
     }

網路(Socket)

  • Java Socket主要繼承自 java.net package
  • IP使用的class:InetAddress=>getByName(Host),getAllByName(Host),getLocalHost(),getHostAddress()
  • UDP使用的class: DatagramPacket , DatagramSocket
    • 欲送出 UDP 資料之前,先建立一個 DatagramPacket 的物件,並把所需資料一一擺進去
    • 然後再利用 DatagramSocket 把這個 DatagramPacket 的資料 send 出去
  • TCP使用的class: ServerSocket , Socket (InputStream, OutputStream), SoecktImpl
  • application用的class:URL , URL Connection

EchoServer的範例

import java.lang.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class EchoServer extends Frame implements Runnable
{
 Label ipLabel,messLabel;
 TextField ip,mess;
 Button sndButton;
 List messList;
 static int portNum = 8888; //指定傳送與接收的port number 

 public EchoServer() //建構子:產生畫面 
 {
  this.setLayout( null ); //不使用 Layout Manager 
  ipLabel = new Label("目的IP");
  ipLabel.setBounds(5,32,45,25);
  this.add( ipLabel );
  ip = new TextField("127.0.0.1");
  ip.setBounds( 50,32,180,25);
  this.add( ip );
  messLabel = new Label("訊 息");
  messLabel.setBounds(5,60,45,25);
  this.add( messLabel );
  mess = new TextField("Echo test...");
  mess.setBounds( 50,60,180,25);
  this.add( mess );
  sndButton = new Button("傳送");
  sndButton.setBounds( 235,60,50,25);
  sndButton.addMouseListener( new myMouseAdapter() );
  this.add( sndButton );
  messList = new List( 12 );
  messList.setBounds( 10,90,280,200);
  this.add( messList );
  this.addWindowListener(
   new WindowAdapter()
   {
    public void windowClosing(WindowEvent e)
    {
     System.exit(0);
    }
   }
  );
  setBackground(Color.lightGray);
  this.setTitle("EchoServer 傳送與接收");
  this.setBounds( 100,100,300,300);
  this.setVisible( true );
}

class myMouseAdapter extends MouseAdapter // Mouse的事件處理, 僅作click 
{
 public void mouseClicked(MouseEvent e) // 按下 sndButton 按鈕 
 { // 送 
  try
  {
   InetAddress lcIP = InetAddress.getLocalHost(); //主機名稱/IP 
   String sendStr = lcIP.getHostAddress()+"=>" + mess.getText().trim();
   DatagramPacket DP =
      new DatagramPacket( sendStr.getBytes(),
      sendStr.getBytes().length,
      InetAddress.getByName( ip.getText().trim() ),
      portNum );
   DatagramSocket DS = new DatagramSocket();
   DS.send( DP );
   DS.close();
   messList.add( "已送出"+mess.getText().trim() );
  }
  catch(Exception re){}
 }
}

public void run() //多執行緒的run方法 
{
 try
 {
  while( true )
  { // 收 
   byte[] buf = new byte[200]; //設定緩衝區大小 
   DatagramPacket DP = new DatagramPacket( buf , buf.length); //設定接收端的UDP packet 
   DatagramSocket DS = new DatagramSocket( portNum ); //建立傳送端的UDP socket 
   DS.receive( DP ); //接收UDP封包 
   DS.close();
   messList.add( new String( buf ).trim() );
   Thread.sleep(100);
  }
 }
 catch( Exception exc) {}
}

public static void main(String[] para) //主程式 
{
 EchoServer Form1 = new EchoServer();
 Thread thObj = new Thread( Form1 );
 thObj.start();
}
}

記憶體回收(Garbage Collection)

定義
Object o1=new Object();

o1 視為物件變數 
new Object() 視為物件實體
GC對物件實體回收,非對物件變數回收,物件變數自有生命週期,物件實體何時回收由jvm決定

可回收時機

  1. 物件實體未被參考
  2. 物件實體不在Active狀態

通知jvm進行回收

  1. System.gc()
  2. Runntime.getRunntime.gc()

當jvm回收某物件實體時,會跟著執行finalize()

  1. Object.finalize()
  2. finalize是protected的
  3. 設計師若要在回收時做某動作,則要override此方法

GC是如何工作的

為了解決老的物件存儲區域GC操作時過大的停頓,在1.4.1版本的 HotSpot JVM 中還實現了一種可選擇的的近乎開發的標記/清掃收集器(Mostly Concurrent non-copying Mark-Sweep Collector 簡稱(CMS Collector),它將整個的標記/清除等工作分成了四個階段:
  1. 標記初始階段(Initial mark):在這個階段系統標記指標直接引用的對象
  2. 開發標記階段(Concurrent marking):在這個階段完成大部分物件的標記工作
  3. 標記完成階段(Remark):在這個階段,完成標記的收尾工作
  4. 開發清除階段(Concurrent sweeping):將所有未被標記的物件清除掉

資料結構與演算法(collection)

資料結構

用於資料結構的Class與Interface
  • Collection
    • List //add(),remove(),clear(),set()
      • LinkedList
      • Vector
        • stack
    • Set //add(),remove(),clear()
      • HashSet
      • SortedSet
        • TreeSet
  • Map //put(key,value),get(key),remove(key),clear()
    • SortedMap
      • TreeMap
    • HashMap
    • HashTable

常用資料結構的特性
資料結構ordersortedduplicatekeynull
List
 Vector
Set
 HashSet
  SortedSet
  TreeSet
Map
 值可重複,key不可
 HashdMap
 值可重複,key不可
 HashTable
 值可重複,key不可
  SortedMap
 值可重複,key不可
  TreedMap
 值可重複,key不可

資料結構的存取方式
資料結構IteratorEnumeration
List
 Vector
 利用element
Set
 HashSet
  SortedSet
  TreeSet
Map
 HashdMap
 HashTable
 利用element
  SortedMap
  TreedMap

演算法

  • Collections //演算法專用的class所含method皆為static
    • binarySearch()
    • max( Collection )
    • min( Collection )
    • reverse( List )
    • rotate( List )
    • Shuttle( List )
    • Sort( List )
    • Swap( List )

斷言(assert)

簡介

偵錯用

編譯

javac -source 1.4 xxx.java

執行

java -ea xxx

語法

assert express;

express為布林值,若為true時無作用,若為false會引發Assertion Error例外

assert exp1:exp2;

express為布林值,若為true時無作用,若為false會引發Assertion Error例外,且代入exp2作錯誤訊息

限制

什麼時候不可用斷言

  1. public methods 的 arguments checking
  2. 避免side effects:不可改變instance variables的值或影響method的return value

什麼時候可以用斷言

  1. private methods 的 precondition,以確保在進行某些操作之前,一個先決條件已經滿足
  2. 用以檢定所有methods的postcondition,以確保在某些操作後,一個既定的條件仍然滿足
  3. 所有方法的return Value檢查

JAR

  • 在撰寫Java程式碼的實務上,要應用jar檔則是透過import關鍵字。
  • Jar檔的來源其實就是java檔(java → class → jar),因此jar的內容,其實就是可重複利用的程式碼。
  • 實際上jar檔是一種zip壓縮檔,因此它的內容就不限定是由class所壓縮而成的,它可以由各種檔案所壓縮而成。
  • Manifest.mf這個文字檔會存在於每個jar檔案內。
  • 使用Jar檔的成功關鍵在於它的路徑,分為外部路徑與內部路徑。而其外部路徑又分為SDK的外部路徑與JRE的外部路徑。
  • Jar檔的另一項功用,它可成為一個包裝器(wrapper),在Windows平台之下只要條件一切符合,包裝器可直接執行;類似執行檔。
  • Jar檔之主檔名稱可自行命名,不需要等於class的主檔檔名。
Main-Class:<空一格>類別名稱
<空白行> //一定要有空白行,且"類別名稱.class"需含有 main()這個method
輸入以下指令:(假設*.class跟manifest.mf都放於C:\目錄下)
jar cvfm myJAR.jar manifest *.class //myJAR為產生的jar名稱,可隨意取
jar cvfm myJAR.jar manifest A.class B.class C.class ..... //後面可以接上一個空白鍵後,再加入其它的*.class檔
成功的話就可以在工作目錄中看到包裝好的*.jar檔。
java -jar myJAR.jar
如果作業系統有將*.jar開啟程式設為javaw.exe或java.exe再設定-jar的參數,那麼滑鼠點2下就會自動執行。

連結資料庫-win32 platform

建立資料庫

資料庫的種類(server)

  • MySQL:database以目錄表示,table以檔案表示,放在對應的目錄下(mysqld.exe可視為一種存取資料庫的工具)
  • oracle:database以目錄表示,table以檔案表示,放在對應的目錄下
  • Access:database以檔案表示,table放在檔案中,外表看不到table

存取資料庫(client)

  • 以各式的SQL指令來存取資料庫,如DCL,DDL,DML
    1. 資料定義語言(Data Definition Language,DDL)
        可以用來建立、更改或刪除 table、schema、domain、index 與 view 。主要指令有三:CREATE、ALTER 與 DROP。
    2. 資料操作語言(Data Manipulation Language,DML)
        DML 係用來操作資料。主要指令有四:SELECT、INSERT、UPDATE 和 DELETE。
    3. 資料控制語言(Data Control Language,DCL)
        DCL 提供資料庫的安全性。主要指令有四:GRANT 和 REVOKE、COMMIT、ROLLBACK。
  • MySQL可以MySQL Control Center來作client端的管理工具(MySQLDD.exe)

設定ODBC

控制台/系統工具/資料來源(ODBC) 
建立"mySql_cust1"

java

建立表單

欄位(Textfield):客戶編號custNo,客戶名稱custName,客戶地址custAdd,部門deptNo 
按鈕(Button):第一筆,最後一筆,第一筆,下一筆,新增,修改,刪除,查詢,儲存,放棄 
列表(List): 可供移動紀錄指標的列表

設定資料庫的driver與connection

可以有以下兩種方法
  1. 先在odbc設定DSN,指定好MySQL檔案的位置
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    Connection con=DriverManager.getConnection("jdbc:odbc:DSN名稱","帳號","密碼");
    附註:在ODBC設定的選項下,記得要把「唯讀」的勾拿掉,以免不能新增及修改
  2. 不設DSN,MySQL檔案位置直接寫在getConnection裡
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    String str="jdbc:mysql://127.0.0.1:3306/mysql";
    Connection con=DriverManager.getConnection(str,"帳號","密碼");

範例

Connection conn;
Statement SQLSmt;
ResultSet RS;
try
{
 Class.forName("sun.jdbc.JdbcOdbcDriver"); //load driver 
conn = DriverManager.getConnection("jdbc:odbc:mySql_Cust1"); //取得connection 
 SQLSmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY ); //取得SQL Statement 
 /*下SQL指令有2種語法
  1.SQLSmt.executeQuery() //select
  2.SQLSmt.executeUpDate() //Insert,Update,Delete
 */ 

 RS = SQLSmt.executeQuery("select * from custTab");
 if ( RS.next() ) //移動結果集的紀錄指標:RS.first(),next(),previous(),last() 
 {
   custNo.setText( RS.getString("custNo") ); //欄位名稱=RS.欄位 
   custName.setText( RS.getString("custName") );
   custAdd.setText( RS.getString("custAdd") );
   deptNo.setText( RS.getString("deptNo") );
   do
   {
    showList.add( RS.getString("custNo") ); //將所有紀錄的custNo丟到list中 
   }
   while ( RS.next() );
   RS.first();
 }
}
catch( Exception e)
{
 System.out.println( e.getMessage() );
//package
import java.sql.*;
/*
Class
static Class forName(String className) throws ClassNotFoundException
DriverManager
static Connection getConnection(String url) throws SQLException// jdbc:subprotocol:subname

Connection
Statement createStatement(int resultSetType,int resultSetConcurrency) throws SQLException
void close() throws SQLException

Statement
ResultSet executeQuery(String sql) throws SQLException
int executeUpdate(String sql) throws SQLException

ResultSet
boolean first() throws SQLException
boolean last() throws SQLException
boolean previous() throws SQLException
boolean next() throws SQLException
String getString(String columnName) // getXXX( Field )
*/
public class j93113001
{
public static void main( String[] dd )
{
try
{
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
Connection conn = DriverManager.getConnection( "jdbc:odbc:lccAlias" );
Statement smt =conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY );
ResultSet RS = smt.executeQuery( "SELECT * FROM custtab order by custNo" );
while( RS.next() )
{
System.out.println( "custNo =" + RS.getString( "custNo" ) + " " +
"custName =" + RS.getString( "custName" ) + " " +
"custAdd =" + RS.getString( "custAdd" ) );
}
conn.close();
}
catch( Exception rr )
{
System.out.println( rr.getMessage() );
}
}
}

JSP

安裝server

  1. 請安裝在 d:\Tomcat 目錄
  2. 新增環境變數
    從我的電腦-->系統內容-->進階-->環境變數, 在環境變數中新增 CATALINA_HOME 變數值為 d:\Tomcat\
  3. 測試
    打開瀏覽器輸入 http://localhost:8080 看看是否安裝成功
  4. 專案環境設定
    建立專案結構,假定為 test 專案
d:
cd \Tomcat\webapps\ROOT //Tomcat的專案目錄
md test //建立一個 test 的專案目錄
md WEB-INF //為 test 專案建立結構目錄
cd WEB-INF
md lib
md classes

自行編寫JSP網頁測試

以文書編輯器編寫下列內容, 儲存檔名為hello.jsp (存放在 d:\Tomcat\webapps\ROOT\test 目錄下)
<HTML>
<BODY>
<%= "hello world" %>
</BODY>
</HTML>

在瀏覽器輸入 http://localhost:8080/test/hello.jsp

JSP架構

  • JSP網頁中包含了靜態的網頁元素(template text)與動態的JSP元素(JSP elements)
  • JSP元素利用<%........%>將Java的程式碼包起來。
  • JSP元素中的註解方法有四 ,後三種是原先 Java 就有的方法
    • <%-- Calculate total money --%>
    • <%//Calculate total money%>
    • <%/*Calculate total money*/%>
    • <%/**Calculate total money*/%>
  • JSP元素有三類
    1. Directive Element: 以「<%@」 開始,以「%>」結尾,directive有三類: 1 page 2 include 3 taglib 每個directive element都有許多屬性(attributes) ,例如 page 常用的屬性有 contentType , charset , errorPage , isErrorPage , session , pageEncoding , buffer , autoFlush, language , import 等
      <%@ page contentType="text/html"; charset="big5" language="java" import="java.sql.*" errorPage="" %>
      <%@ taglib prefix="c" url="http://java.sun.com/jsp/jstl/core" %>
    2. Scriptlets Element:Java程式碼
      <%
        int _start = 1;
        int _end = 10;
        for (int i = _start; i <= _end; i++){.............}
      %>
    3. Expression Element :插入HTML標籤中的運算式,其運算式會自動隱含轉換為字串型態,且不需要分號結尾
      現在日期時間為<%= new java.util.Date() %>
<%@ page contentType="text/html"; charset="big5" language="java" import="java.sql.*" errorPage="" %>
<%@ page import="java.io.*" %> //注意%與@之間最好不要有空白
<%@ page import="java.util.*" %>
<%!
java.util.Date nowDate;
int mem_A;
void fun()
{
}
class person
{
 String name;
}
%>
<%
Calendar calendar = new GregorianCalendar();
nowDate = new Date();
calendar.setTime( nowDate );
%>
<html>
<body>
今天日期<%=calendar.get(Calendar.YEAR)%>年<% out.print( calendar.get(Calendar.MONTH)+1 )%>月<%=calendar.get(Calendar.DAY)%>
<%
person peter = new person();
peter.name="朱孝國" ;
out.print( "peter.name=" + peter.name + "<br />" );
%>
</body>
</html>

相關工具

常用物件呼叫

螢幕顯示

System.out.println( "hello, peter" );

呼叫外部程式

Runtime.getRuntime().exec( "Cdplayer.exe" );

結束GUI程式的執行

System.exit(0);

在linux下使用java

簡介

安裝虛擬機器(VM)的目的在提供java bytecode一個執行環境,可用SUN或IBM的JDK,似乎IBM的JDK效率稍好一些可惜的是好像不發展了?
GNU為Java開發了一個compiler名為 GCJ,但其目的在做一個類似 GCC 的java compile,除了編譯出class檔外,還可以編譯出2進位檔,但目前版本並不支援collections,networking,reflection,serialization,AWT等class
Resin 是一種cutting-edge XML Application Server,可執行JSP

步驟

  1. 下載SUN的JDK
    在Sun的網站有兩種版本可供下載,一種是 RPM 形式,一種是 TarBall 形式,以下以rpm為例,在開始安裝前,請 su 使用者為 root。
  2. 副檔名為.bin者是一個shell script,所以在執行前先給予檔案有執行的權限
    chmod 755 j2sdk-1_4_2_05-linux-i586-rpm.bin 或 chmod +x j2sdk-1_4_2_05-linux-i586-rpm.bin 或 sh j2sdk-1_4_2_05-linux-i586-rpm.bin
  3. 執行script
    ./j2sdk-1_4_2_05-linux-i586-rpm.bin // 此時就會開始解壓縮,完成後在相同的路徑下,會出現一個rpm的檔案j2sdk-1_4_2_05-linux-i586-rpm
  4. 安裝rpm檔,若出錯誤訊息,說有dependence的問題,則加入 --nodeps的option即可。
    rpm -ivh j2sdk-1_4_2_05-linux-i586-rpm //會安裝到/usr/java/下
  5. export PATH=$PATH:/usr/java/j2sdk/bin //建議可建立一個 jdk 的 link 到 j2sdk 方便更新JDK
  6. source /etc/profile
  7. 下載測試程式(Fibonacci.java)
  8. javac Fibonacci.java //本例會有2個.class檔產生
  9. java Fibonacci //載入Fibonacci.class執行

Java 相關的認證

目前 Java 相關的認證分別是 SCJA、SCJP、SCJD、SCWCD、SCBCD、SCDJWS、SCEA、SMAD,參考網址為 : http://suned.sun.com/US/certification/java/java_progj2se.html

SCJP(Sun Certified Java Programmer)

  • SCJP 5.0(CX-310-055) 的範圍 52%
    150美元,時間 175分鐘,共72題複選及填充,答對 59% (43題) 是及格標準。
    • Section 1: Declarations, Initialization and Scoping
    • Section 2: Flow control
    • Section 3: API Contents
    • Section 4: Concurrency
    • Section 5: OO Concepts
    • Section 6: Collections / Generics
    • Section 7: Fundamentals
  • SCJP 1.4(CX-310-035) 的範圍 52%
    150美元,時間 120分鐘,共61題複選及填充,答對 52% (32題) 是及格標準。
    • Section 1: Declarations and Access Control
    • Section 2: Flow control, Assertions (斷言) , and Exception Handling
    • Section 3: Garbage Collection
    • Section 4: Language Fundamentals (oop,object,datatype,operator)
    • Section 5: Operators and Assignments
    • Section 6: Overloading, Overriding, Runtime Type and Object Orientation
    • Section 7: Threads
    • Section 8: Fundamental Classes in the java.lang Package
    • Section 9: The Collections Framework
  • SCJP 1.2(CX-310-025) 的範圍
    150美元,時間 120分鐘,共 59題複選及填充,答對 61% 是及格標準。
    • Section 1: Declarations and Access Control
    • Section 2: Flow Control and Exception Handling
    • Section 3: Garbage Collection
    • Section 4: Language Fundamentals
    • Section 5: Operators and Assignments
    • Section 6: Overloading, Overriding, Runtime Type, and Object Orientation
    • Section 7: Threads
    • Section 8: The java.awt Package
    • Section 9: The java.lang Package
    • Section 10: The java.util Package
    • Section 11: The java.io Package

SCJP考試的潛在技巧與陷阱Provided by Ajith Kallambella

  1. Two public classes in the same file. (illegal)
    • 一個java檔中不可有2個public的class
  2. Main method calling a non-static method. (illegal)
    • main方法本身是類別方法,而類別方法不可直接呼叫物件方法
  3. Methods with the same name as the constructor(s)
    • 方法可以跟建構子有同樣的名稱,差別在建構子沒有傳回值
  4. Thread initiation with classes that do not have a run() method.
  5. Local inner classes trying to access non-final vars. (illegal)
  6. Case statements with values out of permissible range. (byte,int, short,char)
  7. Math class being an option for immutable classes !! (totally wrong!)
  8. instanceOf is not same as instanceof. (注意O大小寫之分)
  9. Private constructors. (legal)
  10. An assignment statement which looks like a comparison.
  11. System.exit() in try-catch-finally blocks. (finally block不會執行)
  12. Order of try-catch-finally blocks matters. (若順序錯的話: error: No try beforecatch)
  13. main() can be declared final. (OK)
  14. -0.0 = = 0.0 is true.
  15. A class without abstract methods can still be declared abstract.
  16. RandomAccessFile descends from Object and implements DataInput and DataOutput.
  17. Map does not implement Collection.
  18. Dictionary is a class, not an interface.
  19. Collection is an Interface where as Collections is a helper class.
  20. Class declarations can come in any order.
  21. Forward references to variables gives compiler error.
  22. Multi dimensional arrays can be sparce.
  23. Arrays, whether local or class-level, are always initialized.
  24. Strings are initialized to null, not 「empty」 String.
  25. An empty String is NOT the same as a null String.
  26. A declaration cannot be labelled.
  27. "continue" must be in a loop(for, do, while). It cannot appearin case constructs.
    • continue必須搭配迴圈使用,而不能用在switch case的選擇敘述句中
  28. Primitive array types can never be assigned to each other, eventhough theprimitives themselves can be assigned.
  29. A constructor can throw any exception.
  30. Initilializer blocks are executed in the order of declaration.
  31. Instance initializer(s) gets executed ONLY IF the objects are constructed.
  32. All comparisons involving NaN and a non-Nan would always result false.
  33. Default type of a numeric literal with a decimal point is double.
  34. integer (and long ) operations / and % can throw ArithmeticException whilefloat / and % will never, even in case of division by zero.
  35. = = gives compiler error if the operands are cast-incompatible.
  36. You can never cast objects of sibling classes( sharing the same parent), even with an explicit cast.
  37. equals returns false if the object types are different.It does not raisea compiler
    error.
  38. No inner class can have a static member.(but static inner class can)
  39. File class has NO methods to deal with the contents of the file.(also theexisting directory)
  40. InputStream and OutputStream are abstract classes, while DataInput andDataOutput are interfaces.

Java程式寫作上的十大錯誤排行榜By David Reilly

  • 第10名:Accessing non-static member variables from static methods (such as main)
  • 第9名: Mistyping the name of a method when overriding
  • 第8名: Comparison assignment ( = rather than == )
  • 第7名: Comparing two objects ( == instead of .equals)
  • 第6名: Confusion over passing by value, and passing by reference
  • 第5名: Writing blank exception handlers
  • 第4名: Forgetting that Java is zero-indexed
  • 第3名: Preventing concurrent access to shared variables by threads
  • 第2名: Capitalization errors
  • 第1名: Null pointers!

閱讀中遇到的單字與片語

  • JDK(Java Development Kits) Java發展套件
  • JRE(Java Runtime Enviroment) Java執行環境,供client端使用如browse
  • deck of cards 紙牌
  • Choose all that apply 多選
  • stored alphabetically 依字元大小儲存(排序之意)
  • prevent 阻礙
  • eligible 適合
  • period 句點 : The package name is a series of elements separated by periods.
  • semicolon 分號
  • asterisk 星號
  • legitimate 合理的; 合法的

參考書目

沒有留言:

張貼留言

有任何問題隨時可以留言請教我