● (一)判斷java程式無法執行原因
(1)JRE=> 如果換了電腦以後,原本可執行的*.class卻不能執行了,
要檢查該電腦是否有安裝JRE(JDK是編譯用)
(2)動態class(main)/靜態class
=>如下例,如果有main方法,是可以執行的,但如果沒有main方法,
只有class ex1{}就無法執行,但兩個做法都可以編譯
class ex1{ public static void main(String args[]){ } }
(二)Object物件(一筆資料)=>一個物件(可以記錄下來)就想成是一筆資料
(1)資料庫紀錄的資料
=>資料表(table):資料庫用資料表的方式來儲存資料
=>每一筆資料的欄位(欄位就是field)標題(attribute屬性):
共同規則 、定義、一次重複使用 :建立資料表時,
要先定義每個欄位的名稱(標題又稱細目),因為要儲存的是data,就牽涉
到datatype也要先定義好(ex:姓名/電話/地=>String),
上述只要定義一次就可以針對每一筆資料重複使用這些定義和規則
String name1="a1";
String add1="b1";
String tel1="c1";
String name2="a2";
String add2="b2";
String tel2="c2";
String name3="a3";
String add3="b3";
String tel3="c3";
System.out.println("名:"+name1+"\t地址:"+add1+"\t電話:"+tel1+"\n");
System.out.println("名:"+name2+"\t地址:"+add2+"\t電話:"+tel2+"\n");
System.out.println("名:"+name3+"\t地址:"+add3+"\t電話:"+tel3+"\n");
*如果不用物件導向的方式直接寫程式,三筆資料就要九個變數,
如果需要改變規則像是改變資料類型,就需要一筆一筆去改變
(2)新增資料時
1.定義要在哪一張"資料表"(reference)=>定義資料的共同規則要在靜態的class
2.新增這筆資料=>在動態class做
ex:
class ex2{
String name;
String add;
String tel;
}
*另外開一個靜態class ex2,先定義都會用到的3個欄位標題(屬性):name,add,tel
(3)新增物件(資料的方式)=>或稱"實體化;初始化"物件
*java中不能只定義變數或物件,一定要"初始化"ex:給初始值
語法:
類別 物件名 = new 類別();
類別=>使用的class=>reference(要用哪一個class的規則來新增資料)
=>等號左右兩邊的類別(class)要相同
*如果要查程式碼的某個字是變數或是物件,可以直接用println(要查詢的內容),當輸出的是一個值,那就是變數,輸出的內容為aaa@xxxx
則該查詢內容為物件,且其reference為@前的aaa
ex:
ex2 n1;
System.out.println(n1);
*ex2=>規則(類別),n1是第一筆資料 =>沒初始化之前,n1就像是表格的第一行但還沒產生實際的格子,初始化後才會產生格子
ex:
ex2 n1=new ex2();
ex2 n2=new ex2();
System.out.println(n1);
System.out.println(n2);
*因為class有很多筆資料,所以不能直接給值,要用new新增一張表的資料給n1
*如果把上述程式編譯後執行,會出現如下列內容,ex2=>代表n1和n2屬於哪個reference,@......,後面是一個16進位的序號代表n1和n2的記憶體位置
(三)new執行的步驟
**ex2=>代表n1和n2屬於哪個reference(要去執行哪個class,以後要查reference可以用這個辦法)
(1)配發記憶體=>實體化(stack)
=>new的背後就是一張記憶體表,如下圖,每一個class會有一個不同的記憶體表
=>以上述例子來說,要查n1就是查ex2@(在ex2中)的xxxxxxx(n1的位置),後面的欄位代表n1的name, n1的add, n1的tel
(這邊的name、add、tel是沒有配記憶體的)
=>以ex2的例子來說,new就是給n1和n2一個記憶體位置
=>以java.util.Scanner sc = new java.util.Scanner(System.in);來說,new就是給sc一個記憶體位置
(2)產生初始值=>heap
=>heap是class中的每一個值所放的位置
=>heap這個動作是由new ex2()中的ex2來做
=>會把n1,n2的 name,add,tel給好初始值
=>不同資料類型的初始值不同,String的初始值為null,int的初始值為0, double的初始值為0.0,布林的初始值為false
=>如果程式要呼叫n1的name欄位,就要用n1.name
ex2:
String name;
int add;
double tel;
ex1:
ex2 n1=new ex2();
ex2 n2=new ex2();
System.out.println(n1);
System.out.println(n1.name); //null
System.out.println(n1.add); //0
System.out.println(n1.tel); //0.0
System.out.println(n2);
(3)如果有設計建構式(constructors),會執行建構式的動作=> new ex2() 的()部分
例子:有一個輸入成績單的程式,要傳到資料庫
先分析欄位標題(即每筆資料的屬性)=>去分析除了使用者輸入的資料還需要保留多少資料(ex:這邊多了總分和平均)
1.先訂定管理的class(訂好所有人的共同規則or屬性)
class student{
String name;
int chi;
int eng;
int sum;
double ave;
void show(){
System.out.println(
"名:"+name+
"\t國文 :"+chi+
"\t英文:"+eng+
"\t總分:"+sum+
"\t平均:"+ave);
}
}
*定義5個屬性/欄位名稱和要重複使用的println功能=>當new的時候會一起使用
*java可以用enter換行程式碼,且不影響執行
**在設定管理的class時(在student.class),可以預設初始值,且初始值可以計算
**但在add.java新增資料時,機器不知道sum會隨著chi和eng的變動而變動
**當new的時候,他的步驟是
1.student@xxxx配給s1記憶體位置
2.查從String name;......到show()的資料(但show()這個method要呼叫才會執行),
並且查是否有和此class相同名稱的contractor,有就會去執行
class student{
String name;
int chi=60;
int eng=70;
int sum=chi+eng;
double ave;
}
add.java
s1.chi=90;
s1.eng=70;
s1.sum=s1.chi+s1.eng;
s1.show();//這邊outputs chi和eng分別為90和70,但sum會是130而非160
原因如下:
當在add.java指定s1.chi=65時,已經到堆疊第二層了,可是當執行s1.show()的時候,
機器只知道chi要抓第二層資料,但並不知道應該在sum上面再堆疊一層新的加總值
(因為機器不知道sum會隨著chi和eng的變動而變動)
所以某個變數有變動或是要做計算會影響到其他變數時,
要在new之後重新計算/run一次,變成s1.chi+s1.eng=s1.sum
所以用contructor(在new的時候產生)或method(事後修改用method)來設計就不需要再重新run一次了
*封裝的權限(被使用/呼叫的權限)=>public、protect、default、private
當加了private以後,就無法直接引用
ex:在student.class中,如果設定private int chi;到add.java用si.chi=65;,
再去compiler,會出現無法存取的錯誤訊息
2.新增資料如果不使用建構式,可以在add.java直接給值,但這樣有很多問題,
像是想加規則條件都不能做 ex:要設定不接受負號"-"(負數),若沒有用private,
設定s1.chi=-65是可以過的
所以不建議這麼做,用建構式給定規則會比較好
ex:
sutdent s1=new student();
s1.show();//outputs皆為初始值
s1.name="aaa";
s1.chi=60;
*這邊指的是s1的name要為aaa,s1的chi要為60
(四)Contructours(相當於資料庫的驗證規則)
(1)"new"新增物件時最後執行的步驟
(2)名字必須與"class"名稱一樣
(3)語法:建構式名(引數){ 執行的步驟 }
=>建構式名與class名相同
eX:
class student{
String name;
private int chi;
private int eng;
private int sum;
private double ave;
student(){
System.out.println("請輸入一位學生");
} //建構式
}
**新增資料時,所有要設定的規則都可以在建構式做
(包含:設定初始值、計算式、判斷式...)
class student{
...
student(){
chi=60;
eng=60;
sum=chi+eng;
ave=sum/2;
}
...
}
(4)Local(區域)/global(全域)變數的生命週期
=>this:當無法判斷是全域還是區域變數時(如ex3),
要指回物件本身的屬性(就是指我們在new一個物件時,一開始就定義的屬性)就要在前面加this
ex1:
class student{
String name;
private int chi;
private int eng;
private int sum;
private double ave;
student(){
int chi=60; //區域變數,只要在{}重設int就會產生一個新的變數
int eng=60; //區域變數
//這邊相加的時候,會先找在同一個 {}內的chi和eng,所以總分會是120
sum=chi+eng;
ave=sum/2;
}
void show(){
System.out.println(
"名:"+name+
//在找chi和eng時,會找同一層{}內的chi和eng,
//如果找不到就會往外找,找到最上面一開始定義student的chi和eng屬性,
//初始值都為0
"\t國文 :"+chi+
"\t英文:"+eng+
//因為sum在student()建構式中沒有另外定義,所以還是抓一開始定義的sum
"\t總分:"+sum+
"\t平均:"+ave);
}
}//輸出會得到國文:0 英文: 0 總分:120
**但是區域變數並不會這樣使用,而是用在引數(參數)處
**引數:用來引用外部資料(把外部key的資料帶入),如果沒有引數,就無法接收外部資料
ex2:
1.先將student建構式改成如下
student(int chi,int eng){ }
2.去compiler add.class會出現錯誤訊息
add.java內容如下:
student s1=new student ();
s1.show();
*錯誤訊息:因為contructor要求兩個int引數,可是add中沒有
3.帶入引數的方法為,在add.java中改為
student s1=new student (90,89);
s1.show();
**這邊的90,89的資料類型必須和student建構式中的引數int chi及int eng的資料類型相同
ex3:
student(int x, int y){
chi=x;
eng=y;
}
去run add.class,會有output 國文:90 英文:89
但java為了之後寫文件需要,會把引數的名字和欄位定義為一樣的單字
這時將x,y改為chi和eng,output會變成 國文:0 英文:0
student( int chi , int eng ){
chi=chi;
eng=eng;
}
這是因為chi和eng(紅色的)又被限定在這個{}內,所以又會去找同層的chi和eng,
就會找到 chi和eng,被指回int chi和int eng
但是在執行show()的時候,找的是一開始定義的屬性private int chi;
和private int eng;,沒有被上述建構式指到,所以還是0
**所以這邊要能跑出資料,要指回物件(student class)本身的屬性,
要在chi和eng前面加上this,this指的就是student物件本身
(this=>attribute of the object)
student.class
class student{
String name;
private int chi;
private int eng;
private int sum;
private double ave;
student(int chi,int eng){
if(chi>=0 && chi <=100 && eng>=0 && eng<=100){
this.chi=chi;
this.eng=eng;
sum=chi+eng;
ave=sum/2;
}else{
System.out.println("0~100");
}
}
void show(){
System.out.println(
"名:"+name+
"\t國文 :"+chi+
"\t英文:"+eng+
"\t總分:"+sum+
"\t平均:"+ave);
}
}
add.class
class add{
public static void main(String args[]){
student s1=new student (-5,89);
s1.show();
}
}
*在編譯add時,如果有查到裡面有其他的class,會連同這些class一起編譯
(5)Overloading(多載化;多種狀況)=>7/31
=>名稱一樣
=>引數不一樣
(五)UML(Unified Modeling Language)=>類別圖,是一種模組化的概念
1.類別名稱(class)
2.field區=>每一筆物件詳細的細目(變數)/attribute,其中"-"代表private
3.constructors
4.methods
=>每一個類別圖代表一個class,裡面只要寫摘要不要寫內容(內容是流程圖)
=>紅色的兩項最重要