想要找 Java 教材:
http://programming.im.ncnu.edu.tw/J_index.html


1. function 一定要明確 "指出" 回傳值 void int... JAVA 很在意這個

--

public class myExcep
{
  public static void main(String args[])
  {
    java.util.Scanner sc = new java.util.Scanner(System.in);
    int num = sc.nextInt(); /* 當輸入不是 int 時,會出現 exception  */
    System.out.println(x);  /* java.util.InputMismatchException */
  }
}

--

switch (grade)
{
  case 'A':
    System.out.println("ok");
    break;
  case 'B':
    break;

}

--

陣列在存取時超出範圍,會發生例外狀況

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10

如果存取一個並未配置空間的陣列參考,會出現
Exception in thread "main" java.lang.NullPointerException
--

Call by Value: 基本型別 (int, float, String...)
Call by Reference: 陣列、物件

foo (int tmp[][]) { do something ... }

bar {
  int num[][] ={ {1,2}, {3,4} }
  foo (num);  /* 這邊是call by reference,所以把參照 num 值拷了一份給 tmp*/
}


--

類別方法(Class Methods)
就是用 static 描述的方法,不用生出物件也可以直接呼叫

class myExample
{  public static void showName()
   {  System.out.print("name: Peter");
   }
}


類別變數(Class Variables)
成員變數屬於類別本身,當類別第一次建立時,就配置變數的記憶體
class myExample
{
  public static double PI=3.1415;
  public static int    count=0;

  myExample() { count++; }
}

main ()
{
  myEx obj[] = new myEx[2];
  obj[0] = new myEx();
  obj[1] = new myEx();
  System.out.println( obj[0].count );    /* 會得到 2 */
}

--

函式在多載,主要是用 input 的參數型別、個數來當識別,例如像:

  public static void   show(int x)    兩者視為相同,無法分辨
  public static double show(int x)    因為皆是傳入一個 int 參數。

--

數學函式的用法,直接用 Math.FUNCTION() 來呼叫就可以,不用 import 其他類別庫,
例如:
Math.max(12, 37)         // 取大值
Math.round(12.32)        // 四捨五入

重要的是 Math 類別提供了兩個 static 變數
Math.PI
Math.E

另外 Math 也提供了亂數可供使用
Math.random();          // 產生 0.0 ~  0.9999999   的亂數
Math.random() * 100     // 產生 0.0 ~ 99.9999999(無窮小數)

--

陣列的宣告法
int [] data = {1,2,3,4,5};
int [][] data = { {1,2,3} , {4,5} , {29,3,2,4,5} };
int [] data = new int [] {1,2,3,4,5};

底下這個方式很特別,稍微學一下。其中 Float 是一種物件
Object data[] = new Object[] {new Integer(28), new Float(12.1)};

/* 把 [][] 看成雙重指標 所以千萬不可以寫成  new int[10] */
/* 否則會出現 incompatible types found : int[]  required: int[][] */
int [][] num = new int[10][];
num[0] = new int[(int) (Math.random()* 10) ];


--

陣列你要想成,有多個指標幫你指向物件,

class node  { public int data; }

在用的時候,千萬記住要各別 new 出物件來
    node myNode[] = new node[5];
    myNode[0] = new node();       /* 各別再去配置空間 */
    myNode[0].data = 10;
    System.out.println(myNode[0].data);

同理也用在 Double 物件上面
    Double foo1[] = new Double[5];
    foo1[0] = new Double(5);
    System.out.println(foo1[0]);

但是如果是基本型別的資料,就可以直接用
    double foo2[] = new double[5];
    foo2[0] =5;
    System.out.println(foo2[0]);

--

String 是種物件,用法

String tmp = new String("the_key_word");
System.out.println( tmp.indexOf("key") );  /* 找出 key 這個字第一次出現*/

String num="123";
Integer.parseInt(str);

--

建構元的名稱,要與類別名稱相同

 class Circle
 {
   public Circle()            /* 修飾子可為 public 表示外界能呼叫  */
   { this(19); }              /* 用 this 這個關鍵字來呼叫建構元    */

   private Circle(int x)      /* 若為 private 則是只能透過內部呼叫 */
   { System.out.println(x); }
 }

--

兒子的 Constructor 如果有呼叫到父親的 Constructor,則要放在第一行
而且是用 super 這個關鍵字。

