● static
1.與excel絕對位置觀念一樣
=>在excel中
相對:計算式一樣,但每個計算結果所用的來源資料都不一樣
(每多一筆資料就會多一筆不同的來源)/new的概念
絕對:某一格的內容要一直隨著不同計算結果重複使用,
但不想要每次改變都要一筆一筆資料重作,就拉出表外獨立
($B$1=>代表會鎖住B1位置,計算的時候不會隨著下拉改變)
 
2.class定義時,定義成"唯一"一格,不會隨著"new"物件而配發給每 一筆物件"heap"區,不與物件資料排列
=>只有一格
 
3.存取方式,不需透過物件,只須透過"class"呼叫
=>又稱"類別類"(需透過物件呼叫使用,稱"物件"類)
=>class產生時,還沒new之前,static就已經產生,
所以不用透過new一個物件來產生(由類別來定義產生)
=>所以下例可以一開始就直接寫成fv.money=5000000
*所以在看API 的時候會發現沒有建構式的時候幾乎都是static,因為建構式一定要做new的動作
 
4.使用對象
a)field區屬性
b)methods(如下例的fv.title())
=>當method使用static時要注意,在static method中的變數如果有用到最開始定義的變數(field),只能用有定義為static的變數,但如果是與上面無關的變數就不需要限定為static
c)inner class內部類別(之後再講)
=>b,c是最主要的應用
 
● 實作:
複利本利和=本金(1+利率)n =>fv=money*Math.pow((1+r),Y);
**加底線代表static
**static說明
money改成static前:
 
fv f1= new fv(1,1000000,0.05,10);
fv f2= new fv(2,1000000,0.01,15);
fv f3= new fv(3,1000000,0.07,5);
f1.show();
f2.show();
f3.show();
 
System.out.println("==============");
 
f1.money=2000000;
f1.show();
f2.show();
f3.show();
 
=>3筆本金是不同的資料,所以改f1.money,其他兩筆不會一起變動
money改成static後:
 
fv f1= new fv(1,1000000,0.05,10);
fv f2= new fv(2,2000000,0.01,15);
fv f3= new fv(3,3000000,0.07,5);
f1.show();
f2.show();
f3.show();
 
System.out.println("==============");
 
