JAVA Note

本網頁以打造無障礙閱讀為目標,可以用任何瀏覽器來觀看本網頁


簡介

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

在Sun Microsystems的 Java語言白皮書裡提到, Java語言有以下特點

應該還可加入以下特點

JAVA的版本

下載與安裝

jdk的安裝說明

Java Development Kit 5.0 官方安裝說明,若需要step by step的版本請參考:Java Programming程式發展環境建置指南

Class Path的說明

JAVA平台架構

J2SE 平台架構圖

J2SE平台架構圖

JAVA程式語言

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

可應用層面

語言編譯流程

HelloWorld.java ascii的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程式架構

Java程式有2大類

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;
}

請以文書編輯器鍵入上方程式區塊內容,並特別注意下列幾點

命名方式

撰寫程式時常遇到要為類別,函數,變數,常數命名的情況,Java 中的命名必須符合其識別字(Identifier)的規範

延伸閱讀:Java Programming Style Guide  ,  Code Conventions for the Java Programming Language(Java程式碼慣例翻譯)

package宣告區

import敘述區 = 引入何套件

class, interface, enum 區 = 類別宣告

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程式可選擇以下三種類型的編輯器

筆者的建議是初學使用純文字的編輯器,其中筆者偏好的是 Crimson ,日後可改用火紅的Eclipse。
以下假設SDK已安裝在d:\jdk,接下來為大家介紹如何設定Crimson與UltraEdit作為編寫java的IDE環境 。

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

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

Java資料型態

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)方法,有下列幾種

double d = 123.35;
String str = String.valueOf(i);

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

Tip:如何尋找API ? 1.傳入為 String 型態 2.回傳 基本資料型態 3.一定是static 4.API的解釋為所需

要將 String 轉換成基本資料型態,大多需要使用基本資料型態的包裝類別(wrapper class)的靜態(static)方法,但須注意的是,若轉換失敗時會丟出例外:NumberFormatException

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()會回傳同一個實體

String 類別

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. 多維陣列的最後一維代表元素

運算子

設定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)

類別包含了

  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)

介面(Interface)

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

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

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

可針對class與成員(變數與函數)作封裝

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)

定義

呼叫

覆載(override)

定義

呼叫

建構函數(建構子/ 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(){}

繼承

繼承類型

類別繼承(同類繼承) = 實作繼承(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 classes的階層 (The Exception Hierarchy)

編譯期例外

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)
  {
  }
 }
}

執行期例外

自訂例外

發生來源

捕捉&處理

處理(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 class Non Buffer subclass Buffer subclass

InputStream

InputStream 是宣告從某特定來源讀取輸入的類別
InputStream 是 java.io 堣j部分輸入資料流的基礎類別

FileInputStream, PipedInputStream BufferedInputStream(InputStream子類別實體)
OutputStream FileOutputStream, PipedOutputStream BufferedOutputStream(OuputStream子類別實體)
Reader FileReader, PipedReader BufferedReader(Reader子類別實體)
Writer FileWriter, PipedWriter BufferedWriter(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)

public class j93110401
{
 public static void main ( String[] args )
 {
  Thread thisThread = Thread.currentThread();
  System.out.println( "thisThread.getName()="+thisThread.getName() ) ;
 }
}

建立執行緒(Creations of Threads)

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)

yield與sleep與wait

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

加入(join)執行緒

守護程式(Daemon)執行緒

同步(Synchronized)

同步區塊(Synchronized block)

同步方法(Synchronized method)

圖形化使用者介面(GUI)

  AWT Swing
Class名 java.awt.* javax.swing.*
表單名 Frame JFrame
元件-按鈕 Button JButton
元件-標題 Label JLable
元件-畫布 Canvas  
元件-核取方塊 Checkbox JCheckBox
元件-單選鈕 Choice JRadioButton
元件-標題 Label JLable
元件-列表 List JList
元件-捲動軸 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等
    WindowListener WindowAdapter
    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)

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

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

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

演算法

斷言(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

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)

存取資料庫(client)

設定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

Apache Tomcat 下載 Tomcat 5.5.12

  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架構

<%@ 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考試的潛在技巧與陷阱Provided by Ajith Kallambella

  1. Two public classes in the same file. (illegal)
  2. Main method calling a non-static method. (illegal)
  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.
  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

閱讀中遇到的單字與片語

參考書目

網路資源

主 網 站:http://peterju.notlong.com (目前轉址至 http://irw.ncut.edu.tw/peterju/) Sitetag Logo

Level Triple-A conformance icon | [歡迎使用任何作業系統、瀏覽器觀看!] | Valid XHTML 1.0 Transitional | Valid CSS! | [Valid RSS] | [創意公眾許可証]
This work is licensed under a Creative Commons License