15 方法(2)-兼論靜態資料
[15-1 static關鍵字]
欄位及方法前置static表示為靜態資料及方法。
[15-1-1靜態(static)及非靜態(non-static)資料及方法]
一般資料(欄位、變數)及方法(操作、函式)須建立物件才可使用,但具static屬性之資料及方法則可不須建立物件即可直接使用,稱為靜態資料及靜態方法。
靜態資料只會在記憶體上建立一份資料,即使建立物件亦共用同一份資料。但非靜態資料則各物件擁有各自的資料,換言之,在記憶體上會建立多份資料,且各自獨立互不相干。
[15-1-2靜態資料及方法之宣告方式]
靜態資料(static data):
前置static,例:
static int mathscore;
static int engscore = 59;
靜態主方法(static main method):
public static void main(String[] args){ }
靜態一般方法(static method):
public static int genmd(int x){ }
非靜態資料及方法因要建立物件後才可使用,有時也稱為物件資料及方法,Java會因場合不同而有不同之名稱。
靜態變數及物件變數運用時之名稱指定
同一類別 |
不同類別 |
||
靜態變數 |
非靜態變數 |
靜態變數 |
物件變數 |
變數名 |
物件名.變數名 |
類別名.變數名 |
物件名.變數名 |
類別名.變數名 |
|
物件名.變數名 |
|
物件名.變數名 |
|
|
|
<靜態變數與物件變數例>
public class StaticField1{
static int x1=10; //靜態變數
int y1=100; //非靜態變數
public static void main(String[] args){ //靜態主方法
x1=11; //同一類別,靜態變數,變數名
StaticField1.x1=13; //同一類別,靜態變數,類別名.變數名
StaticField1 sf10=new StaticField1(); //主類別建立物件
sf10.x1=14; //同一類別,靜態變數,物件名.變數名
sf10.y1=101; //同一類別,物件變數,物件名.變數名
StaticField2.x2=21; //不同類別,靜態變數,類別名.變數名
StaticField2 sf20=new StaticField2(); //建立他類別物件
sf20.x2=22; //不同類別,靜態變數,物件名.變數名
sf20.y2=201; //不同類別,物件變數,物件名.變數名
System.out.println("列印顯示1");
System.out.println("x1="+x1+" y1="+sf10.y1);
System.out.println("x2="+StaticField2.x2+" y2="+sf20.y2);
System.out.println("");
staticMethod1();
sf10.method2();
}
static void staticMethod1(){
x1=15; //同一類別,靜態變數,變數名
StaticField1.x1=17; //同一類別,靜態變數,類別名.變數名
StaticField1 sf11=new StaticField1(); //主類別建立物件
sf11.x1=18; //同一類別,靜態變數,物件名.變數名
sf11.y1=102; //同一類別,物件變數,物件名.變數名
System.out.println("列印顯示2");
System.out.println("x1="+x1+" y1="+sf11.y1);
StaticField2.x2=23; //不同類別,靜態變數,類別名.變數名
StaticField2 sf21=new StaticField2(); //建立他類別物件
sf21.x2=24; //不同類別,靜態變數,物件名.變數名
sf21.y2=202; //不同類別,物件變數,物件名.變數名
System.out.println("x2="+StaticField2.x2+" y2="+sf21.y2);
System.out.println("");
}
void method2(){
x1=19; //同一類別,靜態變數,變數名
StaticField1.x1=21; //同一類別,靜態變數,類別名.變數名
StaticField1 sf12=new StaticField1(); //主類別建立物件
sf12.x1=22; //同一類別,靜態變數,物件名.變數名
sf12.y1=103; //同一類別,物件變數,物件名.變數名
System.out.println("列印顯示3");
System.out.println("x1="+StaticField1.x1+" y1="+sf12.y1);
StaticField2.x2=25; //不同類別,靜態變數,類別名.變數名
StaticField2 sf22=new StaticField2(); //建立他類別物件
sf22.x2=26; //不同類別,靜態變數,物件名.變數名
sf22.y2=203; //不同類別,物件變數,物件名.變數名
System.out.println("x2="+StaticField2.x2+" y2="+sf22.y2);
}
}
class StaticField2{
static int x2=20; //靜態變數
int y2=200; //非靜態變數
}
執行結果:C:\js>java StaticField1
列印顯示1
x1=14 y1=101
x2=22 y2=201
列印顯示2
x1=18 y1=102
x2=24 y2=202
列印顯示3
x1=22 y1=103
x2=26 y2=203
靜態方法及物件方法運用時之名稱指定
同一類別 |
不同類別 |
||
靜態方法 |
非靜態方法 |
靜態方法 |
非靜態方法 |
方法名 |
物件名.方法名 |
類別名.方法名 |
物件名.方法名 |
類別名.方法名 |
|
物件名.方法名 |
|
物件名.方法名 |
|
|
|
<靜態方法與物件方法例>
public class Smclass1{
static int num=0;
public static void main(String[] args){ //靜態主方法
System.out.print ((++num)+ " ");
System.out.println (smethod1());
System.out.print ((++Smclass1.num)+ " ");
System.out.println (Smclass1.smethod1());
Smclass1 s1=new Smclass1();
System.out.print ((++s1.num)+ " ");
System.out.println (s1.smethod1());
System.out.print ((++num)+ " ");
System.out.println (s1.nonsmethod2());
System.out.print ((++Smclass1.num)+ " ");
System.out.println (Smclass2.smethod3());
Smclass2 s2=new Smclass2();
System.out.print ((++s1.num)+ " ");
System.out.println (s2.smethod3());
System.out.print ((++num)+ " ");
System.out.println (s2. nonsmethod4());
}
static String smethod1(){
return "少年不識愁滋味,";
}
String nonsmethod2(){
return "愛上層樓,";
}
}
class Smclass2{
static String smethod3(){
String i="愛上層樓。";
return i;
}
String nonsmethod4(){
String j="為賦新詞強說愁。";
return j;
}
}
執行結果:C:\js>java Smclass1
1 少年不識愁滋味,
2 少年不識愁滋味,
3 少年不識愁滋味,
4 愛上層樓,
5 愛上層樓。
6 愛上層樓。
7 為賦新詞強說愁。
各位可試著將這首宋詞的部分詞句,重組成正確的次序,並將重複部分去除。
[15-2屬於靜態的主方法]
主方法為程式執行的起點,主方法因需要所在的主類別不建立物件就可執行,故須為靜態方法。
主方法因是靜態方法,故只能存取靜態欄位,非靜態欄位須以建立物件方式存取,已於上述章節說明。
[15-2-1主方法的命令列引數]
由命令列執行Java程式時,可輸入數個引數(參數)。由public static void main(String[ ] args){ }可看出,命令列引數屬於字串型別的一維陣列。
格式:
java 程式位元碼檔名引數值1 引數值2 引數值3........
執行時指定引數值:
java MainArg1 apple orange pear
[範例]
class MainArg1{
public static void main(String[ ] args){
int i ;
if (args.length<3){
System.out.println("請輸入3個命令列引數。") ;
System.exit(1);
}
else {
for(i = 0 ; i < args.length ; i++)
System.out.println((i+1) + ":" + args[i]) ;
}
}
}
執行結果:
C:\js>java MainArg1
請輸入3個命令列引數。
C:\js>java MainArg1 apple orange pear
1:apple
2:orange
3:pear
[15-2-2主方法命令列引數相關函式(內建類別方法)]
[args.length函式]
args.length為取得命令列輸入引數個數之函式。
<範例>如前例。
[Integer.parseInt函式]
主方法命令列引數皆為字串資料型態,數字字串用於計算時,須先轉換為整數資料型態,此時可使用Integer.parseInt函式。
[範例]
class MainArg2{
public static void main(String[ ] args){
int i ;
int j ;
if (args.length==0){
System.out.println("沒有命令列引數。") ;
System.exit(1);
}
else {
for(i = 0 ; i < args.length ; i++){
j = Integer.parseInt(args[i]);
System.out.println((i+1) + ":" + j);
}
//上2行述句可併為System.out.println((i+1) + ":" + Integer.parseInt(args[i])) ;
}
}
}
執行結果:
C:\js>java MainArg2
沒有命令列引數。
C:\js>java MainArg2 100
1:100
C:\js>java mainArg2 100 200
1:100
2:200
[15-3方法多載(overload)]
是在一個類別裡,定義參數的數量、型別不同,但名稱相同的多個方法,稱為方法多載。使用時會呼叫參數的數量、型別相同的方法。
class Score6 {
void totalScore1(int a, int b, int c) {
int chi = a , eng = b , pro = c , totSco1 ;
totSco1 = chi + eng + pro ;
System.out.println("totSco1=" + totSco1) ;
}
void totalScore1(int a, int b) {
int chi = a , eng = b , totSco2 ;
totSco2 = chi + eng ;
System.out.println("totSco2=" + totSco2) ;
}
void totalScore1(double a) {
double chi = a ;
System.out.println("國文=" + chi + "分") ;
}
}
class MainClass6{
public static void main(String[ ] args) {
Score6 so = new Score6( ) ;
so.totalScore1(88,77) ;
so.totalScore1(88.8) ;
so.totalScore1(90,60,70) ;
}
}
執行結果:C:\js>java MainClass6
totSco2=165
國文=88.8分
totSco1=220
留言列表