f1.money=2000000;
f1.show();
f2.show();
f3.show();
 
 
=>最上面的本金會全部變為3000000,因為static只有一格,資料會被最後一筆改掉
=>下面只要f1.money或 f2.money或 f3.money任一改變全部都會跟著改變( 改成static後,變成絕對位置,(相當於拉出excel表外獨立),f1.money=f2.money=f3.money,不論誰改變都會同時變動 )
*完整內容
fv.java
class fv{
private int number;
static int money;
private double r;
private int y;
private double fv;
 
fv(int number,double r, int y){
this.number=number;
this.r=r;
this.y=y;
fv=money*Math.pow((1+r),y); //y是(1+r)的次方
}
 
void show(){
 
System.out.println("編號:"+number+
"\t本金:"+money+
"\t年利率:"+r+
"\t年:"+y+
"\t複利本利和:"+(int)fv //去小數
);
}
 
add1.java
fv.money=5000000;
fv f1= new fv(1,0.05,10);
fv f2= new fv(2,0.01,15);
fv f3= new fv(3,0.07,5);
f1.show();
f2.show();
f3.show();
System.out.println("==============");
f1.money=2000000;
f1.show();
f2.show();
f3.show();
 
=>因為年金都相同,所以就不用每次都去輸入這筆資料,可以把constructor中的money都刪除
 
*如果編號要自動跳號
(一)直接把nubmer++
add1.java
fv.money=5000000;
fv f1= new fv(0.05,10);
fv f2= new fv(0.01,15);
fv f3= new fv(0.07,5);
f1.show();
f2.show();
f3.show();
 
fv.java
private int number;
static int money;
private double r;
private int y;
private double fv;
 
fv(double r, int y){
this.number++;
this.r=r;
this.y=y;
fv=money*Math.pow((1+r),y); //y是(1+r)的次方
}
 
=>因為目前number不是static,所以以每一筆編號都是獨立的不是共用的,當f1做完0+1後,f2的編號是獨立的,故還是從0開始做++,f3亦然
 
(二)把number改為static再++
fv.java
private static int number;
static int money;
private double r;
private int y;
private double fv;
=>如果把static加在private和int中,會得到如上結果
=>這邊的做法是當new f1時,number=0+1=1, 當new f2時,number=1+1=2, 當new f3時,number=2+1=3,最後一筆number把前面的都改掉了
 
=>以這個作法如果要每個編號不一樣,就只能在執行的時候馬上秀一筆資料,才不會後面的資料給改掉,但這樣很難跟陣列結合
add1.java
fv f1= new fv(0.05,10);
f1.show();
fv f2= new fv(0.01,15);
f1.show();
fv f3= new fv(0.07,5);
f1.show();
(三)正確做法
fv.java
private int number;
private static int count;
static int money;
private double r;
private int y;
private double fv;
 
fv(double r, int y){
//也可寫成this.number=++count,但++要寫在前面,
//不然會把加之前的資料指過去
count++;
this.number=count;
this.r=r;
this.y=y;
fv=money*Math.pow((1+r),y); //y是(1+r)的次方
}
=>所以number不能用static,要用另外一個變數(count)去加,這樣number就會各自獨立不會共用一個,是每一次count算好就丟給每一個nubmer
 
 
**複利本利和沒有跟著本金而改變的問題處理
問題:
當本金由5000000改為,20000000,複利本利和都沒變
 
add1.java
fv.money=5000000;
fv f1= new fv(0.05,10);
fv f2= new fv(0.01,15);
fv f3= new fv(0.07,5);
f1.show();
f2.show();
f3.show();
System.out.println("==============");
//static直接用類別呼叫,不要再用f1/f2/f3
fv.money=2000000;
f1.show();
f2.show();
f3.show();
 
fv.java
fv(double r, int y){
count++;
this.number=count;
//也可寫成this.number=++count,但++要寫在前面,不然會把加之前的資料指過去
this.r=r;
this.y=y;
//y是(1+r)的次方,這邊的建構是可以不加這個公式,因為下面mehtod有重算
//fv=money*Math.pow((1+r),y); 
}
 
void show(){
fv=money*Math.pow((1+r),y);
System.out.println("編號:"+number+
"\t本金:"+money+
"\t年利率:"+r+
"\t年:"+y+
"\t複利本利和:"+(int)fv //去小數
);
=>因為本利和本來是在建構式中計算(new的時候才會計算)
當本金改變,不會重新計算,解決辦法就是在show()輸出前重新計算一次
 
**如果要做成表格的方式,把標題拉到最上方共用
fv.java
void show(){
  fv=money*Math.pow((1+r),y);
  System.out.println(number+"\t"+money+"\t"+r+"\t"+y+"\t"+(int)fv);
}
static void title(){
  System.out.println("編號\t本金\t年利率\t年\t複利本利和");
}
 
add1.java
fv.money=5000000;
fv.title();
fv f1= new fv(0.05,10);
fv f2= new fv(0.01,15);
fv f3= new fv(0.07,5);
f1.show();
f2.show();
f3.show();
 
System.out.println("==============");
fv.money=2000000;
f1.show();
f2.show();
f3.show();
=>因為title()是static,所以可以直接用fv.title()不需要new
 
**method使用static要注意,在static method中的變數如果有用到最開始定義的變數(field),只能用有定義為static的變數
eX:把show()改為static,會出現錯誤訊息non-statice varible
static void show(){
fv=money*Math.pow((1+r),y);
System.out.println(number+"\t"+money+"\t"+r+"\t"+y+"\t"+(int)fv);
}
=>因為當在執行show()的時候,會把裡面的變數都當作static來做,如fv.money(ok)、fv.(r),會用fv直接呼叫,這時呼叫到不是static的變數就會出現錯誤
 
如果改成如下內容,就不會有問題,因為count是static
static void show2(){
     System.out.println("請輸入第"+count+"個");
}
 
 
 
**用Scanner來做
addtest.java
import java.util.Scanner;
class addtest{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
System.out.println("請輸入資料筆數");
int n=sc.nextInt();
System.out.println("輸入本金:");
fv.money=sc.nextInt();
fv[] f=new fv[n];
for(int i=0;i<f.length;i++)
{
System.out.print("輸入第"+(i+1)+"筆-->利率: ");
double r=sc.nextDouble();
System.out.print(); //換行排版用    
System.out.print("輸入第"+(i+1)+"筆-->年: ");
int y=sc.nextInt();
f[i]=new fv(r,y);
}
fv.title();
for(int i=0;i<f.length;i++)
{
     f[i].show();
}
}
}
=> double的Scanner函式為 nextDouble()
 
● static import:如果要使用的api的功能中,大部分都是static method,可以直接匯入static method,這樣就可以直接使用method不需要再call class,但非屬於static的method不能這樣做,要透過new
ex:Math
import static java.lang.Math.*;
 FV(double r,int y){
  count++;
  this.number=count;
  this.r=r;
  this.y=y;
  fv=money*pow((1+r),y);
 }
=>這邊的路徑是指到Math下的method,而非指到Math,如果不加static而直接用pow()不用Math.pow() 會找不到
● 實作:
static不一定要連database,譬如可以把常用的公式放入一個class,然後method都設定為static,要用的時候直接呼叫,不用每次都要new,
ex:
FV=>複利本利和=本金*(1+利率)n=>FV(m,r,y)
(m,r,y=>先想好要用到的變數)
AR=>圓面積=3.14*rr=>AR(r)
RO=>周長=23.14r=>RO(r)
cal.java
class cal
{
static double FV(int money,double r, int y)
{
return money*Math.pow((1+r),y);
}
static double AR(double r)
{
return 3.14*r*r;
}
static double RO(double r)
{
return 2*3.14*r;
}
}
 
addcal.java
class addcal{
public static void main(String args[]){
System.out.println(cal.FV(10000,0.05,5));
System.out.println(cal.AR(5));
System.out.println(cal.RO(20));
}
}
=>用double小數點可以取到最小比較精準
=>因為有return,所以是傳值類的,故名稱前面要設定類別,而且可以直接print出來
 
● inheritance繼承=>目的:產生父類別
(1)多個class,共同的屬性與規則
(2)superclass=>父類別,subclass=>子類別(順序由上到下的概念)
(3)extends
假設同一個學校有兩個科系a和b 
a.java
class a{
String name;
int chi;
int excel;
void show(){
    System.out.println("姓名:"+name+"\t國文:"+chi+"\texcel:"+excel);
     }
}
b.java
class b{
String name;
int chi;
int word;
void show(){
     System.out.println("姓名:"+name+"\t國文:"+chi+"\tword:"+word);
 }
}
add2.java
class add2{
public static void main(String args[]){
a a1= new a();
b b1= new b();
a1.show();
b1.show();
}
}
=>在同一個機構/系統(這邊是同一個學校)的前提之下,假設規則要改變(ex:chi要改成可以用double),以上面的做法必須兩個class分別去做修正,如果有很多class就變成要一個一個去改,這樣太浪費時間,可以去抓a和b兩個class定義一樣的規則(共同規則),放到另外一個class(公因數的概念)
class school{
      String name;
      double chi;
}
=>把a和b的這兩個class中的name和chi刪除,若此時直接compiler add2.java,會出現錯誤訊息,因為在a和b class中找不到上述兩個變數
 
作法:
把a和b class都加上extends school
class a extends school{ .....}
class b extends school{ .....}
=>classs a extends school 稱作:school的內容繼承給a,代表把a要用到的內容/功能放在其他class
(一條線延伸的概念,翻譯成延伸比較好理解)
=>所以new的時候,會找a+extends 中 的內容
 
 
 
(4)is-a=>是否具有此class的類型(包括自己定義的class與父類別)
has-a=>是否擁有使用此"方法"與"field"的權限=>是否有繼承
用下面例子來解釋:
我們用b class產生了一個b1物件,如果想看b1有多少功能(包括本身與繼承而來的功能)可用
 
is-a(類型):
b1 is a b(b1是 b class類型的物件)
b1 is a school (b1是 school class類型的物件)
=> 是call by reference的概念
=>因為查b的時候看到裡面有extends school,代表有繼承school,所以b1 is a school,如果shool上面還有繼承也是要一起抓下來
 
has-a(內容):
b1 has a word
b1 has a name
b1 has a chi
**只要沒有設定權限,就會全部繼承,所以越sub的功能越多,越super的功能越少
*繼承時因為很多層,如果用notepad++開發要每一個class都compiler一次不然run會有問題
*繼承的好處=>共同規則只要改一次就好
 
(5)constructor 建構式
a)全部都要執行,一定要執行
b)順序由父類別====>子類別(有上到下)
(一) school有一個建構式,但a沒有建構式的狀況下
school.java
String name;
int chi;
school(){
     System.out.println("我是父類別的建構式");
}
 
a.java
int excel;
void show(){
     System.out.println("姓名:"+name+"\t國文:"+chi+"\texcel:"+excel);}
 
add2.java
a a1= new a();
a1.show();
 
 
(二) school有一個建構式,但a也有一個建構式的狀況下
school.java
String name;
int chi;
school(){
     System.out.println("我是父類別的建構式");
}
 
a.java
int excel;
a(){
     System.out.println("我是子類別的建構式");
}
void show(){
     System.out.println("姓名:"+name+"\t國文:"+chi+"\texcel:"+excel);
}
 
add2.java
a a1= new a();
a1.show();
 
=>在new a的時候,會先去查a class有沒有父類別,如果有,會去看繼承內容和是否有建構式,有建構式就會先做父類別的建構式再做a的建構式,如果school上還有父類別,會再往上找(即由上往下)
 
 
● 之後寫程式,盡量main的內容越少越好,都放在static class
 
arrow
arrow
    創作者介紹
    創作者 muchone 的頭像
    muchone

    簡單。生活。享受

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