class Student extends Person
{
    Student()
    {   /* 呼叫父親的建構子,  should be at the 1st line */
        super();
        System.out.println("Student() ");
    }

  void foo() { System.out.println("Son foo"); }
  void bar() { super.foo(); }  /* 自己也有 foo() 所以
                                  如果要呼叫老爸的 foo() 就用 super 這字 */
}

--

super 的用法有兩種:
1. 用來呼叫父類別建構子: super();
   用來呼叫父類別特定的建構子: super(27, "abc");
2. 用來呼叫父類別的函式:如果父親、兒子都有 foo() ,
                         要特定指名呼叫 父的foo() 就用super.foo()


class CBase { protected int value=10; }  /* protected 允許讓兒子繼承 */

class CExt mextends CBase
{
  public int value=20;  /* 此時 CExt 會有兩個 value:自身、由父類來的 */

  public int get_Value() { return (value); }
  public void set_Value(int x)  { value = x; }

  public int get_Base_Value() { return (super.value); }
  public void set_Base_Value(int x) { super.value = x;}
}

public static void main(String args[])
{
    CExt obj1 = new CExt(); obj1.set_Base_Value(28);
    CExt obj2 = new CExt(); obj2.set_Base_Value(99);

    System.out.println( obj1.get_Base_Value() );  /* 得到 28 */
    System.out.println( obj2.get_Base_Value() );  /* 得到 99 */
}

--

this 的用法還有另一招
(注意:在 C++ 語言中,this 是一個指標,所使用時要用 -> 來操作)

class CBase
{
  public int value=10;

  public void show()
  { int value=99;
    System.out.println (this.value);   /* 物件成員 10 */
    System.out.println (value);        /* 區域變數 99 */
}

--

關於 final 的用法

1. 禁止 function 被子類別改寫(overriding)
  class Base { public final void show() {...} }

  /* 錯誤!! overridden method is final */
  class Ext extends Base { public void show() {...} }   /* 不允許自己重新定義 */

2. 用來達到 常數(constant) 的作用
   class Base { public static final double pi=3.14; }
   class Ext extends Base {
     double pi=8;            ○    /* 自己可以另外搞一套 */
     show() { super.pi=10;   ╳ }  /* 但是不可修改到父類那組 */
     show() { pi = 10; }
   }

3. 禁止 class 被繼承
   final class Base {}
   class CExt extends CBase        /* cannot inherit from final CBase */

--

問題:
1. 我在 myExcep.java 中用到 myClass.Java 的類別變數
為什麼 myClass.java 在每次重新執行時,不需要重新編譯?

2. Math.random() 到底產生的範圍是什麼? 去確認一下
   類別 java.util.Random 又是怎樣

3. String.indexOf() 的用法到底怎樣

--

開始談 class 的用法

class FOO()
{
  private int num=0;    /* private 變數隻允許自己的類別來存取 */
  public  set_Num(int x) { num = x; }
}

public class myEx
{
  public static void main(String args[])
  { FOO obj = new FOO();
    FOO.num=10;              ╳
    FOO.set_Num(10);         ○
  }
}

--
在一個建構子中,要呼叫另一個建構子時,用的是 this
而且 this 關鍵字 只能放在建構元內的第一行。

class Cfoo
{ String name;

  Cfoo()
  { this("default"); }  /* this.Cfoo("default") 這是錯的用法 */

  Cfoo(String x)
  { name = x ; }
}

--

預設的建構子

class Cfoo {} 的預設建構子會長成:  public Cfoo()

--

在類別函式中,不可以呼叫 實例函式/實體變數,因為這些東西屬於個別物件所有
non-static method my() cannot be referenced from a static context

class Cfoo
{
  static int num=0;
  int age;

  public void my() { }
  static void my_s()  /* (╳) 類別函式 不可以呼叫 實例函數、實例變數 */
  { my(); }

}

在類別函式中,也不能使用 this這個關鍵字,因為 this 是指呼叫該 method 的物件。

class Cfoo
{ int num=0;    /* 物件變數 */
  public static void get_Num()  /* 類別函式 (!!不可以用到物件變數!!) */
  {
    System.out.println ( num );      /* 這也是不允許的 ,沒物件跟本不會有 num*/
    System.out.println ( this.num )  /* this 代表呼叫這個函式的物件 */
  }                                  /* 不允許 */
}

--

class complex
{
  double a,b;
  public boolean compre(complex obj)
  { /* 要用每個欄位下去逐一比對 */
    if ( this.a==obj.a && this.b==obj.b) return true;
    else return false;  /* 如果寫成 this==obj 這表示,比較兩指標所指位置 */
  }
}

--

在 obj 物件內改寫 toString() 函式,注意看這邊的語法,奧義。

