Java 程式設計(一):第六章方法與套件引用 - 翻轉工作室

文章推薦指數: 80 %
投票人數:10人

『類別』(Class)是 Java 最的程式單元,是編譯成中間碼(bytecode)的基本單位。

... (a) public static:允許類別外部呼叫的靜態(或稱類別)方法。

翻轉電子書系列:Java程式設計(一)含程式邏輯   翻轉工作室:粘添壽   第六章方法與套件引用 6-1類別與方法呼叫 6-1-1程式最小單位-class 『類別』(Class)是Java最的程式單元,是編譯成中間碼(bytecode)的基本單位。

一套由Java所發展而成的軟體,可能包含若干個類別程式,每一類別實現某一特殊功能。

從軟體工程來講,可以分門別類的將各種功能程式建構獨立的類別。

當我們需要某一專案系統時,再由眾多類別中挑選某些類別組合而成,這就是軟體零件的基本概念。

然而一個類別程式也可能非常龐大,需要由多個『方法』(Method)所構成。

類別程式包含有兩種成員: (1)變數成員:又稱為類別變數,存活於該類別內。

(2)方法成員:實現該類別功能的程式。

最簡單的Java程式可以是單單只有一個主類別構成的程式,其基本架構如圖6-1所示。

圖6-1主類別與方法架構 6-1-2Java程式專案的架構 吾人利用Java來發展軟體,該專案內的架構可歸納出下列重點:(如圖6-2所示) 圖6-2Java軟體專案 (1)一套Java軟體可能包含若干個類別程式。

(2)一個類別程式可能由多個方法程式(或稱方法成員)與若干個變數成員所構成。

(3)方法名稱為main者,稱之為『主方法』(mainmethod),它是啟動Java軟體,第一個執行的程式。

(4)具有main方法的類別程式,稱之為『主類別』(mainclass);它的名稱必須與檔案名稱相同,也是第一個被導入的中間碼。

(5)當由主類別啟動主方法(main)之後,主方法可直接呼叫同類別內的方法;相同的,主類別內的其他方法也可以互相呼叫;此運作程序稱之為『函數呼叫』(Functioncall)。

(6)如果程式正常運作的話,主方法應該是最後結束的執行函數。

也就是說,Java程式由main函數開始執行,也是由他最後結束的。

(7)其他函數也如同main函數一樣,被呼叫執行完成之後,一定會返回程式呼叫的原來地方。

在傳統程式設計的理念上,為了簡化程式開發的複雜性,會將一套系統分割成若干個子系統來實現,然後針對子系統內某些特定功能,獨立開發成『函數』程式。

如此一來,某一套系統也許會被分割成多個程式模組,每一模組再由若干的程式『函數』所構成。

軟體發展步驟是,首先分別獨立實現各個函數程式,再組合各個程式模組,最後再將多個模組整合成一套軟體系統,這種製作理念又稱為『結構化程式設計』。

Java不再延用結構化設計理念,而是以物件導向的設計理念。

雖然程式模組或函數都能表現系統中某一種特殊功能,但他們之間是獨立的;實現每一只函數或模組,都必須從頭開始,很難相互運用。

由許多發展軟體的經驗得知,當您發展某一應用系統時,這些程式模組大多是大同小異的。

因此,我們就思考如何設計一套可以自由伸展的『程式因子』(prime),再由小的程式因子擴充成較大的因子,或組合較若干個因子成為另一功能的程式因子,這個程式因子即是『物件導向』的理念。

實現程式因子的最小單元就是『類別』,類別程式內也可能包含多個『方法』;僅以傳統語言的設計理念,我們暫時將『方法』視為『函數』的功能。

6-2方法宣告與流程 6-2-1方法的宣告 在某一程式內,我們大多會將些特殊功能並會重複使用的程式,編寫成一個方法(或稱為函數),讓它可以被重複呼叫使用。

另一方面,為了實現方法特殊功能(如,加法器),它被呼叫時允許呼叫者植入相關『引數』(如,加數與被加數);執行完後,也會回覆執行結果(如,兩數的和)。

為了達到上述功能,宣告方法的語法如下: 宣告方法(函數)語法: 範   例 方法屬性傳回值型態方法名稱(引數_1,引數_1){ 方法實體… …… return傳回值; } staticintADD(inta,intb){ intc; c=a+b; returnc; } 呼叫方法 範    例 資料型態變數名稱=方法名稱(引數,..); intsum=ADD(3,5); 相關參數如下: (1)方法屬性:可被引用(呼叫)的屬性,常用有下列組合型態: (a)publicstatic:允許類別外部呼叫的靜態(或稱類別)方法。

(b)privatestatic:僅允許類別內其他方法呼叫的靜態方法。

(c)static:如同publicstatic屬性。

(2)傳回值型態:宣告執行該方法後,得到結果的資料型態,可宣告為一般資料型態(int、float、char...等)、或某一物件型態(object),如果不回傳任何值,則宣告為void(空)。

(3)方法名稱:指定該方法(或函數)名稱,與一般變數名稱相同。

(4)引數:呼叫該函數時,可以攜帶的引數,可以是變數、或數值。

(5){……}:函數的程式主體。

(6)return變數(或敘述句):執行後將變數(或敘述句)內容回傳,該資料型態必須與『傳回值型態』相同。

譬如,『主方法』(或稱主函數)是不需經由產生物件再執行,而可以直接執行的(static屬性),並允許外部環境呼叫它(public屬性),執行後也不會傳回任何資料(void傳回值型態);因此,宣告主方法的相關參數為publicstaticvoidmain(..)。