  public static void main(String args[])
  {
    Object obj = new Object()
    {
      public String toString()   /* 改寫 fucntion */
      { return ("noname"); }
    };
    System.out.println( obj.toString() );
  }

--

繼承登場

父類別                          子類別
======                          ======
沒有宣告 public/private  ---->  沒有宣告 public/private
public 成員              ---->  一樣是 public
private 成員             ---->  只能透過父類別的函式來存取
建構元                   ---->  不能繼承


class Circle
{ public Circle() {System.out.println("Circle constructor()");}
  public Circle(int x) {System.out.println("Circle constructor(int x)");}
}

class Coin extends Circle
{ /* 什麼都沒寫,預設會去呼叫父類別的 Circle() - 即 super() */
  public Coin() { System.out.println("Coin construcotr()"); } 與下面同樣意思
  public Coin() { super(); System.out.println("Coin construcotr()"); }

  /* 如果想要 呼叫特定的 父類別建子,那就用 super() - 會呼叫 Circle(int x) */
  public Coin(int x) { super(x); System.out.println("Coin construcotr()"); }
}

--

書本上有談到 overriding 與 overloading
overriding  - 在子類別中,定義名稱、引數個數、傳回值型態均與父類別相同的method
overloading - 在相同類別中,定義名稱相同,引數數目不同,或者型態不同的method

--

抽象類別登場 (子類別用 extends 來繼承,再補齊原本 abstract 部份)
所謂抽象類別就是內含有 abstract function 的類別。其使用語法如下:

abstract class Shape                /* 別忘了 class 要加上宣告 abstract */
{ public abstract void show(); }    /* 然後當然也少不了 函式的部份 */

class Rectangle extends Shape       /* 定義 Rectangle 之後準備實作 show() */
{ public void show() { System.out.println ("Rect()"); } }

class Circle extends Shape          /* 定義 Circle 之後實作 show() */
{ public void show(){ System.out.println ("Circle()"); } }


1. 抽象類別(abstract class)不可用來產生物件
2. 在抽象類別中所有 "抽象函數" 必定要在子類別中實作,這樣才可用子類別建物件
   (別忘了,只要有一個抽象函數存在,該 class 就變成 abstract class
    abstract class 是不能用來產生物件的。)
3. 抽象類別中,可以有部份函數已經實作。未實作部份就是由子類別來補齊。
4. 一個抽象函數,可以宣告為 public/protected

--

談談 interface

1. 介面中的成員變數,要設定初值
2. 在介面中的 function 默認都是 abstract 了
   在介面中的 成員變數 默認都是 final 了,不能更改其值 (一開始就要給初值)
3. 成員函數只能宣告為 public 或者不宣告。不能宣告為 protected/private。
4. 在實作 function 時,傳數參數的型別、數目,與回傳值 都要與介面定義內的相符合。
5. 所有在介面內定義的 function 都要在類別(class) 中實作出來,
   否則該類別就變成 abstract class

interface Shape
{
  int value=10;
  public abstract void foo();
  public abstract void bar();
}

abstract class Circle implements Shape  /* 抽象 - 因為 bar() 沒有實作出來 */
{
  public void foo()  { System.out.println("hello"); }
}

class Triangle implements Shape  /* 全部的函式都實作完,可以用來建立物件 */
{
  public void foo() {...}
  public void bar() {...}
}

--

在 java 中並不支援使用 extends 來多重繼承,而是用 "介面" implements 來實現

interface Shape { public abstract void show(); }  /* 傳入參數要給名字 */
interface Color { public abstract void setColor(String x); }

class Circle implements Shape, Color
{ public void show() {...}     /* 所有 函式 都要實作,否則會變成抽象類別*/
  public void setColor(String x) {...}
}

--

討論 interface 與 abstract 的差別

1. 介面內的 變數成員,要設定為常數
   介面內的 所有方法,都設定為抽象方法。
2. 抽象類別允許:變數不需要設定初值 + 一般函數/抽象函數 並存。

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 kcw 的頭像
    kcw

    kcw

    kcw 發表在 痞客邦 留言(0) 人氣()