宣告方法(函數)範例: publicstaticvoidmain(Stringargs[]){ …… ……     //“空”(void)傳回值,不需要return } 6-2-2範例研討:加法器函數製作 (A)系統功能:Ex6_1.java 請製作一個兩數相加的加法器函數,於主程式會要求輸入兩個整數,再呼叫加法器球兩整數的和,最後印出兩數相加的結果。

期望操作介面如下: 請輸入第一個整數=>35 請輸入第二個整數=>48 35+48=83 (B)製作技巧研討: 題目要求製作一個加法器(Add()),並將主程式(main())所輸入的兩個整數相加後,顯示其結果。

由此可見,主類別中包含兩個函數(或稱方法,method),如圖6-3所示。

Main方法利用sum=Add(value1,value2)敘述句呼叫Add方法,並且攜帶了兩個引數。

依照引數的相對應位置,將value1內容填入a變數內;也將value2內容複製到b變數內。

Add函數將執行結果sum,利用return敘述句,傳回給main方法,並存入main方法內的sum變數內。

另外,main與Add方法內都有sum變數,但兩者皆是獨立不相干的『區域變數』。

1 2 3 4 5 staticintADD(inta,intb){ intc; c=a+b; returnc; } 圖6-3呼叫加法器函數的運作情形 (C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 //Ex6_1.java   importjava.util.*; /*Ex6_1類別開始*/ publicclassEx6_1{     /*main方法開始*/     publicstaticvoidmain(Stringargs[]){          Scannerkeyin=newScanner(System.in);          intsum;                           //區域變數          intvalue1,value2;          System.out.printf("請輸入第一個整數=>");          value1=keyin.nextInt();          System.out.printf("請輸入第二個整數=>");          value2=keyin.nextInt();          /*呼叫Add()函數*/          sum=Add(value1,value2);          System.out.printf("%d+%d=%d\n",value1,value2,sum);     }/*main方法結束*/       /*Add方法開始*/     staticintAdd(inta,intb){         intsum;                            //區域變數         sum=a+b;         returnsum;     } /*Add方法結束*/ } /*Ex6_1類別結束*/ (D)程式重點說明: (1)第5~29行:『publicclassEx6_1{…}』。

宣告主類別的範圍。

(2)第7~18行:『publicstaticvoidmain(…){….}』。

宣告main方法的範圍。

(3)第23~27行:『staticintAdd(inta,intb){…}』。

宣告Add方法的範圍。

(4)第9行:『intsum;』。

宣告main方法的區域變數sum。

(5)第 23行:『int sum;』。

宣告Add方法的區域變數sum。

6-2-3範例研討:比較大小方法製作 (A)程式功能 請製作一套系統,它允許連續輸入五個數字,再輸出其中最大值與最小值的數值。

系統功能如下:(請參考Ex3_5範例) 請輸入第1整數=>34 請輸入第2整數=>56 請輸入第3整數=>12 請輸入第4整數=>98 請輸入第5整數=>67 最大數值是98 最小數值是12 (B)製作技巧 吾人嘗試製作兩個比較大小方法,一者max(a,b)則傳會兩數較大者,另一者min(a,b)則傳回兩數中較小則,程式架構如下: 圖6-4Ex6_2程式架構 (C)程式範例 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 //Ex6_2.java importjava.util.*; publicclassEx6_2{ //Ex6_2類別開始     publicstaticvoidmain(Stringargs[]){          Scannerkeyin=newScanner(System.in);          intmax=0,min=999;          intvalue;          for(inti=0;i<5;i++){             System.out.printf("請輸入第%d整數=>",i+1);             value=keyin.nextInt();             max=Max(max,value);            min=Min(min,value);          }          System.out.printf("最大數值是%d\n",max);          System.out.printf("最小數值是%d\n",min);       }/*main方法結束*/       staticintMax(inta,intb){ //Max方法開始         if(a>b)          returna;         else          returnb;     } //Max方法結束       staticintMin(inta,intb){ //Min方法開始     if(ajavaEx6_2 請東方擲骰子(按Enter鍵)=>        擲出=>6  5  2 東方擲的是:13 請南方擲骰子(按Enter鍵)=>        擲出=>1  1  5 南方擲的是:7 請西方擲骰子(按Enter鍵)=>        擲出=>1  3  4 西方擲的是:8 請北方擲骰子(按Enter鍵)=>        擲出=>1  1  1 北方擲的是:3 擲出最大的是=13 (B)製作技巧研討: 每位牌友都需要擲3個骰子,我們可以將擲骰子動作製作成函數(game());另外,也需製作一只比較大小的函數(max()),如圖6-3所示。

主程式main呼叫game()函數時,不需攜帶任何引數,但執行完畢後,會傳回3個骰子的總和;呼叫max()函數時,需攜帶兩個函數,但會傳回其中較大者。

圖6-5Ex6_2程式架構 (C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 //Ex6_2.java   importjava.util.*; publicclassEx6_2{     publicstaticvoidmain(Stringargs[]){          intmaxNum,num1,num2,num3,num4;          Scannerkeyin=newScanner(System.in);          System.out.printf("請東方擲骰子(按Enter鍵)=>");          keyin.nextLine();    //暫停的功能          num1=game();          System.out.printf("東方擲的是:%d\n",num1);            System.out.printf("請南方擲骰子(按Enter鍵)=>");          keyin.nextLine();     //暫停的功能          num2=game();          System.out.printf("南方擲的是:%d\n",num2);            System.out.printf("請西方擲骰子(按Enter鍵)=>");          keyin.nextLine();     //暫停的功能          num3=game();          System.out.printf("西方擲的是:%d\n",num3);            System.out.printf("請北方擲骰子(按Enter鍵)=>");          keyin.nextLine();       //暫停的功能          num4=game();          System.out.printf("北方擲的是:%d\n",num4);            maxNum=max(num1,max(num2,max(num3,num4)));          System.out.printf("擲出最大的是=%d\n",maxNum);     }     staticintgame(){          Randomrandom=newRandom();          intk,sum=0,ran;          System.out.printf("\t擲出=>");          for(k=1;k<=3;k++){               ran=1+random.nextInt(6);               System.out.printf("%d  ",ran);               sum=sum+ran;          }          System.out.printf("\n");          returnsum;     }     staticintmax(inta,intb){          if(a>b)              returna;          else             returnb;     } } (D)程式重點說明 (1)第8行:『System.out.printf("請東方擲骰子(按Enter鍵)=>")』。

顯示要求玩家自行啟動亂數產生。

(2)第9行:『keyin.readLine();』。

系統執行到此命令時,會暫停等待使用者由鍵盤輸入數值,並按下『Enter』鍵,再讀入所輸入資料。

但此程式並沒有要求使用者輸入任何資料,讀入資料也沒有存入任何變數,其表示僅等待使用者敲入『Enter』鍵而已。

(3)第4~50行:『publicEx6_2{…}』。

宣告主類別的範圍。

(4)第 5~31行:『publicstaticvoidmain(..){…}』。

宣告主方法的範圍。

(5)第32~43行:『staticintgame(){…}』。

宣告game()方法的範圍。

(6)第44~49行:『staticintmax(inta,intb){…}』。

宣告max()方法範圍。

6-2-5自我挑戰:擲骰子搏奕遊戲 (A)系統功能:PM6_1.java 以前夜市常出現擲骰子的搏奕遊戲,方法是參與賭博者依序擲出三個骰子到碗公內,總數最大者贏了此局。

請編寫一程式來取代賭具(碗公與骰子),並假設只有四個人參與賭博。

程式功能是參與者輸入自己名字,系統立即顯示所擲骰子的總數,最後顯示最高者命名與數值。

期望操作介面如下: G:\Examples\chap6>javaPM6_1 請玩家輸入姓名並擲骰子=>丁一        您擲出=>3  1  3  合計:7 請玩家輸入姓名並擲骰子=>劉二        您擲出=>6  6  2  合計:14 請玩家輸入姓名並擲骰子=>張三        您擲出=>6  2  3  合計:11 請玩家輸入姓名並擲骰子=>李四        您擲出=>4  6  1  合計:11 恭喜!!劉二先生擲出14贏得此局 (B)製作技巧提示: 圖6-6 吾人可規劃兩個方法(main與game)於主類別內(PM6_1)。

game方法處理擲出3個骰字的動作,包含分別顯示每只骰子的數字,以及計算總和,並傳回給主方法main。

虛擬碼提示如下: 導入相關套件; 主類別宣告範圍{    //主類別開始 主方法main宣告範圍{    //main方法開始 宣告擲出最大數值者姓名並設定初值(StringmaxName=“”); 宣告擲出最大數值並設定初值(intmaxNum=0); For(inti=1;i<=4;i++){ 讀入玩家姓名(name); 呼叫擲骰子函數(number=game()); If(number>maxNum){ maxNum=number; maxName=name; } } 輸出最大者姓名與數字(maxName,maxNum); }   //main方法結束 宣告game方法範圍{ //game方法開始 宣告產生亂數物件; 產生並顯示3個1~6之間亂數; 計算總和並回傳; }//game方法結束 }//主類別結束   6-3方法變數與類別變數 6-3-1變數的生存範圍 某一變數被宣告產生之後,可以使用的範圍如何,這也值得商榷的,稱為生存範圍。

基本上,變數的生存範圍僅限制於被宣告時的程式區塊內,越過了程式區塊,便失去了效用。

但程式區塊可能經由多層次的程式區塊所構成,即是區塊內可能再出現子程式區塊,子程式區塊內又可能再出現更內圈的子程式區塊,依此類推層層包圍。

每一層次區塊都可能會宣告變數,變數的生存範圍可能會影響到程式運作的正確性如何。

雖然每一層次所宣告變數的生存範圍不同,但也沒有那麼複雜。

生存範圍最重要的概念是,『外層次所宣告的變數,在該層次內的任何子層次都是有效的;任何內部所宣告的變數,在它的外層次是無效的』。

另一重點是『程式區塊』為何,以Java語言為例,可能出現的有: (1)類別實體:宣告類別後,利用左右大括號({….})所包圍的實體區塊(Body)。

(2)函數實體:宣告函數(方法)後,利用左右大括號({….})所包圍的實體區塊(Body)。

(3)選擇敘述區塊:選擇命令(如if/else/switch/case)的敘述實體。

(4)迴圈敘述區塊:迴圈命令(如for/while/do-while)的敘述實體。

簡單的說,利用左右大括號({….})包起來,即是一個程式實體。

大括號內所宣告的變數,超過大括號以外則無效,即是它的生存範圍。

另外,任何敘述句所出現的大括號皆有此特性。

6-3-2類別變數與方法變數 簡單的說,實體區塊內所宣告的變數,僅存活於該區塊內,區塊以外便不存在了。

但區塊內可能再宣告另一個或多個子區塊,這種情況下,在父區塊或子區塊所宣告變數的存活空間有何不同? 在傳統程式語言(如C語言)之下,父區塊所宣告的變數,在子區塊還是存活著,稱之為『整體變數』;而子區塊所宣告的,在父區塊或同等父區塊的子區塊下是無效的。

Java語言大致上沿用傳統語言規範,要特別留意的是,不同方法之間變數要互相引用時,必須將其宣告成『靜態變數』(staticvariable),如圖6-4所示。

圖6-8類別變數與區域變數 6-3-3範例研討:擲骰子大吃小搏奕 (A)程式功能:Ex6_3.java 擲骰子賭博大多不喜歡『通吃』規則,為了增加次數與趣味性,都採用大吃小的規則,越多人參與賭越好玩,擲出最大者吃最小者。

請製作一套大吃小的擲骰子遊系統,參賭者輸入姓名後擲出3個骰子,隨時告知目前領先者與點數(隱藏最低者姓名與點數),直接鍵入『Enter』表示結束參與者,立即顯示出贏家與輸家為何人,以及其擲出點數為何。

期望操作介面如下: (B)製作技巧研討: 依照系統要求,我們可以歸納出下列重點:(請參考圖6_4) (1)必須隨時紀錄最高與最低者姓名,以及所擲出的點數,將其宣告成類別變數(maxName、minName、maxNum與minNum)。

(2)系統希望參賽者人數不定,利用『Enter』表示結束。

利用所讀入的字串變數(name),其內容的字元長度為0,則表示輸入『Enter』;因此,可利用length()方法判斷字串長度是否為0。

(C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 //Ex6_3.java   importjava.util.*; publicclassEx6_3{   /*宣告類別變數(整體變數)*/    staticStringmaxName="",minName="";    staticintmaxNum=0,minNum=99;      /*main方法開始*/    publicstaticvoidmain(Stringargs[]){      Scannerkeyin=newScanner(System.in);//區域物件      Stringname;                           //區域變數      intnumber;                            //區域變數      System.out.printf("===歡迎光臨大吃小擲骰子遊戲===\n");      System.out.printf("輸入姓名並擲骰子(Enter結束)=>");      name=keyin.nextLine();      while(name.length()!=0){          game(name);          System.out.printf("領先者%s先生%d點\n",maxName, maxNum);          System.out.printf("輸入姓名並擲骰子(Enter結束)=>");          name=keyin.nextLine();       }       System.out.printf("贏家%s先生擲出%d\n",maxName,maxNum);       System.out.printf("輸家%s先生擲出%d\n",minName,minNum);    }    /*game方法開始*/    staticvoidgame(Stringname){        Randomrandom=newRandom();           //區域物件        intran,sum=0;                         //區域變數        System.out.printf("\t您擲出=>");        for(intk=1;k<=3;k++){              //區域變數             ran=1+random.nextInt(6);             System.out.printf("%d  ",ran);             sum=sum+ran;        }        System.out.printf("合計=%d\n",sum);        if(sum>maxNum){             maxName=name;             maxNum=sum;        }        if(sum<=minNum){             minName=name;             minNum=sum;        }    } } (D)程式重點分析: (1)第6~7行:『staticStringmaxName=’””,…』。

宣告nmaxName、minName、maxNum與minNum變數為靜態類別變數,可被直接存取於main與game方法內敘述。

(2)第12行:『Stringname;』。

宣告字串變數name,此為main方法內的區域變數,也僅存活於main方法內。

(3)第17行:『while(name.length()!=0{…})』。

此為while迴圈敘述,條件是判斷name變數內子串長度是否為0(name.length()!=0),如長度大於0則表示有輸入任何字元,該字串即是玩家的姓名;如果長度為0的話,則表示直接敲入『Enter』鍵,妹有輸入任何字元,表示結束的功能。

(4)第18行:『game(name);』。

呼叫game()方法,並攜帶name變數(玩家姓名)內容為引數。

(5)第29~47行:『staticvoidgame(Stringname){…}』。

宣告game方法程式區塊,功能是產生3次1~6的亂數(擲骰子動作),並顯出擲骰子結果。

最後與maxNum與minNum比較是否最大或最小,如是的話,則更改maxName、maxNum內容,或minName與minNum內容(以上皆是靜態變數)。

(6)第31行:『Randomrandom=newRandom();』。

宣告產生Random物件,為區域物件僅存活於game方法內。

(7)第32行:『intran,sum=0;』。

區域變數,僅存活於game方法內。

(8)第34行:『for(intk=1;k<=3;k++){..}』。

變數k是for迴圈的區域變數,僅存活於for迴圈內。

6-3-4自我挑戰:改良型博弈遊戲 (A)程式功能:PM6_X.java 在Ex6_3範例中,如果有兩人擲同樣的點數,會取得先擲的人,我們希望將它修改一下,讓後面擲出的點數與前面的人相同時,請他再重新擲一次。

(B)提示:請自行演練   6-4遞迴函數 6-4-1遞迴函數的流程 主程式呼叫函數後,系統轉移到函數上執行,但函數可能再呼叫其他函數,這是非常普遍的現象。

如果執行某一函數當中,它會再呼叫自己的函數,則稱之為『遞迴函數』(Recursivefunction)。

許多程式設計師喜歡利用遞迴函數來減低程式的設計量,但遞迴函數會佔用許多記憶體空間,並不是非常理想的程式設計手法。

所謂呼叫函數,即是將函數的程式碼倒入記憶體空間,再去執行他;如果呼叫許多函數,則導入了許多程式碼進入系統。

當程式碼進入系統之後,隨之被啟動執行,與原來程式碼沒有任何關係,執行完畢之後,記憶體程式碼隨之被刪除,但磁碟空間內的程式碼還是保留著。

如果某一函數一直呼叫自己,則是不斷的導入與自己相同的程式碼進入主記憶體,前後導入的程式碼之間並沒有任何關連,如圖6-5所示。

圖6-10遞迴函數的運作程序 讀者也許會納悶,如果某一函數會呼叫自己的函數,當然下一次呼叫的函數,還是會再呼叫自己,則將會無窮盡的延伸下去。

為了能讓遞迴函數能有停止的時間,函數內必需加入判斷敘述,條件成立再呼叫自己函數,否則必須轉回。

因此,遞迴函數有某種固定的格式,範例如下: 範例:level(n)=1*2*3*4*,…,*n 說明:total=level(5)的運作程序 staticintlevel(intk){ if(k<=1) return1; else return(k*level(k-1)); } 假設主程式呼叫上述遞迴函數,並給予引數5為例(total=level(5)),其運作程序說明如表6-1所示。

第一次呼叫時k=5,條件判斷不成立,則執行returnk*level(k-1),當呼叫執行level(4)時,同樣再呼叫自己,依此類推,一直到k=1。

當k=1時,條件成立,則返回1,接著level(2)返回得到2、level(3)返回得到6...,最後level(5)返回得到120。

表6-1遞迴函數level(5)執行步驟 次數 level(k) K K<=1 執行動作 返回 1 level(5) 5 no return(5*level(4)) 5*24=120 2 level(4) 4 no return(4*level(3)) 4*6=24 3 level(3) 3 no return(3*level(2))) 3*2=6 4 level(2) 2 no return(2*level(1)) 2*1=2 5 level(1) 1 yes return1 1 6-4-2範例研討:累乘遞迴程式 (A)程式功能:Ex6_4.java 請利用呼叫遞迴函數來編寫累乘程式,程式允需輸入一個整數n,計算並輸出total=1*2*3*4*,…,n(n!);亦需顯示每次遞迴呼叫的執行內容,期望操作介面如下: (B)製作技巧研討: 利用任何迴圈敘述句(for、while)都很容易製作累乘程式,但系統要求利用遞迴函數,只好照辦。

另外,系統要求列印每次呼叫遞迴函數的結果,吾人必須在函數內加入列印的功能。

(C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /Ex6_4.java   importjava.util.*; publicclassEx6_4{    publicstaticvoidmain(Stringargs[]){        Scannerkeyin=newScanner(System.in);        inttotal,num;        System.out.printf("請輸入一個整數=>");        num=keyin.nextInt();        total=level(num);        System.out.printf("1*2*3*,...,%d=%d\n",num,total);    }    /*遞迴函數開始*/    staticintlevel(intk){        intsum;        if(k<=1)            return1;        else{            sum=k*level(k-1);            System.out.printf("%d*level(%d-1)=%d\n",k,k,sum);            returnsum;        }    }/*遞迴函數結束*/ } (D)程式重點說明: (1)第14~23行:『staticintlevel(intk){…}』。

遞迴函數主體。

(2)第16~17行:『if(k<=1)retrun1;』。

表示遞迴函數結束。

(3)第18~22行:『else{sum=k*level(k-1);…}。

函數呼叫與自己名稱相同的函數,但引數減少(k-1)。

(4)第20行:『System.out.printf(…)』。

印出每次呼叫函數的執行結果。

6-4-3自我挑戰:曼波舞步表演系統 (A)程式功能:PM6-2.java 曼波舞步的步法是進一步再退一步、進兩步再退兩步、進三步再退三步,依此類推。

前進多少步則相對應後退多少步,當然不會直線進退,可選擇任何路徑進行;又此可見,連續越多步法越困難。

請製作一套曼波舞步表演系統,並可隨觀眾喜好選擇表演級數,期望操作系統介面如下: G:\Examples\chap6>javaPM6_2 ==曼波舞步表演系統== 請輸入表演級數=>4 第1階舞步=>11 第2階舞步=>1221 第3階舞步=>123321 第4階舞步=>12344321 謝謝參觀 以第2階舞步為例,前進兩步(1,2),之後緊接著後退兩步(2,1)。

(B)製作技巧提示。

舞步中可區分『前進』與『後退』兩種步法,前進多少步則後退幾步;吾人可分別利用兩個遞迴函數來達成,前進遞迴函數(front_dance())可連續印出1、2、3...等k;後退遞迴函數(back_dance)則k...等3、2、1。

另外,由觀眾選擇希望觀賞的級數(num),表演出n=1,2,..,k階層的舞步。

虛擬碼提示如下: 觀眾選擇觀賞級數(n); for(intk=1;k<=n;k++){ 顯示表演階層(k); 呼叫前進遞迴函數(front_dance(k)); 呼叫後退遞迴函數(back_dance(k)); } staticvoidfornt_dance(intk){    //前進遞迴函數宣告  if(k<=1)       System.out.printf("1");  else{       front_dance(k-1);       System.out.printf("%d",k);   } } staticvoidback_dance(intk){     //後退遞迴函數宣告   if(k<=1)        System.out.printf("1");   else{        System.out.printf("%d",k);        back_dance(k-1);   } }   6-5套件引用與方法產生 6-5-1Java套件架構與導入 利用傳統語言編寫程式,一套完整的應用程大多是由多個函數所構成。

因此,我們可將某些特殊功能編寫成函數程式(Function),再編譯成『目的檔』(Objectfile),讓其他程式引用,如此可減少許多應用系統開發的時程,也可達到函數重複使用的目的。

一般會將所開發的函數集,以其功能歸類某些特定功能的群組,並可依照特定群組來引用,因此稱之為『庫存函數』(Library)。

一套系統開發工具(如C語言)的強弱,其關鍵在於所提供庫存函數的多寡。

某些開發工具除了提供標準庫存函數之外,也會提供某些特殊功能的函數庫,譬如,多媒體處理、繪圖功能、動畫功能等等。

既然Java應用系統是由多個類別所構成,我們也可以將某些常用的功能,編寫成類別,並且可重複被引用。

但我們回顧一下Java的特性,如下: (1)類別內有兩個主要成員:變數與方法,如果物件(類別產生)著重於變數,則類似於『結構變數』,主要用描述真實實體的特性。

如果著重於方法,則類似於『函數』功能,主要實現某一特定功能的程式設計。

因此,Java的函數庫,表示類別中較著重於方法的開發。

(2)每一方法實現某一特定功能,一般會將功能相似的方法集中歸納於同一類別裡;即是某一類別裡可以取得相對應功能的方法。

(3)反過來講,某一特殊功能並無法由一個類別承擔,必須由許多類別儲存較細部的分類。

譬如,Windows上的繪圖套件(awt),便需要多個類別來實現。

因此,Java將某一特定功能的類別,再組合成某一功能套件(Package)。

(4)Java將所提供套件、類別、方法以目錄方式儲存,而目錄的根目錄以java表示,如,java.lang.String.substring()。

其中java.lang為套件名稱(language套件)、String為類別名稱、另substring()為方法名稱。

圖6-6為Java套件的結構圖,表6-2為Java內定的子套件(節錄部分),當然還有許多子套件陸續會被發表出來。

每一子套件都針對某一特殊領域,提出許多類別。

圖6-12Java套件結構圖   表6-2Java子套件(節錄) 套  件 說            明 java.applet JavaApllet套件含有Applet類別及其介面,可以建立Applet/瀏覽器,以及多媒體表現平台。

java.awt JavaAbstractWindowsToolkit套件包含所有相關視窗GUI的類別及介面。

java.awt.event JavaAWT可能產生事件的類別與介面。

java.io JavaInput/Output套件包含資料輸入/輸出的類別與介面。

java.lang JavaLanguage套件包含許多Java程式可能使用到的類別及介面;編譯時會自動導入。

java.net JavaNetworking套件幫函網路功能的類別。

java.text 包含國際各種語言顯示的類別。

java.util JavaUtilities套件包含共用程式的類別及介面。

javax.swing JavaSwingGUIComponents套件提供支援可攜式GUI類別;自Java2之後,大多取代java.awt套件。

javax.swing.event 包含Swing可能產生事件的類別;自Java2之後,大多取代java.awt.event套件。

…… …. (A)套件導入-import 套件是『類別』與『介面』的整合,Java利用目錄方式來儲存不同的套件;也就是說,一個套件由一個目錄樹來整合該套件之下的類別,又利用目錄整合同一類別底下的方法。

引用套件時,必須在程式的第一行開始利用import導入套件,語法如下: 導入套件語法: 範例: imortpacketName.subPacket.className; importpacketName.*; importjava.util.Scanner; importjava.util.*; 第一行表示導入packageName套件中的子套件(subPacket)內的className類別,這種表示法最完整。

但如果同一子套件內多個類別時,也可簡化packetName.*,其中『*』表示在此目錄之下所有的意思。

在Java語言中,除了java.lang套件會自動導入,而不用import標明外,其他套件都必須利用import命令導入。

當套件內類別被導入後,有兩種呼叫方法: (1)物件方法:利用new命令,將類別衍生出物件,原類別上所描述的方法,便隨之轉換成物件方法。

使用者可以利用物件方法引用所需的方法。

(2)類別方法:不經由new產生物件,而使用者直接呼叫類別內的方法。

許多較常用功能的套件都採用此方法,譬如java.lang套件內的方法。

6-5-2範例研討:製作工程計算器 (A)程式功能:Ex6_5.java 請製作一套工程計算器,使用者輸入數值後,可選擇log()、log10()、sqrt()、sin()、cos()與tan()等函數計算,並輸出顯示其結果,期望操作介面如下: (B)製作技巧研討: 本系統需引用包含有三角函數的數學套件(java.lang.Math),與允許鍵盤輸入套件,吾人選用java.util.Scanner;當然採用java.io套件亦可。

另外,系統希望能重複選擇輸入使用,需利用while迴圈判斷是否結束,與switch/case判斷選擇項目,並處理相關事項。

選單視窗會重複出現,吾人可將其編寫成函數呼叫(disp_men());但它僅輸出顯示,則沒有引數與傳回值。

(C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 //Ex6_5.java   importjava.lang.*;           //導入子套件(包含Math類別) importjava.util.Scanner;      //導入套件內的類別 publicclassEx6_5{    publicstaticvoidmain(Stringargs[]){          /*利用套件內類別java.util.Sacnner產生物件keyin*/        Scannerkeyin=newScanner(System.in);        doublevalue,ans=0;        intselect;        disp_men();               /*呼叫引用keyin的物件方法nextInt()*/        select=keyin.nextInt();        while(select!=7){             System.out.printf("輸入一個數值(注意三角函數範圍)=>");               /*呼叫keyin的nextDouble物件方法*/             value=keyin.nextDouble();             switch(select){                 case1:                     /*直接引用類別Math的類別方法*/                     ans=Math.log(value);                     System.out.printf("log(%.2f)=%.2f\n",value,ans);                     break;                 case2:                     /*直接引用類別Math的類別方法*/                     ans=Math.log10(value);                     System.out.printf("log10(%.2f)=%.2f\n",value,ans);                     break;                 case3:                      /*直接引用類別Math的類別方法*/                     ans=Math.sqrt(value);                     System.out.printf("sqrt(%.2f)=%.2f\n",value,ans);                     break;                 case4:                     ans=Math.sin(value);                     System.out.printf("sin(%.2f)=%.2f\n",value,ans);                     break;                 case5:                     ans=Math.cos(value);                     System.out.printf("cos(%.2f)=%.2f\n",value,ans);                     break;                 case6:                     ans=Math.tan(value);                     System.out.printf("tan(%.2f)=%.2f\n",value,ans);                     break;                 default:                     System.out.printf("錯誤輸入\n”);              }              disp_men();              select=keyin.nextInt();         }         System.out.print("==謝謝使用歡迎再度光臨==\n");     }      staticvoiddisp_men(){           System.out.printf("\n***工程計算器提供有下列功能***\n");           System.out.printf("(1)log 函數\t(2)log10()函數\n");           System.out.printf("(3)sqrt函數\t(4)sin()  函數\n");           System.out.printf("(5)cos 函數\t(6)tan()  函數\n");           System.out.printf("(7)離開系統\n");           System.out.printf("請選擇輸入=>");      } } (D)程式重點說明: (1)第3行:『importjava.lang.*;』。

導入java.lang下的所有類別;該套件系統會自動導入可不用再import。

(2)第4行:『importjava.util.Scanner;』。

僅導入java.util套件下Scanner類別,其他未被導入,可減少佔用記憶體空間。

(3)第9行:『Scannerkeyin=newScanner(System.in);』。

利用Scanner類別宣告產生keyin物件,keyin物件繼承了Scanner類別的所有方法成員(Methodmember)。

(4)第12行:『disp_men();』。

呼叫disp_mem()函數,該函數無傳回值(void),也不需要傳任何引數。

(5)第15行:『select=keyin.nextInt();』。

呼叫keyin物件內的nextInt()物件方法。

(6)第24行:『ans=Math.log(value);』。

直接呼叫Math類別內的log()類別方法。

6-5-3範例研討:密碼設定程式 (A)程式功能:Ex6_6.java 一般資訊系統大多利用『帳號/密碼』過濾用戶的身份。

用戶輸入帳號與密碼,系統檢視密碼是否正確,正確的話,同意用戶登入系統;否則會拒絕登入。

如此一來,系統需要紀錄用戶密碼,作為判斷用戶身份之依據。

但系統如果以明文儲存用戶密碼,他人只要入侵系統就可以觀察到所有用戶的密碼,因此密碼是不可以『明文儲存』的。

也就是說,密碼必須經過加密或雜湊計算後,成為一串亂文格式再儲存。

但密碼如設定太短的話,所產生的亂文變化就不大,有心人還是可以猜測出密碼。

但一般人為了方便記憶,又不喜歡設定太長的密碼。

『醃製法』密碼計算就是為了解決這個問題。

醃製法是系統產生一個亂數稱之為『鹽』,『鹽』與密碼明文串接成一個較長的字串,此新字串經過加密或雜湊演算後,再儲存於系統。

請製作一套『醃製法』密碼儲存系統,利用使用者輸入密碼明文後,與系統產生一個『鹽』,再將密碼與鹽組合為另一字串,利用此字串產生一個雜湊值,並印出結果;接著,假設使用者欲進入系統,如密碼輸入正確,則允許進入系統;否則拒絕進入。

期望操作介面如下: D:\Java1_book\chap6>javac -encoding utf8 Ex6_6.java   D:\Java1_book\chap6>javaEx6_6 請輸入使用者名稱=>user01 請輸入密碼明文=>123456 產生鹽亂數=942儲存於電腦系統內 密碼明文與鹽組合=123456942 user01密碼雜湊=-1867376844   請輸入密碼(驗證密碼是否正確)=>123456 由系統中取出鹽=942 輸入密碼與鹽結合後=123456942 輸入密碼雜湊值=-1867376844 user01密碼設定正確,該帳戶可使用 (B)製作技巧提示: 圖6-7為密碼雜湊值產生方法,電腦的密碼系統紀錄著每位使用者的『帳戶名稱』、『密碼雜湊值』與『鹽』。

設定密碼的程序是,使用者輸入密碼明文,與系統所產生的『鹽』串接後,再經過『雜湊演算法』計算得到一串固定長度的雜湊值,也將產生的雜湊值與鹽儲存於密碼檔案內。

圖6-15密碼雜湊值的產生方法。

當使用者欲進入系統,則輸入帳戶名稱(如tsnien)與密碼;系統則由密碼檔案搜尋出該帳戶的『鹽』,再與使用者所輸入的『密碼』相連結之後,再經過相同的雜湊演算法計算,得到雜湊值,此值與密碼檔案內的『密碼雜湊值』相同的話,則判斷輸入密碼正確;否則拒絕該使用者登入。

吾人將以上所敘述的運作程序,編寫虛擬碼如下: 導入相關套件(java.util.*;); 宣告紀錄檔:帳號(Stringname)、鹽(Stringsalt)、密碼雜湊值(inthash_pas); 宣告相關變數與物件; /*帳號/密碼設定程式*/ 讀取使用帳號(name); 讀取使用者設定密碼(passwd1); 產生鹽亂數(intvalue1=1+(int)(Math.random()*999)); 轉換鹽亂數成字串(salt =String.valueOf(value1)); 鹽與密碼明文連結(passwd2=passwd1.concat(salt)); 產生密碼雜湊值(hash_pas=passwd2.hashCode()); 輸出顯示該帳號(name)、密碼雜湊值(hash_pas)與鹽(salt); /*密碼驗證程式*/ 讀取使用者輸入密碼(passwd1); 鹽與密碼明文連結(passwd2=passwd1.concat(salt)); 產生密碼雜湊值(test_pas=passwd2.hashCode()); if(test_pas==hash_pas) 顯示"==歡迎光臨藝術化資訊系統=="; else 顯示"密碼不正確,拒絕進入系統"; (C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 //Ex6_6.java /*請製作一套密碼產生系統,當使用者輸入明文密碼,系統則會產生結果並印出*/   importjava.util.Scanner; publicclassEx6_6{    publicstaticvoidmain(Stringargs[]){          Scannerkeyin=newScanner(System.in);        Stringname,key;              //登錄使用者名稱,鹽        inthash_pas;                  //登錄密碼雜湊值        Stringpasswd1,passwd2;        intvalue1,value2;        System.out.printf("請輸入使用者名稱=>");        name=keyin.nextLine();          System.out.printf("請輸入密碼明文=>");        passwd1=keyin.nextLine();        value1=1+(int)(Math.random()*999);        key=String.valueOf(value1);             System.out.printf("產生鹽亂數=%s儲存於電腦系統內\n",key);        passwd2=passwd1.concat(key);        System.out.printf("密碼明文與鹽組合=%s\n",passwd2);        hash_pas=passwd2.hashCode();        System.out.printf("%s密碼雜湊=%d\n",name,hash_pas);          System.out.printf("\n請輸入密碼(驗證密碼是否正確)=>");        passwd1=keyin.nextLine();             System.out.printf("由系統中取出鹽=%s\n",key);        passwd2=passwd1.concat(key);             System.out.printf("輸入密碼與鹽結合後=%s\n",passwd2);        value2=passwd2.hashCode();             System.out.printf("輸入密碼雜湊值=%d\n",value2);        if(value2==hash_pas)            System.out.printf("%s密碼設定正確,該帳戶可使用\n",name);        else            System.out.printf("%s密碼設定不正確,請重新設定\n",name);    } }   6-6專題研討 6-6-1範例研討:製作DES加密/解密工具 (A)程式功能:Ex6_7.java 請製作一只DES(DataEncryptionStandard)密碼系統加密/解密功能的雛形工具,系統允許使用者輸入明文與產生鑰匙元素後,即顯示加密後密文,以及解密後明文,操作介面如下: D:\Java1_book\chap6>javac-encodingutf8Ex6_7.java   D:\Java1_book\chap6>javaEx6_7 請輸入明文=>大家恭喜、新年快樂 請輸入密碼元素(8個字元)=>12345678 密碼元素:12345678 明文:大家恭喜、新年快樂 加密後密文:h\吘$:?!廄礓v?JX5Q? 解密後明文:大家恭喜、新年快樂  (B)製作技巧提示 要將DES密碼系統演算法轉換為程式,是一件不容易的工作,我們可利用Javax.crypto套件下的類別程式來完成。

(C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 //Ex6_7DES加密/解密程式   importjava.security.SecureRandom;  importjava.util.Scanner; importjavax.crypto.Cipher;  importjavax.crypto.SecretKey;  importjavax.crypto.SecretKeyFactory;  importjavax.crypto.spec.DESKeySpec;    publicclassEx6_7{       publicstaticvoidmain(String[]args){             Scannerkeyin=newScanner(System.in);          System.out.print("請輸入明文=>");        Stringplain=keyin.nextLine();             System.out.print("請輸入密碼元素(8個字元)=>");        Stringkey=keyin.nextLine();        System.out.println("密碼元素:"+key);         System.out.println("明文:"+plain);         byte[]cipher=encrypt(plain,key);         System.out.println("加密後密文:"+newString(cipher));         Stringcipher_n=decrypt(cipher,key);         System.out.println("解密後明文:"+cipher_n);     }       //DES加密程式    publicstaticbyte[]encrypt(Stringplain,Stringkey){         try{             SecureRandomrandom=newSecureRandom();             DESKeySpecdesKey=newDESKeySpec(key.getBytes());             SecretKeyFactorykeyFactory=SecretKeyFactory.getInstance("DES");             SecretKeysecurekey=keyFactory.generateSecret(desKey);             Ciphercipher=Cipher.getInstance("DES");             cipher.init(Cipher.ENCRYPT_MODE,securekey,random);             byte[]result=cipher.doFinal(plain.getBytes());             returnresult;         }catch(Throwablee){             e.printStackTrace();         }         returnnull;     }       //解密程式    publicstaticStringdecrypt(byte[]content,Stringkey){         try{             SecureRandomrandom=newSecureRandom();             DESKeySpecdesKey=newDESKeySpec(key.getBytes());             SecretKeyFactorykeyFactory=SecretKeyFactory.getInstance("DES");             SecretKeysecurekey=keyFactory.generateSecret(desKey);             Ciphercipher=Cipher.getInstance("DES");             cipher.init(Cipher.DECRYPT_MODE,securekey,random);             byte[]result=cipher.doFinal(content);             returnnewString(result);         }catch(Throwablee){             e.printStackTrace();         }         returnnull;     }  }  6-6-2範例研討:產生RSA鑰匙配對程式 (A)程式功能:Ex6_8.java 請製作一套1024位元的RSA鑰匙配對產生工具,每次執行時會產生不同的鑰匙配對(公開鑰匙與私有鑰匙),期望操作介面如下: D:\Java1_book\chap6\RSA>javac-encodingutf8Ex6_8.java   D:\Java1_book\chap6\RSA>javaEx6_8 產生RSA鑰匙配對中 將鑰匙配對寫入檔案,並顯示於螢幕 PublicKey:30819f300d06092a864886f70d010101050003818d003081890281810094be1274ff cd65be48bc02a96fabf8bc5a614b715ff24bdf46afddca2ae5f3ab24a32bc6304699bdb92fe594a9 98e917320e2b2174c4a4a43f216acfdd4533c87e8019e46556cc572edde97b26b91416bc5777795b 90e9d44ebd979638c0acaa0a1842d6252c9d11e157ede3eb0b82cba138d9f3390cb917bcd88f8fb6 92c92d0203010001 PrivateKey:30820275020100300d06092a864886f70d01010105000482025f3082025b0201000 281810094be1274ffcd65be48bc02a96fabf8bc5a614b715ff24bdf46afddca2ae5f3ab24a32bc63 04699bdb92fe594a998e917320e2b2174c4a4a43f216acfdd4533c87e8019e46556cc572edde97b2 6b91416bc5777795b90e9d44ebd979638c0acaa0a1842d6252c9d11e157ede3eb0b82cba138d9f33 90cb917bcd88f8fb692c92d02030100010281802056525ced60124694398bba9a74a0d7122f24dfb ….. ….. 由檔案讀出RSA鑰匙配對,並顯示於螢幕 PublicKey:30819f300d06092a864886f70d010101050003818d003081890281810094be1274ff cd65be48bc02a96fabf8bc5a614b715ff24bdf46afddca2ae5f3ab24a32bc6304699bdb92fe594a9 98e917320e2b2174c4a4a43f216acfdd4533c87e8019e46556cc572edde97b26b91416bc5777795b 90e9d44ebd979638c0acaa0a1842d6252c9d11e157ede3eb0b82cba138d9f3390cb917bcd88f8fb6 92c92d0203010001 PrivateKey:30820275020100300d06092a864886f70d01010105000482025f3082025b0201000 281810094be1274ffcd65be48bc02a96fabf8bc5a614b715ff24bdf46afddca2ae5f3ab24a32bc63 04699bdb92fe594a998e917320e2b2174c4a4a43f216acfdd4533c87e8019e46556cc572edde97b2 6b91416bc5777795b90e9d44ebd979638c0acaa0a1842d6252c9d11e157ede3eb0b82cba138d9f33 ……. …… D:\Java1_book\chap6\RSA>dir/b*.key private.key    //私有鑰匙檔案 public.key     //公開鑰匙檔案 (B)製作技巧提示 我們利用Java.scurity套件內,產生RSA鑰匙配對方法。

(C)程式範例: 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 //Ex6_8.java importjava.io.File; importjava.io.FileInputStream; importjava.io.FileOutputStream; importjava.io.IOException; importjava.security.KeyPair; importjava.security.KeyPairGenerator; importjava.security.SecureRandom; importjava.security.KeyFactory; importjava.security.NoSuchAlgorithmException; importjava.security.PrivateKey; importjava.security.PublicKey; importjava.security.spec.InvalidKeySpecException; importjava.security.spec.PKCS8EncodedKeySpec; importjava.security.spec.X509EncodedKeySpec;   publicclassEx6_8{                publicstaticvoidmain(String[]args){                myKeyPairadam=newmyKeyPair();                try{                        Stringpath=".";                        //Generatethekeypair(publickeyandprivatekey)                        KeyPairGeneratorkeygen=KeyPairGenerator.getInstance("RSA");                        SecureRandomrandom=newSecureRandom();                        //給與亂數因子,指定鑰匙長度,再產生鑰匙                        System.out.println("產生RSA鑰匙配對中");                        random.setSeed("seedVaule".getBytes());                        keygen.initialize(1024,random);          //Generate1024-bitkeys                        KeyPairgeneratedKeyPair=keygen.generateKeyPair();                        //儲存鑰匙配對                        System.out.println("將鑰匙配對寫入檔案,並顯示於螢幕");                        adam.dumpKeyPair(generatedKeyPair);       //Printthegeneratedkeys                        adam.SaveKeyPair(path,generatedKeyPair); //Storethekeysintotwofiles                        //讀取鑰匙配對                        System.out.println("\n由檔案讀出RSA鑰匙配對,並顯示於螢幕");                        KeyPairloadedKeyPair=                                        adam.LoadKeyPair(path,"RSA");    //Loadthekeysfromfiles                        adam.dumpKeyPair(loadedKeyPair);          //Printtheloadedkeys                }catch(Exceptione){                        e.printStackTrace();                        return;                }        } }   classmyKeyPair{        //列印鑰匙配對方法        publicvoiddumpKeyPair(KeyPairkeyPair){                PublicKeypub=keyPair.getPublic();                System.out.println("PublicKey:"+getHexString(pub.getEncoded()));                                PrivateKeypriv=keyPair.getPrivate();                System.out.println("PrivateKey:"+getHexString(priv.getEncoded()));                }                publicStringgetHexString(byte[]b){                StringBuilderresult=newStringBuilder();                for(inti=0;i



請為這篇文章評分?