程序設計與數據結構-問題庫

主目錄



第 00 周 - 預備做業 03 問題與解答

  • 【問題1】關於markdown格式,有些同窗的markdown中的標題沒有對齊,評論了以後也沒有修改,以下圖:


  • 解答 :這種排版錯誤,有兩種狀況:

① 上一部分的內容與下一個標題之間沒有空行,因爲使用了-修飾文字,致使後面標題與前面的內容連在一塊兒,原格式以下:

## 1. 虛擬機的安裝
- XXXXXX
## 2. Linux命令
- XXXXXX
## 3. 感悟
- XXXXXX

效果以下:


1. 虛擬機的安裝

  • XXXXXX

    2. Linux命令

  • XXXXXX

    3. 感悟

  • XXXXXX



② 空行了可是下一行的前面空了四格,出現這種錯誤的同窗應該很少,原格式以下:

## 1. 虛擬機的安裝
- XXXXXX

    ## 2. Linux命令  //##前面空了四格
- XXXXXX

    ## 3. 感悟
- XXXXXX

效果以下:


1. 虛擬機的安裝

  • XXXXXX

    ## 2. Linux命令
  • XXXXXX

    ## 3. 感悟
  • XXXXXX


建議將原格式修改成:

## 1. 虛擬機的安裝

- XXXXXX



## 2. Linux命令

- XXXXXX



## 3. 感悟

- XXXXXX

  固然若是標題格式前面空了1~3格或者5格以上,也不會有修飾效果,能夠本身嘗試一下,因此標題修飾符前面不要加空格,各部分之間加幾個空行,原格式看着也比較舒展,markdown格式須要同窗們在之後的做業中慢慢體會,從一篇博客的markdown就能夠看出對待博客的態度!



  • 【問題2】安裝虛擬機時,ubuntu只有32位的選項,而沒有像流程中的那樣有64位的選項。在創建32位ubuntu時顯示:This kernel requires an x86-64 CPU,but only detected an i686 CPU.Unable to boot - please use a kernel appropriate for your CPU.

  • 解答 :在安裝虛擬機時選擇的是32位的,且沒有打開intel vt-x(虛擬化技術),i686是intel系列的CPU,是32位的,因此會提示這個問題。intel vt-x的好處就是能夠在32位的機器上虛擬出64位操做系統。修改BIOS配置,把virtualization參數改成enable便可:

    關於如何修改Inter Virtual Technology,能夠參考OracleVMVirtualBox不能建立64位的虛擬機辦法,也能夠參考這篇博客再瞭解一下。



  • 【問題3】在安裝Ubuntu的時候打開教程裏給的網址到最後下載的時候網頁老是顯示404 Not Found

  • 解答戳此連接去Ubuntu的中文官網下的系統軟件,能夠下載Ubuntu 16.04 LTS(長期支持)版本或者Ubuntu 17.04版本



  • 【問題4】使用sudo apt-get install Vim來安裝Vim的時候出現問題:E: 沒法定位軟件包

  • 解答 :沒法定位軟件包,主要是軟件源的問題(被封了,或者失效了),能夠先使用sudo apt-get update更新,或者能夠使用下面的命令更新,可是要注意路徑。
    etc/apt/source.list中更新軟件源:sudo gedit /etc/apt/source.list



  • 【問題5】在下載好了VirtualBox後裝Ubuntu系統的時候,運行到一半忽然彈出錯誤提示框:

    Host system reported disk full. VM execution is suspended. You can resume after freeing some space.

  • 解答 :電腦的磁盤文件類型是FAT32文件格式,而在FAT32下,單個文件的最大是4GB,不支持超過4GB的文件。NTFS和FAT32都是文件系統的一種,而NTFS相對FAT32推出的要晚,因此技術也就更先進,可是對於早期的系統,好比Windows95的支持,FAT32要更好,具體的區別有下面幾點:

    • NTFS能夠支持最大64G的單個文件和2048G的分區。FAT32支持最大4G的單個文件和32G的分區。
    • NTFS不須要整理磁盤碎片。
    • NTFS支持對分區、文件夾和文件的壓縮。
    • NTFS採用更小的簇,能更有效地管理硬盤空間,最大限度的避免磁盤空間浪費。
    • NTFS分區上,能夠爲共享資源、文件夾和文件設置訪問許可權限。比FAT32安全性要高不少。並且基於NTFS的WIN 2000/XP運行要快於基於FAT32的WIN 2000/XP;但在WIN 9X系統的兼容性方面,FAT32優於NTFS。

    把文件系統從FAT32升級到NTFS便可:

    1.單擊開始→運行。
    2.打開窗口之後,在光標的提示符下輸入「convert X:/FS:NTFS」,而後回車。注意在「convert」的後面有一個空格。
    3.接着系統會要求你輸入X盤的卷標,而後回車。(卷標在「個人電腦」中點X盤,而後看它的屬性能夠找到。)工做界面這樣就可簡單地轉換分區格式爲NTFS了。這個方法只用於FAT32轉爲NTFS,不能將NTFS轉爲FAT32
    4.重啓電腦,虛擬機的安裝問題得以解決。

    (引用自餘坤澎同窗的博客


  • 其餘問題詳見答疑論壇:https://group.cnblogs.com/pdds/

【返回目錄】



第 01 周 - 做業問題與解答

  • 【問題1】上傳到碼雲發現本身的文件位置不理想,想要修改就刪掉了碼雲上已上傳的文件,致使遠程和本地不一樣步,使得上傳出現問題。

  • 解答 :將本地(虛擬機上)同名文件刪除,git pull 而後可繼續上傳。



  • 【問題2】安裝插件時出現:沒法得到鎖 /var/lib/dpkg/lock -open (11: 資源暫時不可用)。

  • 解答 :參考ubuntu 解決「沒法得到鎖 /var/lib/dpkg/lock -open」的方法

    解決辦法以下:

    一、終端輸入 ps aux ,列出進程。找到含有apt-get的進程,直接sudo kill PID。

    二、強制解鎖,命令

    sudo rm /var/cache/apt/archives/lock
    sudo rm /var/lib/dpkg/lock
  • 此後若想從新安裝則可輸入sudo apt-get install XXX, 但此時又可能會提示 「E: dpkg 被中斷,您必須手工運行 sudo dpkg --configure -a 解決此問題」, 手工輸入 " sudo dpkg --configure -a" 後,若又出現 「依賴關係問題 - 仍未被配置」這一提示的話,直接運行 「sudo apt-get -f install」 便可。



  • 【問題3】用sudo apt-get install atom安裝atom時軟件包沒法定位

  • 解答 :輸入sudo add-apt-repository ppa:webupd8team/atom

    按一下回車鍵,等待一下子後sudo apt-get update,以後sudo apt-get install atom等待安裝便可。



  • 【問題4】腳本文件設置好之後沒法打開。

  • 解答 :參考:http://www.cnblogs.com/hester/p/5575658.html

    chmod命令用來改變文件的模式,給系統中全部用戶這個源文件的執行許可。

    而後咱們能夠直接經過指定源文件的位置來執行程序。

    咱們使用./來指示程序位於當前目錄。

    【附】若是用"./"+"腳本名"命令不能執行shell腳本,能夠試試換用 bash 腳本名 執行。



  • 【問題5】虛擬機忽然打不開,錯誤問題提示「不能打開一個新任務」。

  • 解答 :那是由於vboxdrv服務沒有安裝或沒有成功啓動,找到安裝目錄下的vboxdrv文件夾,如D:\Program\Files\Oracle\VirtualBox\drivers\vboxdrv,右擊VBoxDrv.inf,選安裝,而後重啓。從新安裝屢次後仍然提示打開錯誤,而且嘗試過兼容模式運行,管理員身份運行,從新安裝VBoxDrv.inf,或者能夠去官網從新安裝的最新版的5.2.6的版本,實測有效果。(下載地址:https://www.virtualbox.org/wiki/Downloads)

    若是仍是不行,卸載virtualbox,選擇下載vmware。



  • 【問題6】編寫好的東西push不上去。

  • 解答 :參考:http://blog.csdn.net/Lea__DongYang/article/details/78134882 ,從新執行git config命令配置用戶名和郵箱便可。



  • 【問題7】和問題一有些類似,關於git push上傳失敗:

  • 解答 :在碼雲新建過項目後複製連接到電腦本地git clone以後會在相應目錄下自動建立一個和項目名稱相同的目錄,要進入項目名稱目錄下上傳文件,git push纔不會顯示當前分支沒有對應的上游分支,而且上傳成功。



  • 【問題8】如何實現「虛擬機」和「物理機」直接的複製粘貼?

  • 解答 :參考:https://jingyan.baidu.com/article/cbf0e500f88a4f2eaa289338.html

    或者按照如下這種方式設置:



  • 其餘問題詳見答疑論壇:https://group.cnblogs.com/pdds/

【返回目錄】



第 02 周 - 做業問題與解答

  • 【問題1】在作PP2.4時以爲輸入的代碼沒有問題,可是爲何有一行的輸入會出現,可是不能輸入呢?

  • 解答 :把 collage = 那條語句再複製一條在它下面,再加一個nextLine。

    nextInt只讀取整數,並無讀取輸入進去的\n,也就是說後面的nextLine會讀取\n,但並不返回,會致使後面的一個語句顯示沒有讀取輸入,直接跳過了。

    參考:Scanner中nextLine()方法和next()方法的區別

    Java中關於nextInt()、next()和nextLine()的理解



  • 【問題2】爲何使用 final int 來定義變量而以後卻能夠改變該變量的值?

  • 解答 :後面改變了變量類型,若是直接寫zhengyeye = 2333是不能編譯的。運行的應該是以前編譯好的class文件。從新定義相同的變量會提示問題。



  • 【問題3】書中寫的類沒法單獨編譯運行:

  • 解答 :自定義的類只能編譯,須要在有main函數的類中建立對象調用。



  • 【問題4】類名以美圓開頭,但依舊沒法編譯?

  • 解答 :類名雖然能夠以美圓開頭,可是因爲類名和文件名要求一致文件名通常不容許以美圓開頭。文件名使用 $ 開頭有特殊的涵義:取變量值,致使文件名被自動修改成.java,上圖中以 $ 開頭的文件名自動變爲.java,最終結果致使類名和文件名不一致,因此會提示class xxx is not public ,should be declared in a file name xxx。



  • 【問題5】運行老師給的AutoCompileX.sh總顯示找不到文件。

  • 解答 :須要把文件移動到相應的目錄下進行操做纔可以使用對應的腳本文件。



  • 【問題6】1.2+2.4=3.5999999999999?

  • 解答 :因爲計算機程序設計環境中二進制和十進制的浮點數是有IEEE二進位浮點數算數標準表示的,致使計算時有誤差。



  • 【問題7】運算符的應用問題,寫成以下形式但運算時只計算了前面的減法而自動忽略了後面的乘法:

  • 解答 :未進行調整爲浮點小數,計算時將後面的結果自動變爲1,致使了錯誤的結果。



  • 【問題8】關於書上概念型問題:
    (1)字符型到底是什麼?
    (2)什麼是參數?
    (3)什麼是變量聲明?
    (4)請寫出程序中使用符號變量而不是它所表示的常數值的三個好處。

  • 解答 :(1)字符型量包括字符常量和字符變量。字符串常量是由一對雙引號括起的字符序列。字符變量的取值是字符常量,即單個字符。

    字符變量的類型說明符是char。字符變量類型說明的格式和書寫規則都與整型變量相同。

    (2)參數是當調用方法時傳遞給方法的數據。參數分爲實參和形參。方法名括號裏面的參數是形參,調用方法或者函數的括號裏面的是實參。

    (3)變量聲明肯定了一個變量名及該變量可存儲數據的類型。告訴編譯器在程序中使用了哪些變量,及這些變量的數據類型以及變量的長度,而後爲變量分配存儲空間。

    (4)a.經過給常量值賦予符號名,是程序代碼比直接使用常熟之更容易直接理解;b.常數值在整個程序中使不可變的;c.若是須要修改程序中的常量值,只需在聲明語句中修改一次該常量初始值。



  • 【問題9】轉義序列中的"\t"、"\n"、"\r"的做用不清楚

  • 解答 :仿照例2.4在程序中試用,可是剛開始的時候在System.out.println("Roses are red.")的開頭位置添加,結果"\n" 與 "\r"效果同樣,在聽過老師的講解和教學視頻的解析,明白二者在效果上是同樣的,可是在乎義上是不一致的,"\n"表示是單純的換行,"\r"表示是回車換行。

    \r與\n合起來就是回車換行的意思,回車是將光標移到當前行的行首;換行是將光標移到當前行的下一行,但仍是同一列,不會回到行首。它們合起來能夠將光標移到下一行的行首,也就是回車並換行。但在不一樣的系統中它們的功能也不太相同。好比在windows裏,\r\n表示回車換行;但在linux中\n就表明回車換行。這也是爲何在linux下用vim打開windows編輯的文件會發如今每一行尾都有個^M字符的緣由。



  • 【問題10】組合運算符與正常的運算符之間的區別

  • 解答 :在形式上組合運算符比正常的運算符在運用上更爲簡潔,在教學視頻上的講解,給出了更爲明確的解釋,例如一樣是"short s = 4" 後面用兩種不一樣的形式,"s = s +5"與"s +=5"倒是一個true,一個false。緣由在於開始的4是以兩個字節的存儲空間進行存儲,然後面的5以int的存儲空間進行的,爲4個字節,兩次運算,先相加在賦值,不能自動轉換。然後者是一次運算,左右兩邊的和賦值給左邊,能夠自動換行。



  • 【問題11】在編寫temp程序時,檢查了多遍編寫內容是沒有問題的,可是輸出時一直提示錯誤,有一個錯誤是一不當心刪掉了import的i,還有一個問題「須要class,interface或enum解決方案」不知道怎麼辦。

  • 解答 :主要是用非記事本編寫代碼文件,存在編碼格式轉換問題。從新先建一個記事本程序,而後把源代碼粘貼到該文件下,用javac 類名.java編譯,java 文件名運行該程序便可。這是因爲Java文件的編碼致使的問題。 一般使用「javac FirstSample.java」編譯UTF-8編碼的.java源文件。 沒有指定編碼參數encoding的狀況下,默認使用的是GBK編碼。 當編譯器用GBK編碼來編譯UTF-8文件時,就會把UTF-8編碼文件的3個字節的文件頭,按照GBK中漢字佔2字節、英文佔1字節的特性解碼成了「亂碼」的兩個漢字。 這個源文件應該是用記事本另存爲UTF-8編碼。

    參考:javac編譯提示錯誤須要爲 class、interface 或 enum



  • 【問題12】若是執行下列代碼,獲得的b的值是什麼?(注意過程)
int a=4;
int b=(a++)+(--a)+(++a);
  • 解答
    1.先算b1=(a++)
    2.b2=b1+(--a)
    3.b=b2+(++a)

    1.b1=a=4,a=a+1=5
    2.a=a-1=5-1=4,b2=b1+a=4+4=8
    3.a=a+1=4+1=5,b=b2+a=8+5=13

    自增自減符號的後綴能夠說是先把本來的變量值賦給結果值,再把原來的變量值+1或者-1,而前綴能夠說是先把變量值+1或者-1,而後再把新的出的變量值賦給結果值。這題中a就是變量值,b就是結果值。(摘自:於欣月同窗的精彩回答



  • 其餘問題詳見答疑論壇:https://group.cnblogs.com/pdds/

【返回目錄】


第 03 周 - 做業問題與解答



  • 【問題2】激活 IntelliJ IDEA 時修改Hosts文件提示沒有權限怎麼辦?

  • 解答 :參考:https://jingyan.baidu.com/article/8ebacdf0cf184b49f65cd50b.html?qq-pf-to=pcqq.group



  • 【問題3】安裝好IDEA以後從碼雲上克隆項目沒有反應?

  • 解答 :若是按clone後沒有反應,可進行以下嘗試:點擊左上角file,點擊settings,雙擊Version Control那一欄的小標誌,點擊git,在第一欄找到你下載的git.exe,而後點擊OK。再從新clone便可。



  • 【問題4】關於PP3.3電話號碼各部分首位沒法輸出0的解決方法:(格式化輸出)

  • 解答 :參考張旭升的代碼:(稍有改動)
import java.text.DecimalFormat;
import java.util.Random;
public class TelNum {
    public static void main(String[] args) {
        DecimalFormat decimalFormat = new DecimalFormat("000");
        DecimalFormat decimalFormat1 = new DecimalFormat("0000");
        Random random = new Random();

        int num = random.nextInt(8);
        int num1 = random.nextInt(8);
        int num2 = random.nextInt(8);
        int num3 = random.nextInt(656);
        int num4 = random.nextInt(10000);

        System.out.println("電話號碼:" + num + num1 + num2 + "-" + decimalFormat.format(num3) + "-" + decimalFormat1.format(num4));
    }
}
  • 補充問題:作習題3_3的時候雖然代碼上寫的可以輸出三位數字,但只能輸出兩位數字,甚至有時候只能輸出一位。

  • 解答:輸出時在前面沒有字符串的狀況下,系統自動把結果默認爲相加因此也就最多隻能輸出三位了,只要在前面加上字符串就默認後面的數是字符串了。



  • 【問題5】在有關將數字變成貨幣格式的時候,按照書中的例子作了,可是結果顯示的不是$而是¥。

  • 解答 :當初設置虛擬機時所選的地區是中國,因此它會轉化爲當地的貨幣符號。
    若是想要在中國地區顯示美圓符號$,先聲明一下import java.util.Locale;再把那一行代碼改爲:NumberFormat fmt1=NumberFormat.getCurrencyInstance(Locale.US);
    參考:http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/java/util/Locale.html
    https://zhidao.baidu.com/question/552422997551378132.html

    最後的輸出結果以下:



  • 【問題6】爲何用 public 修飾類名時文件名與類名相同?

  • 解答 :參考:https://www.cnblogs.com/baby-zhude/p/7918724.html



  • 【問題7】爲何String不須要顯式地導入到程序中?

  • 解答 :String屬於lang類,有如下幾種:
    一、String,八種基本數據類型的包裝類都在這個包中;
    二、Object:類層次結構的根類;
    三、Math:執行基本數學方法運算;
    四、StringBuffer:線程安全的可變字符序列;
    五、thread:是程序中的執行線程。Java虛擬機容許應用程序併發地運行多個執行線程。



  • 【問題8】如何將虛擬機中bin文件夾上傳到碼雲?

  • 解答 :能夠設置不忽略.class文件。這樣就能夠把bin文件夾和class文件上傳上去。

    參考:Git忽略規則.gitignore梳理



  • 【問題9】如何使用JDK API?

  • 解答 :參考:https://blog.csdn.net/l4432321/article/details/52600426



  • 【問題10】空字符串和空引用的區別?

  • 解答

    空字符串「」:
    一、類型:「」是一個空字符串(String),長度爲0,佔內存,在內存中分配一個空間,能夠使用Object對象中的方法。(例如:「」.toString()等)
    二、內存分配:表示聲明一個字符串類型的引用,其值爲「」空字符串,這個引用指向str1的內存空間。

    空引用null:
    一、類型:null是空引用,表示一個對象的值,沒有分配內存,調用null的字符串的方法會拋出空指針異常。(例如:str1.endsWith(str2); java.lang.NullPointerException)
    二、內存分配:表示聲明一個字符串對象的引用,但指向null,也就是說沒有指向任何內存空間。

  • 例:
String str1 = ""; //str1對應一個空串,聲明對象的引用
String str2 = null; //str2引用爲空
String str3 = new String(); //str3將指向具體的String實例,默認值爲「」





  • 【問題12】格式化輸出中的DecimalFormat類「#」和「0」的區別?

  • 解答:針對DecimalFormat類的「#」和「0」的區別,試了好幾回,而且每次運用的「#」和「0」的長度也不一樣,其中「#」的做用表示該位無數字則自動省略,「0」表示該位無數字則補零。兩種都要進行四捨五入,進行保留。並且書中的例題頗有意思,其中的「The circle's area:78.5398」在格式化爲「0.####」若是爲「0.###」的時候,8進位,9變10結果應該爲78.530,但因爲「#」的做用使得末尾的0去掉了。

    參考:https://www.cnblogs.com/yelongsan/p/5482774.html

    「#」:若是該位四捨五入後數字爲0,那麼就省略這個0,
    「0」:若是該位四捨五入後沒有數字,那麼就自動補0。



  • 其餘問題詳見答疑論壇:https://group.cnblogs.com/pdds/

【返回目錄】


第 04 周 - 做業問題與解答

  • 【問題1】如何理解靜態變量,靜態方法和靜態類?

  • 解答 :靜態變量由全部實例共享。靜態方法能夠經過類名稱來調用。main方法只能訪問靜態變量或局部變量。

    靜態變量有兩種狀況:
    靜態變量是基本數據類型,這種狀況下在類的外部沒必要建立該類的實例就能夠直接使用
    靜態變量是一個引用。這種狀況比較特殊,主要問題是因爲靜態變量是一個對象的引用,那麼必須初始化這個對象以後才能將引用指向它。
    所以若是要把一個引用定義成static的,就必須在定義的時候就對其對象進行初始化。

    靜態方法:與類變量不一樣,方法(靜態方法與實例方法)在內存中只有一份,不管該類有多少個實例,都共用一個方法。
    靜態方法與實例方法的不一樣主要有:
    靜態方法能夠直接使用,而實例方法必須在類實例化以後經過對象來調用。

    在外部調用靜態方法時,能夠使用類名.方法名或者對象名.方法名的形式。實例方法只能使用後面這種方式。
    靜態方法只容許訪問靜態成員。而實例方法中能夠訪問靜態成員和實例成員。
    靜態方法中不能使用this(由於this是與實例相關的)。

    關於靜態類,參考:http://blog.sina.com.cn/s/blog_605f5b4f0100zbps.html
    靜態類僅包含靜態成員,不能被實例化,靜態變量能夠由全部的類實例共享,靜態方法能夠經過類名稱調用。靜態類是密封的,所以不可被繼承。靜態類不能包含構造函數,但仍可聲明靜態構造函數以分配初始值或設置某個靜態狀態。

  • 【附】實例變量和靜態變量的區別?

    靜態變量也叫類變量,這種變量前加了static修飾符。能夠直接用類名調用,也能夠用對象調用,並且全部對象的同一個類變量 都是共享同一塊內存空間。
    實例變量也叫對象變量,這種變量沒有加static修飾符。只能經過對象調用, 並且全部對象的同一個實例變量是共享不一樣的內存空間的。

    靜態變量是全部對象共有的,某一個對象將它的值改變了,其餘對象再去獲取它的值,獲得的是改變後的值;

    實例變量則是每個對象私有的,某一個對象將它的值改變了,不影響其餘對象取值的結果,其餘對象仍會獲得實例變量一開始就被賦予的值。



  • 【問題2】如何使用return語句?return與void的關係?

  • 解答 :方法的返回值類型必須與方法聲明首部中規定的返回值類型一致。當方法不返回任何值時,用void做爲返回值類型。一條return語句由保留字return和後續的可選表達式組成。執行return語句時,控制當即返回到調用方法,並返回表達定義式的返回值。

    每個方法中能夠有多個return,但並非返回的屢次,而是在不一樣狀況下進行的返回。同時,在構造方法中沒有返回值。不返回值的方法一般不包含return語句,當 該方法執行結束時將自動返回調用方法。



  • 【問題3】如何理解「接口」?

  • 解答 :對於接口,是一組常量和抽象方法的集合,抽象方法是指沒有實現的方法,即沒有代碼體,接口中沒有實現的方法,參數列表的方法聲明頭後面僅跟着分號。接口不能被實例化,類經過實現定義在接口中的每一個抽象方法來實現這個接口,實現接口的類需在類聲明頭部使用保留字implements,再給出接口名,類中必須實現至少一個接口中的抽象方法,同時也能夠定義其餘方法。多個類能夠實現同一個接口,一個類也能夠實現多個接口。實現一個接口的類時,在接口中能夠定義額外的方法。示例爲一個簡單的接口:
public interface Nameable
{
     public static setName(String Name);
     public String getName();
}



  • 【問題4】爲何非要去寫一個接口?

  • 解答 :接口的應用,大大提升了方法步驟的靈活性。

    「接口是個規範」,這句沒錯。「不如直接就在這個類中寫實現方法豈不是更便捷」,你怎麼保證這個接口就一個類去實現呢?若是多個類去實現同一個接口,程序怎麼知道他們是有關聯的呢?既然不是一個類去實現,那就是有不少地方有用到,你們須要統一標準。甚至有的編程語言(Object-C)已經不把接口叫 interface,直接叫 protocol。統一標準的目的,是你們都知道這個是作什麼的,可是具體不用知道具體怎麼作。好比說:我知道 Comparable 這個接口是用來比較兩個對象的,那麼如何去比較呢?數字有數字的比較方法,字符串有字符串的比較方法,學生(本身定義的類)也有本身的比較方法。而後,在另一個負責對象排序(不必定是數字喔)的代碼裏面,確定須要將兩個對象比較。這兩個對象是什麼類型呢?Object a,b?確定不行,a > b 這樣的語法沒法經過編譯。int a,b?也不行?一開始就說了,不必定是數字。....因此,Comparable 就來了。他告訴編譯器,a b 兩個對象都知足 Comparable 接口,也就是他們是能夠進行比較的。具體怎麼比較,這段程序不須要知道。因此,他須要一些具體的實現,Comparable 接口有一個方法,叫 compareTo。那麼這個方法就是用來取代 <、> 這樣的運算符。由於運算符是編譯器保留給內置類型(整數、浮點數)進行比較用的,而不是一個廣義的比較運算。若是你能夠明白 JDK 自身庫裏面諸如 Comparable 這樣已經有的接口,那麼就很容易理解本身在開發程序的時候爲何須要用到接口了。

    四點關於JAVA中接口存在的意義:
    一、重要性:在Java語言中, abstract class 和interface 是支持抽象類定義的兩種機制。正是因爲這兩種機制的存在,才賦予了Java強大的 面向對象能力。
    二、簡單、規範性:若是一個項目比較龐大,那麼就須要一個能理清全部業務的架構師來定義一些主要的接口,這些接口不只告訴開發人員你須要實現那些業務,並且也將命名規範限制住了(防止一些開發人員隨便命名致使別的程序員沒法看明白)。
    三、維護、拓展性:好比你要作一個畫板程序,其中裏面有一個面板類,主要負責繪畫功能,而後你就這樣定義了這個類。但是在不久未來,你忽然發現這個類知足不了你了,而後你又要從新設計這個類,更糟糕是你可能要放棄這個類,那麼其餘地方可能有引用他,這樣修改起來很麻煩。若是你一開始定義一個接口,把繪製功能放在接口裏,而後定義類時實現這個接口,而後你只要用這個接口去引用實現它的類就好了,之後要換的話只不過是引用另外一個類而已,這樣就達到維護、拓展的方便性。
    四、安全、嚴密性:接口是實現軟件鬆耦合的重要手段,它描敘了系統對外的全部服務,而不涉及任何具體的實現細節。這樣就比較安全、嚴密一些(通常軟件服務商考慮的比較多)。



  • 【問題5】對於調用toString方法不是很理解,不調用也能完成輸出,爲何非要去調用它?

  • 解答 :用System.out.println()輸出一個對象的時候,java默認調用對象的toString()方法。通常你要覆蓋這個方法,這樣根據覆蓋邏輯你就能夠輸出本身的對象。好比你定義一個類User,有id,name屬性,你直接輸出一個user對象的話System.out.println(user),獲得的只是全限定名 @ 地址首地址 。若是你在User類裏面覆蓋這個toString方法的話就能輸出你要的。

    若是一個java對象改寫了toString方法,就不會打印出內存地址,而是直接調用了他的toString方法。在源碼中,好比System.out.println()方法,用它來打印一個對象。它會首先判斷一下該對象是否爲null,若是爲null,就直接打印出一個null的字符串。若是不爲null,就自動調用該對象的toString方法。因此,若是改寫了toString,就會直接調用toString方法了。若是沒有,就是調用父類Object中的toString方法,也就是打印出內存地址。

    能夠繼續參考侯澤洋同窗這篇博客中的教材問題1和代碼問題2進一步瞭解。



  • 【問題6】在作PP4.2,編寫bulb類的時候爲何會輸出一段亂碼?(能夠當成對問題5的補充)

  • 解答 :你的對象沒有重寫這個方法的時候調用會輸出地址!你的對象須要被打印或者需以某種方式轉換爲字符串時就須要重寫方法!由於你不少時候都會去作一個轉換或者打印的操做因此最好重寫一下。

    可繼續參考:每一個Java類都有的toString方法



  • 【問題7】普通方法和構造方法的區別?

  • 解答 :1. 構造函數的命名必須和類名徹底相同;在java中普通函數能夠和構造函數同名,可是必須帶有返回值。
  1. 構造函數的功能主要用於在類的對象建立時定義初始化的狀態。它沒有返回值,也不能用void來修飾。這就保證了它不只什麼也不用自動返回,並且根本不能有任何選擇。而其餘方法都有返回值。即便是 void 返回值,儘管方法體自己不會自動返回什麼,但仍然可讓它返回一些東西,而這些東西多是不安全的。
  2. 構造函數不能被直接調用,必須經過new運算符在建立對象時纔會自動調用,通常方法在程序執行到它的時候被調用。
  3. 當定義一個類的時候,一般狀況下都會顯示該類的構造函數,並在函數中指定初始化的工做也可省略,不過Java編譯器會提供一個默認的構造函數。此默認構造函數是不帶參數的,而通常方法不存在這一特色。

    構造方法是建立對象時自動調用的,普通方法須要對象去調用,只要建立對象就必定會調用構造方法,能夠顯式的指定某個構造方法,若是不指定就調用默認的。



  • 【問題8】形式參數和實際參數的區別?

  • 解答 :形式參數是函數定義中的,系統沒有爲其分配內存空間,可是在定義裏面能夠使用的參數。例如:fun(int a)。這裏a就是形式參數。
    實際參數是函數調用的時候傳給函數的變量。這個是系統實實在在分配了內存空間的變量。
    簡單點說,就是形式參數給個形式,實際參數放進去用。例如:fun(a);
    函數聲明的用處是告訴編譯器聲明的函數在後面有定義。若是你將函數定義放在調用的前面,就不須要聲明。另外聲明就是函數定義後面加上分號的形式。
    例如:定義是fun(int a),聲明就是fun(int a);

    可參考:形參和實參的區別







  • 【問題11】在作例4.3-例4.4時,Account.java編譯成功後,運行時出現如圖所示的狀況。

  • 解答 :編輯Account.java的目的是定義一個Account類,使Transaction類能夠運用其中定義的方法從而順利運行,因此Account類不須要main方法,因此單獨編譯此Java文件會出現如此錯誤提示。



  • 【問題12】在編寫課堂做業即pp47的時候,編寫的book類能夠運行成功,可是在Java編譯的時候顯示的就是null.

  • 解答 :編寫的類變量和定義方法(構造函數)的參數名字是同樣的致使錯誤最終輸出null,因而改成this。參考課本第七章對於this的引用,this引用是能夠容許對象引用本身的,並且this引用還能夠引用於當前正在運行的對象。

    在上述構造方法中,this引用特指對象的實例變量,賦值語句右邊的變量是構造方法的形參變量。
    這種方法避免了對含義相同的變量要給出不一樣命名以示區別的問題。有時,這種狀況發生在其餘的方法中,但更常常出如今構造方法中。



  • 其餘問題詳見答疑論壇:https://group.cnblogs.com/pdds/

【返回目錄】


第 05 周 - 做業問題與解答

  • 【問題1】===的區別?

  • 解答=是賦值,== 是判斷,輸出的是 boolean 結果——true、false。





  • 【問題3】Java中幾種循環語句各有什麼特色?

  • 解答 :①while循環(先判斷,執行0次或者屢次);②do循環(至少執行一次後再判斷);③for循環(先判斷,循環次數肯定或者容易計算)④for-each循環((迭代器)簡單的處理對象中的各項元素)


    (上圖還添加了 switch 語句)







  • 【問題6】若是兩個字符串,長度不一樣,多個對應位置索引處的字符不一樣,compareTo如何比較?

  • 解答 :字符和字符串的比較以Unicode字符集爲基礎。這種比較稱爲字典順序比較。而其只比較第一個字符,若是不一樣則其後再也不比較。

    compareTo() 的返回值是int, 它是先比較對應字符的大小(ASCII碼順序)
    一、若是字符串相等返回值0
    二、若是第一個字符和參數的第一個字符不等,結束比較,返回他們之間的差值(ascii碼值)(負值前字符串的值小於後字符串,正值前字符串大於後字符串)
    三、若是第一個字符和參數的第一個字符相等,則以第二個字符和參數的第二個字符作比較,以此類推,直至比較的字符或被比較的字符有一方全比較完,這時就比較字符的長度。

    可參考:java中的compareto方法的詳細介紹ASCII經常使用對照表





  • 【問題8】不理解循環語句中 break 與 continue 的區別?

  • 解答 :break和continue都是用來控制循環結構的,主要是中止循環。

    (1)break:

    有時候咱們想在某種條件出現的時候終止循環而不是等到循環條件爲false才終止。這時咱們能夠使用break來完成。break用於徹底結束一個循環,跳出循環體執行循環後面的語句。

    (2)continue:

    continue和break有點相似,區別在於continue只是終止本次循環,接着還執行後面的循環,break則徹底終止循環。能夠理解爲continue是跳過當次循環中剩下的語句,執行下一次循環。

    可參考:(1)break和continue的區別

    (2)循環中 break 與 continue 的區別

    (3)for循環裏面break和continue的區別



  • 【問題9】關於pp5.7只能進行一次,不能讓遊戲繼續下去的問題?

  • 解答 :以前已經提過nextInt()方法與nextLine()的區別,再總結一遍:

    nextInt()讀取一個鍵盤獲取的數字以後焦點並不會移動到下一行,這時候若是下面語句中跟了一句nextLine()的話就讀不到輸入的內容了。由於nextLine()是遇到換行符結束讀取,nextInt()讀取的內容尚未換行,因此緊跟着nextInt()的nextLine()就只是讀取到了最後的換行符。因此並無接收到在上述程序中的y/n。

    參考:Scanner中nextLine()方法和next()方法的區別Java中關於nextInt()、next()和nextLine()的理解





  • 其餘問題詳見答疑論壇:https://group.cnblogs.com/pdds/

【返回目錄】


第 06 周 - 做業問題與解答

  • 【問題1】關於foreach循環方式不太熟悉?foreach語句和for語句的比較?

  • 解答 :參考java中for循環的幾種方式深刻理解java中for和foreach循環

    (1).若是隻是遍歷集合或者數組,用foreach好些,快些。

    (2).若是對集合中的值進行修改,就要用for循環了。其實foreach的內部原理其實也是Iterator,但它不能像Iterator同樣能夠人爲的控制,並且也不能調用iterator.remove();更不能使用下標來訪問每一個元素,因此不能用於增長,刪除等複雜的操做。

    (3).總的來講,當你想要對不少變量進行相同的操做時,foreach是較爲簡單快捷的;而當你想要更加精確具體的控制不少變量進行不一樣操做時,for語句將會是更好的選擇。



  • 【問題2】虛擬機登陸後藍屏怎麼解決?

  • 解答 :首先, 按下Ctrl + Alt + F4 進入一個界面。輸入用戶名和密碼,進入root模式。

    而後,須要安裝相應的服務而後重置。

    sudo apt-get install xserver-xorg-lts-utopic

    sudo dpkg-reconfigure xserver-xorg-lts-utopic

    reboot

    若是前面第一個操做有問題,須要重置 dpkg 後再試 sudo dpkg --configure -a

    可參考:Ubuntu 登陸後圖形化界面藍屏問題



  • 【問題3】爲何數組的索引值的從0開始的?

  • 解答 :一、數組在內存中申請是,所申請的內存是一段連續的內存地址;

    二、例:int[] a=new int[3];申請一段:int 數據類型的數組,a 爲變量,數組長度爲:[3];

    三、這個數組所申請的內存地址是連續的(假設所申請的:第一個內存地址爲:1008,第二個爲:1009,第三個爲:1010);,但咱們只知道:1、變量:a,它只拿到第一個內存地址1008;2、它的數組空間爲3個;

    四、a[0]——把a拿到的內存地址:1008 + 0 = 1008 (指向第一個內存地址);
    a[1]——把a拿到的內存地址:1008 + 1 = 1009 (指向第二個內存地址);
    a[2]——把a拿到的內存地址:1008 + 2 = 1010 (指向第三個內存地址);

    因此:數據下標從 [0] 開始的意義也在於此!

    可參考:爲何數組是從0開始的



  • 【問題4】parseInt 方法在將後面的字符轉換爲數值類型時要如何使用?

  • 解答 :1.基本用法(只接受一個參數,能夠當作第二個參數默認是10):parseInt的返回值只有兩種可能,不是一個十進制整數,就是NaN。
    a.將字符串轉爲整數。
parseInt('123') // 123

b.若是字符串頭部有空格,空格會被自動去除。

parseInt(' 81') // 81

c.若是parseInt的參數不是字符串,則會先轉爲字符串再轉換。這個很重要
d.字符串轉爲整數的時候,是一個個字符依次轉換,若是遇到不能轉爲數字的字符,就再也不進行下去,返回已經轉好的部分。
e.若是字符串的第一個字符不能轉化爲數字(後面跟着數字的正負號除外),返回NaN。
f.若是字符串以0x或0X開頭,parseInt會將其按照十六進制數解析。

parseInt('0x10') // 16

g.若是字符串以0開頭,將其按照10進制解析。

parseInt('011') // 11

h.若是參數以0開頭,但不是字符串,則會先將數值轉成字符串,而後解析,見規則c

parseInt(011) // 9

i.對於那些會自動轉爲科學計數法的數字,parseInt會將科學計數法的表示方法視爲字符串,所以致使一些奇怪的結果。

parseInt(1000000000000000000000.5) // 1
// 等同於
parseInt('1e+21') // 1
parseInt(0.0000008) // 8
// 等同於
parseInt('8e-7') // 8
2.進制轉換(接收兩個參數):parseInt方法還能夠接受第二個參數(2到36之間),表示被解析的值的進制,返回該值對應的十進制數。默認狀況下,parseInt的第二個參數爲10,即默認是十進制轉十進制。

a.第一個參數解析規則參照第一條基本用法
b.若是第二個參數不是數值,會被自動轉爲一個整數。這個整數只有在2到36之間,才能獲得有意義的結果,超出這個範圍,則返回NaN。若是第二個參數是0、undefined和null,則直接忽略。



  • 【問題5】類/對象/變量/參數的含義?區別?聯繫?

  • 解答 :類:類是組成java程序的基本要素,它封裝了一類對象的屬性和方法。

    對象:類是建立對象的模板,當使用一個類建立了一個對象時,也就是說給出了這個類的一個實例。

    變量:區別於常量的一種可變數據。java中的三大變量是靜態變量、實例變量和局部變量。局部變量就是本地變量,在方法、構造器或者塊中使用,在方法、構造器或者塊進入時被建立。實例變量在類中聲明,可是它在方法、構造器以外。靜態變量在類中用static關鍵字聲明,可是它在方法、構造器或者塊以外。

    參數:參數分兩種,一種叫形參,一種叫實參。在方法名後面括號裏面用逗號分開的就是形參。當方法沒有參數時,若是想要使用這個方法的話必須在調用這個方法時給它傳遞形參的實際值(這就是實參)

    聯繫:

    (圖片來自範雯琪同窗的博客









  • 【問題9】例題8.3中字符之間相減怎麼理解?

  • 解答 :例題8.3部分代碼以下:
for (int ch = 0;ch<line.length();ch++)
        {
            current = line.charAt(ch);
            if (current>='A' && current<='Z')
                upper[current-'A']++;
            else
                if (current>='a' && current<='z')
                    lower[current-'a']++;
                else
                    other++;
        }

首先在char中,對應的不是理解中的字母,而是Unicode碼,例如A是65,因此是減去A對應着減去其uincode碼。從中能夠鎖定句中的字母的索引。而又已知的是數組默認值爲0,因此,若是有相應字母,那麼經過upper[]++來增長對應索引的內容。
對應的,在輸出時,有:

// Print the results
    System.out.println();
    for (int letter=0; letter < upper.length;letter++)
    {   
       System.out.print((char)(letter + 'A'));
       System.out.print(": " + upper[letter]);
       System.out.print("\t\t" + (char)(letter + 'a'));
       System.out.print(":" + lower[letter]);
    }

繼續利用Unicode碼,從A開始,A爲65,則對應的letter從0開始。能夠輕易的將數字轉化爲字符。



  • 【問題10】如何理解書上的這句話:

    將一個數組做爲參數的方法能夠實際改變改數組元素,由於該方法引用的是原始數組的元素值。但該方法不能改變數組引用自己,由於它接受的參數是原始數據引用的副本。這個規則與管理任何對象類型的規則一致。

  • 解答 :使用值傳參(pass_by_value)的方式來傳遞函數參數,只是值傳遞方式在處理原始數據類型參數與引用類型參數時候有不一樣,若是一個參數是原始數據類型,那麼參數變量的值傳遞進去。若是是引用類型,是傳進了引用變量的值(也就是說,只是將指向數據的引用的值給傳進去了,也就是被調用的函數新建的空間放的是這個引用的值,那麼也就是也指向了數組存在的內存),因此一樣是值傳遞,引用類型的傳入的固然是引用變量的值,指向了同一數組,那麼函數內對數組進行的修改在函數退出後依舊是有效的。

    可參考:Java 一維數組做爲參數和返回值java 值傳遞 數組傳遞



  • 其餘問題詳見答疑論壇或雲班課:https://group.cnblogs.com/pdds/

【返回目錄】


第 07 周 - 做業問題與解答

  • 【問題1】Java 四種可見性修飾符的類型和區別、非可見性修飾符的特色?

  • 解答 :(Java 修飾符主要分爲可見性和非可見性修飾符(又稱訪問修飾符和非訪問修飾符))
    四種可見性修飾符可參考Java中訪問修飾符public、private、protect、default範圍
    public:被聲明爲 public 的類、方法、構造方法和接口可以被任何其餘類訪問。因爲類的繼承性,類全部的公有方法和變量都能被其子類繼承。
    private:私有訪問修飾符是最嚴格的訪問級別,因此被聲明爲 private 的方法、變量和構造方法只能被所屬類訪問,而且類和接口不能聲明爲 private。
    protected:當父類和子類在同一個包中時,被聲明爲 protected 的變量、方法能被同一個包中的任何其餘類訪問;當父類和子類不在同一個包中時,子類實例能夠訪問其從父類繼承而來的 protected 方法,而不能訪問父類實例的protected方法。
    default:在同一包內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。

    非可見性修飾符已學的有三種:

    static:用於聲明靜態變量或靜態方法。
    final:final 變量能被顯式地初始化而且只能初始化一次。類中的 final 方法能夠被子類繼承,可是不能被子類修改。
    abstract:抽象類不能用來實例化對象,聲明抽象類的惟一目的是爲了未來對該類進行擴充。

    關於權限修飾符還要注意幾個問題:

    1.並非每一個修飾符均可以修飾類(指外部類),只有public和default能夠;

    2.全部修飾符均可以修飾數據成員,方法成員,構造方法;

    3.爲了代碼安全起見,修飾符不要儘可能使用權限大的,而是適用便可。好比,數據成員,若是沒有特殊須要,儘量用private。增強封裝性;

    4.修飾符修飾的是「被訪問」的權限。



  • 【問題2】super.message();super(message);的區別?

  • 解答super.message();是調用父類的方法而且這裏的message是方法名,super(message);是調用父類的構造方法而且這裏的message是形參名。



  • 【問題3】接口類與抽象類的區別?

  • 解答 :(參考王老師的上課講義)
    接口類:常量 + 抽象方法
    抽象類:常量/變量 + 抽象/非抽象方法(Notes:抽象類能夠不包含抽象方法)

    和接口類同樣,抽象類不能被實例化!(包含未實現的方法)
    和接口類不一樣,抽象類中的方法必須使用abstract修飾。(接口中全部方法都是抽象的,能夠省略abstract,也能夠使用!)

    //接口類
    public interface Complexity{
      public void setComplexity(int complexity);//抽象方法
      public int getComplexity();//抽象方法
    }
    //抽象類
    public abstract Complexity{
      private int reality;
      public abstract void setComplexity(int complexity);//抽象方法
      public int getComplexity(){//非抽象方法
      return reality;
          }
    }

    可參考:深刻理解Java的接口和抽象類Java中的抽象類



  • 【問題4】super 引用時爲何出現錯誤?

  • 解答 : 父類的構造方法中包括參數,則參數列表爲必選項,用於指定父類構造方法的入口參數。
    由於前面的父類構造方法包含了參數列表,因此引用時須要鍵入全部的訪問變量以此來指定父類構造方法中的參數。



  • 【問題5】代碼編譯時沒法經過?

  • 解答 :該類是子類,若是子類建立構造方法的話,那麼須要用super語句把父類的構建方法也輸入,(主要是把父類的對象也初始化),不然會有錯誤。而且必定要注意,super語句要放在第一行。



  • 【問題6】super 和 this 的異同?

  • 解答











  • 其餘問題詳見答疑論壇或雲班課:https://group.cnblogs.com/pdds/

【返回目錄】


第 08 周 - 做業問題與解答



  • 【問題2】關於後綁定(動態綁定)已經前綁定(靜態綁定)的理解和比較?

  • 解答 :參考java — 靜態綁定和動態綁定Java靜態綁定與動態綁定

    <1>前期綁定就是說在編譯過程當中就已經知道這個方法究竟是哪一個類中的方法,此時由編譯器或其它鏈接程序實現。java當中的方法只有final,static,private和構造方法是前期綁定。

    <2>後期綁定是在運行時根據具體對象的類型進行綁定。動態綁定的過程:
    1.虛擬機提取對象的實際類型的方法表;
    2.虛擬機搜索方法簽名;
    3.調用方法。









public class Polymorphism {
public static void main(String[] args) {
//既然是多態,java 中重載和重寫都是多態的體現,你問的這句話確定不屬於重載則用重寫來解釋
// 這裏聲明瞭一把槍,變量爲gun,但他卻指向了一把Ak47對象,也就是說 gun雖然是Gun的引用,但實際是一個Ak47對象
//那麼gun.shot其實調用的是Ak47.shot 而不是Gun本身的shot
Gun gun = new Ak47();
gun.shot();
}
}
class Gun {
public void shot() {
System.out.println("突!");
}
}
class Ak47 extends Gun {
public void shot() {
System.out.println("突!突!突!突!突!");
}
}

多態機制遵循的原則歸納爲:當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,可是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法,可是它仍然要根據繼承鏈中方法調用的優先級來確認方法,該優先級爲:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。







  • 其餘問題詳見答疑論壇或雲班課:https://group.cnblogs.com/pdds/

【返回目錄】


第 09 周 - 做業問題與解答

  • 【問題1】異常中throw和throws區別?

  • 解答 :參考throws和throw拋出異常的使用規則

    throw是語句拋出一個異常。 語法:throw (異常對象);

    throws是方法可能拋出異常的聲明。(用在聲明方法時,表示該方法可能要拋出異常)。

    語法:(修飾符)(方法名)([參數列表])[throws(異常類)]{......}

    一、throws出如今方法函數頭;而throw出如今函數體。
    二、throws表示出現異常的一種可能性,並不必定會發生這些異常;throw則是拋出了異常,執行throw則必定拋出了某種異常對象。
    三、二者都是消極處理異常的方式(這裏的消極並非說這種方式很差),只是拋出或者可能拋出異常,可是不會由函數去處理異常,真正的處理異常由函數的上層調用處理。



  • 【問題2】錯誤和異常有什麼區別?

  • 解答 :參考Java----異常類(錯誤和異常,二者區別)

    1).java.lang.Error: Throwable的子類,用於標記嚴重錯誤。合理的應用程序不該該去try/catch這種錯誤。絕大多數的錯誤都是非正常的,就根本不應出現的。

    java.lang.Exception: Throwable的子類,用於指示一種合理的程序想去catch的條件。即它僅僅是一種程序運行條件,而非嚴重錯誤,而且鼓勵用戶程序去catch它。

    2).Error和RuntimeException 及其子類都是未檢查的異常(unchecked exceptions),而全部其餘的Exception類都是檢查了的異常(checked exceptions).

    checked exceptions: 一般是從一個能夠恢復的程序中拋出來的,而且最好可以從這種異常中使用程序恢復。好比FileNotFoundException, ParseException等。檢查了的異常發生在編譯階段,必需要使用try…catch(或者throws)不然編譯不經過。

    unchecked exceptions: 一般是若是一切正常的話本不應發生的異常,可是的確發生了。發生在運行期,具備不肯定性,主要是因爲程序的邏輯問題所引發的。好比ArrayIndexOutOfBoundException, ClassCastException等。從語言自己的角度講,程序不應去catch這類異常,雖然可以從諸如RuntimeException這樣的異常中catch並恢復,可是並不鼓勵終端程序員這麼作,由於徹底沒要必要。由於這類錯誤自己就是bug,應該被修復,出現此類錯誤時程序就應該當即中止執行。 所以,面對Errors和unchecked exceptions應該讓程序自動終止執行,程序員不應作諸如try/catch這樣的事情,而是應該查明緣由,修改代碼邏輯。

    RuntimeException:RuntimeException體系包括錯誤的類型轉換、數組越界訪問和試圖訪問空指針等等。
    處理RuntimeException的原則是:若是出現 RuntimeException,那麼必定是程序員的錯誤。例如,能夠經過檢查數組下標和數組邊界來避免數組越界訪問異常。其餘(IOException等等)checked異常通常是外部錯誤,例如試圖從文件尾後讀取數據等,這並非程序自己的錯誤,而是在應用環境中出現的外部錯誤。







  • 【問題5】字節流和字符流的區別和用法?

  • 解答 :參考理解Java中字符流與字節流的區別字節流與字符流的區別&&用字節流好仍是用字符流好?

    在java.io包中操做文件內容的主要有兩大類:字節流、字符流,兩類都分爲輸入和輸出操做。在字節流中輸出數據主要是使用OutputStream完成,輸入使的是InputStream,在字符流中輸出主要是使用Writer類完成,輸入流主要使用Reader類完成。(這四個都是抽象類)在全部的硬盤上保存文件或進行傳輸的時候都是以字節的方法進行的,包括圖片也是按字節完成,而字符是隻有在內存中才會造成的,因此使用字節的操做是最多的。兩種寫入文件的方式,但字節流的使用更重要。



  • 【問題6】爲何能夠對異常根本不進行處理?不進行處理不會致使程序出錯嗎?

  • 解答 :對於不可檢測的異常,程序中能夠選擇捕獲處理,也能夠不處理。這些異常通常是由程序邏輯錯誤引發的,程序應該從邏輯角度儘量避免這類異常的發生。

    運行時異常:都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標越界異常)等,這些異常是不檢查異常,程序中能夠選擇捕獲處理,也能夠不處理。這些異常通常是由程序邏輯錯誤引發的,程序應該從邏輯角度儘量避免這類異常的發生。運行時異常的特色是Java編譯器不會檢查它,也就是說,當程序中可能出現這類異常,即便沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會編譯經過。

    非運行時異常 (編譯異常):是RuntimeException之外的異常,類型上都屬於Exception類及其子類。從程序語法角度講是必須進行處理的異常,若是不處理,程序就不能編譯經過。如IOException、SQLException等以及用戶自定義的Exception異常,通常狀況下不自定義檢查異常。





  • 【問題8】關於語句System.errSystem.out的區別及具體用法?

  • 解答 :一、out:「標準」輸出流。此流已打開並準備接受輸出數據。一般,此流對應於顯示器輸出或者由主機環境或用戶指定的另外一個輸出目標。

    二、err:「標準」錯誤輸出流。此流已打開並準備接受輸出數據。一般,此流對應於顯示器輸出或者由主機環境或用戶指定的另外一個輸出目標。按照慣例,此輸出流用於顯示錯誤消息,或者顯示那些即便用戶輸出流(變量 out 的值)已經重定向到一般不被連續監視的某一文件或其餘目標,也應該馬上引發用戶注意的其餘信息。

    out和err的一個區別是,out每每是帶緩存的,而err沒有緩存(默認設置,能夠改)。因此若是你用標準出錯打印出來的東西能夠立刻顯示在屏幕,而標準輸出打印出來的東西可能要再積累幾個字符才能一塊兒打印出來。若是你在應用中混用標準輸出和標準出錯就可能看到這個問題。
    測試代碼:

    public class Test2 {
    static{
    System.out.println("1");
    }
    public static void main(String[] args) {
    System.err.println("2");
    new Test2();
    }
    public Test2() {
    System.out.println("3");
    }
     }

    實驗結果:
    1,3的位置相對不變,2的位置隨機出現



import java.io.*;
public class FileTest {
public static void main(String[] args) throws IOException {
    //(1)文件建立(文件類實例化)
    File file = new File("C:\\Users\\besti\\Desktop\\FileTest","HelloWorld.txt");
    if (!file.exists()){
        file.createNewFile();
    }
    //(2)文件讀寫
    //第一種:字節流讀寫,先寫後讀
    OutputStream outputStream1 = new FileOutputStream(file);
    byte[] hello = {'H','e','l','l','o',',','W','o','r','l','d','!'};
    outputStream1.write(hello);

    InputStream inputStream1 = new FileInputStream(file);
    while (inputStream1.available()> 0){
        System.out.print((char) inputStream1.read()+"  ");
    }
    inputStream1.close();
    //============================BufferedInputStream====================================
    byte[] buffer = new byte[1024];
    String content = "";
    int flag = 0;
    InputStream inputStream2 = new FileInputStream(file);
    BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream2);

    while ((flag =bufferedInputStream.read(buffer))!=-1){
        content += new String(buffer,0,flag);
    }
    System.out.println(content);
    bufferedInputStream.close();
//====================================BufferedOutputstream================================================
    OutputStream outputStream2 = new FileOutputStream(file);
    BufferedOutputStream bufferedOutputStream2 = new BufferedOutputStream(outputStream2);
    String content2 = "寫入文件的緩衝區內容";
    bufferedOutputStream2.write(content2.getBytes(),0,content2.getBytes().length);
    bufferedOutputStream2.flush();
    bufferedOutputStream2.close();
    //第二種:字符流讀寫,先寫後讀(兩種讀)
    Writer writer2 = new FileWriter(file);
    writer2.write("Hello, I/O Operataion!");
    writer2.flush();
    writer2.append("Hello,World");
    writer2.flush();

    BufferedWriter bufferedWriter = new BufferedWriter(writer2);
    String content3 = "使用bufferedWriter寫入";
    bufferedWriter.write(content3,0,content3.length());
    bufferedWriter.flush();
    bufferedWriter.close();

    Reader reader2 = new FileReader(file);
    System.out.println();
    while(reader2.ready()){
        System.out.print((char) reader2.read()+ "  ");
    }
    BufferedReader bufferedReader = new BufferedReader(reader2);
    while ((content =bufferedReader.readLine())!= null){
        System.out.println(content);
    }
}
}





  • 其餘問題詳見答疑論壇或雲班課:https://group.cnblogs.com/pdds/

【返回目錄】


第 10 周 - 做業問題與解答





  • 【問題3】persistence (持續化)和 serialization(序列化)區別?

  • 解答 :參考序列化和持久化的區別與聯繫郭愷同窗的博客

    序列化和持久化很類似,有些人甚至混爲一談,其實仍是有區別的,序列化是爲了解決對象的傳輸問題,傳輸能夠在線程之間、進程之間、內存外存之間、主機之間進行。我之因此在這裏提到序列化,是由於咱們能夠利用序列化來輔助持久化,能夠說凡是能夠持久化的對象均可以序列化,由於序列化相對容易一些(也不是很容易),因此主流的軟件基礎設施,好比.net和java,已經把序列化的框架完成了。

    因此,序列化只是輔助持久化而已,是有必定區別的,換句話說,實現持久化就能夠實現序列化。



  • 【問題4】ArrayList和Linked和Vector的區別

  • 解答 :參考Vector,ArrayList, LinkedList的區別

    1.Vector、ArrayList都是以相似數組的形式存儲在內存中,LinkedList則以鏈表的形式進行存儲。

    2.List中的元素有序、容許有重複的元素,Set中的元素無序、不容許有重複元素。

    3.Vector線程同步,ArrayList、LinkedList線程不一樣步。

    4.LinkedList適合指定位置插入、刪除操做,不適合查找;ArrayList、Vector適合查找,不適合指定位置的插入、刪除操做。

    5.ArrayList在元素填滿容器時會自動擴充容器大小的50%,而Vector則是100%,所以ArrayList更節省空間。







  • 【問題7】「數組與鏈表爲同級」,那他們能夠互換嗎,或者彼此替代嗎?

  • 解答 :參考數組和鏈表的區別

    數組的特色:
    一、在內存中,數組是一塊連續的區域。
    二、數組須要預留空間,在使用前要先申請佔內存的大小,可能會浪費內存空間。 好比看電影時,爲了保證10我的能坐在一塊兒,必須提早訂好10個連續的位置。這樣的好處就是能保證10我的能夠在一塊兒。可是這樣的缺點是,若是來的人不夠10個,那麼剩下的位置就浪費了。若是臨時有多來了我的,那麼10個就不夠用了,這時可能須要將第11個位置上的人挪走,或者是他們11我的從新去找一個11連坐的位置,效率都很低。若是沒有找到符合要求的做爲,那麼就無法坐了。
    三、插入數據和刪除數據效率低,插入數據時,這個位置後面的數據在內存中都要向後移。刪除數據時,這個數據後面的數據都要往前移動。 好比原來去了5我的,而後後來又去了一我的要坐在第三個位置上,那麼第三個到第五個都要日後移動一個位子,將第三個位置留給新來的人。 當這我的走了的時候,由於他們要連在一塊兒的,因此他後面幾我的要往前移動一個位置,把這個空位補上。
    四、隨機讀取效率很高。由於數組是連續的,知道每個數據的內存地址,能夠直接找到給地址的數據。
    五、而且不利於擴展,數組定義的空間不夠時要從新定義數組。

    鏈表的特色:
    一、在內存中能夠存在任何地方,不要求連續。
    二、每個數據都保存了下一個數據的內存地址,經過這個地址找到下一個數據。 第一我的知道第二我的的座位號,第二我的知道第三我的的座位號……
    三、增長數據和刪除數據很容易。 再來我的能夠隨便坐,好比來了我的要作到第三個位置,那他只須要把本身的位置告訴第二我的,而後問第二我的拿到原來第三我的的位置就好了。其餘人都不用動。
    四、查找數據時效率低,由於不具備隨機訪問性,因此訪問某個位置的數據都要從第一個數據開始訪問,而後根據第一個數據保存的下一個數據的地址找到第二個數據,以此類推。 要找到第三我的,必須從第一我的開始問起。
    五、不指定大小,擴展方便。鏈表大小不用定義,數據隨意增刪。

    綜上所述:
    同級只是它們的共同點之一,不一樣僅僅以這樣一個標準就去認爲能夠互換,實際上講,各個都有彼此的優勢,互換的也僅僅是方法,各自有實現目標的辦法,只是有些方法複雜,有些比較簡單而已,因此講,從實際問題上講,是能夠互換的,可是不能直接講位置互換就能夠,須要進行方法內部的修改,而後發現問題,及時修改。



  • 【問題8】數據結構和抽象數據類型的區別和聯繫?

  • 解答 :參考趙曉海同窗的博客

    數據結構:老是爲了完成一個功能或者目的寫程序,但無論什麼程序、代碼實際上都是一些指令的集合,說白了就是在描述「怎麼作」,而光知道怎麼作還只是問題的一半,還要知道「作什麼」,也就是剛纔那些指令的對象是誰,天然確定是相關的數據,好比說學生信息管理中,指令是增長學生,那他的對象就是學生信息這種數據,指令是成績統計,那對象就是學生的成績數據,而在咱們的程序中,數據也必需要有一種很明確的組織表示方式,只要這樣咱們才能在這種具體明確的實體上編寫指令,好比說學生數據能夠定義爲一個多維的數組,只有這樣咱們再寫增長學生時,才能知道具體增長就是增長一個數組元素併爲其賦值。因此數據結構就是相互之間有聯繫的具備某種組織方式的數據集合。

    抽象數據類型相比較數據結構要具體一些,咱們光有了數據結構還不夠,由於數據是各類各樣的,對於不一樣數據,咱們能採起的方法也不同,好比說學生數據能夠增減,成績數據能夠進行算數運算,可是爲何說抽象呢,也就說他並非具體整型仍是字符型這種基本類型,而是咱們根據咱們要解決的實際問題,對應現實世界所描述的一種和現實世界中的實體對應的數據類型,並且這種抽象的數據類型還包括可以對於他實行的操做,好比說咱們定義一種數據類型叫「學生」,具體的數據我能夠定義一中相似表的結構存儲,並且還要定義一些操做,好比說添加學生,刪除學生,這兩部分就共同組成了「學生」這個抽象的數據類型。





  • 【問題10】在學習堆棧過程當中,不理解「與Stack類不一樣的是,在JavaAPI中沒有實現隊列的類。」是什麼意思?

  • 解答 :參考李馨雨同窗的博客

    先去了解javaAPI究竟是什麼:

    API(Application Programming Interface,應用程序編程接口)是一些預先定義的函數,目的是提供應用程序與開發人員基於某軟件或硬件的以訪問一組例程的能力,而又無需訪問源碼,或理解內部工做機制的細節。

    運行Java程序時,虛擬機裝載程序的class文件所使用的Java API class文件。全部被裝載的class文件(包括從應用程序中和從Java API中提取的)和全部已經裝載的動態庫(包含本地方法)共同組成了在Java虛擬機上運行的整個程序。

    再去了解一下隊列的使用:

    在java5中新增長了java.util.Queue接口,用以支持隊列的常見操做。Queue接口與List、Set同一級別,都是繼承了Collection接口。

    javaAPI中沒有實現隊列的類,因此只能經過Queue接口來實現隊列。



  • 其餘問題詳見答疑論壇或雲班課:https://group.cnblogs.com/pdds/

【返回目錄】


第 11 周 - 做業問題與解答

  • 【問題1】什麼是生命活動週期方法?

  • 解答 :生命週期很好理解,可是在後面加上方法就顯得有些抽象。書上也很詳細的將其中每一個具體方法進行講解。可是,具體到一個app中是怎樣的呢?先用一個圖進行理解(圖)onCreate和onDestroy方法在每一個生命週期中只執行一次,而其餘都可循環。這裏着重探究onPause、onStop、onDestroy方法。

    1.當活動開始進入運行階段後,假如用戶執行其餘活動時,就須要執行onPause操做,使得減小資源的浪費。而此時的內存依舊佔用。此時,activity仍然處於部分可見的狀態。

    2.當活動調用onStop方法時,首先,活動將處於不可見狀態。可是它依然保持全部狀態和成員信息,可是它再也不可見,因此它的窗口被隱藏,當系統內存須要被用在其餘地方的時候,Stopped的Activity將被殺掉。

    3.當Activity(用戶調用finish()或系統因爲內存不足)被系統銷燬殺掉時系統調用,(整個生命週期只調用1次)用來釋放onCreate()方法中建立的資源,如結束線程等。

    參考android 活動的生命週期,還能夠把整個活動週期分紅三個部分:

    • 完整生存期:onCreate()方法和onDestroy()之間,總共調用了6個方法。
    • 可見生存期:活動在onStart()方法和onStop()之間,總共4個方法,再加上從新運行的onRestart()方法,總共5個。
    • 前臺生存期:活動在onResume()方法和onPause()方法,總共2個方法。

    活動生命週期圖解:



  • 【問題2】對於Android事件和監聽器不是很理解。

  • 解答 :參考Android事件和監聽器詳細的介紹

    監聽器是一個存在於View類下的接口,通常以On******Llistener命名,實現該接口須要複寫相應的on****(View v)方法(如onClick(View v))。

    監聽器的三種實現方法:
    方法一:在Activity中定義一個內部類繼承監聽器接口(這裏是OnClickListener)。常見的繼承方法以下:

    class MyListener implements View.OnClickListener{
      @Override
      public void onClick(View v) {
          Toast.makeText(MainActivity.this,"you have clicked Button2",Toast.LENGTH_SHORT).show();
      }
    }

    方法二:實現匿名內部類。這種方法適合只但願對監聽器進行一次性使用的狀況,在該代碼塊運行完畢以後,該監聽器也就不復存在了。

    bt1.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              Toast.makeText(MainActivity.this,"you have clicked Button1",Toast.LENGTH_SHORT).show();
          }
      });

    方法三:利用佈局文件中的onClick屬性,並在實現文件中實現該方法。注意的是這裏的方法名應該和佈局文件中onClick屬性的方法名相同,該方法必須是public方法。

    // 方法三,注意須要public方法
    public void onButtonClick (View view){
      Toast.makeText(MainActivity.this,"you have clicked Button3",Toast.LENGTH_SHORT).show();
    }
    }



  • 【問題3】Android Studio 里加載的R類到底是什麼?

  • 解答 :R類是AS中看不到的一個通用類,能夠在app/build/generated/source目錄下找到它。每當添加、修改或者刪除資源時,都會從新生成R。R的做用是讓你能夠在代碼中引用一個資源。

    R類的做用是讓你可以引用代碼中的一個資源:
    1)layout下中的andoid:id、android:text等資源信息等
    2)string對應的字段是res/values/strings.xml中的配置項信息(自動生成的,不須要認爲的修改R類,包含id也同樣)。
    3)@color查找顏色:color對應的字段是res/values/colors.xml中的配置項信息(自動生成的,不須要認爲的修改R類,包含id也同樣)。
    4)@drawable查找圖片:只須要把png/jpeg/gif文件拷貝到新建的/res/drawable目錄下,或者拷貝到工程新建的默認drawable-xx目錄下
    5)@dimen某個組件尺寸定義:須要在res/values/目錄下新建一個dimen.xml文件.



  • 【問題4】對活動程序的文件目錄結構要怎麼理解?

  • 解答 :文件目錄以下圖所示:

    • build:該目錄包含了自動生成的文件,這些文件包括了編譯設置項、R類等

    • libs:該目錄包含了開發Android應用所須要的庫文件

    • src:該目錄存放了應用的源代碼.java文件。默認狀況下,它包含了MainActivity.java文件,這個源代碼j有一部分是執行了你點擊應用圖標時啓動應用所須要功能
      • res:該目錄存放了全部的資源文件
      • drawable:該目錄存放了項目的drawable對象和一些圖片資源
      • layout:該目錄存放了各個界面的佈局文件
      • menu:該目錄存放了應用中設計的菜單對象
      • mipmap:該目錄存放了應用的主要圖片資源
      • values:該目錄存放了字符串、顏色等定義的資源集合
      • AndroidManifest.xml:該文件是描述應用基礎特性的文件,定義了每一個組件。



  • 【問題5】apk文件的簽名是什麼意思?

  • 解答 :計算機中所說的簽名和生活中所說的簽名在本質上是同樣的,Android系統要求每個Android應用程序必需要通過數字簽名纔可以安裝到系統中,也就是說若是一個Android應用程序沒有通過數字簽名,是沒有辦法安裝到系統中的!Android經過數字簽名來標識應用程序的做者和在應用程序之間創建信任關係,不是用來決定最終用戶能夠安裝哪些應用程序。這個數字簽名由應用程序的做者完成,並不須要權威的數字證書籤名機構認證,它只是用來讓應用程序包自我認證的。



  • 【問題6】Android Studio 里加載的Gradle究竟是指什麼?

  • 解答 :參考Android Studio中的Gradle是幹什麼的

    專業解釋:

    Gradle是一個基於Apache Ant和Apache Maven概念的項目自動化建構工具。它使用一種基於Groovy的特定領域語言來聲明項目設置,而不是傳統的XML。當前其支持的語言限於Java、Groovy和Scala,計劃將來將支持更多的語言。

    較好地解釋:

    軟件開發講究代碼複用,經過複用能夠使工程更易維護,代碼量更少..... 開發者能夠經過繼承,組合,函數模塊等實現不一樣程度上的代碼複用.但不知你有沒有想過,軟件開發也是一種工程做業,毫不僅僅是寫代碼,還涉及到工程的各類管理(依賴,打包,部署,發佈,各類渠道的差別管理.....),你天天都在build,clean,簽名,打包,發佈,有沒有想過這種過程,也能夠像代碼同樣被描述出來, 也能夠被複用。

    總結地說:

    一、Gradle是一種構建工具,它能夠幫你管理項目中的差別,依賴,編譯,打包,部署......,你能夠定義知足本身須要的構建邏輯,寫入到build.gradle中供往後複用;

    二、Gradle不是一種編程語言,它不能幫你實現軟件中的任何實際功能。



  • 【問題7】在運行書上相關代碼時,R文件變紅,如何處理?

  • 解答 :之前用studio是R文件是不報錯的。當你從其餘程序拷過一些代碼是會發現R文件會變紅而且應用程序不能運行。除了R文件其餘地方沒有報錯,只有app運行時會報錯 。
    這是由於當你從其餘程序拷過一些代碼。你的r文件中沒有自動加載,這時你須要把那些報錯的代碼刪除並從新在Android studio中輸入,這樣你的應用程序就能夠運行了。也能夠試着用rebuild project.

    還可參考Android Studio-R文件錯誤的解決辦法Android Studio中R文件丟失的解決辦法



  • 【問題8】在運行書上相關代碼時,menu文件報紅,如何處理?

  • 解答 :menu文件主要是由於沒有導入,可是若是想本身新建的話要注意menu佈局文件要在menu文件夾地下建立才行,應該先在res文件夾右鍵,而後選擇New > Android resource directory,出現界面後在Resource type下拉欄選擇menu。接着在menu文件夾下右鍵,New > Menu resource file以後輸入文件名就能夠了.





  • 【問題10】顯式意圖和隱式意圖表明什麼?區別?

  • 解答 :參考Intent的顯式意圖和隱士意圖
    對意圖的理解:

    顯式意圖:調用Intent.setComponent()或Intent.setClass()方法明確指定了組件名的Intent爲顯式意圖,顯式意圖明確指定了Intent應該傳遞給哪一個組件。
    隱式意圖:沒有明確指定組件名的Intent爲隱式意圖。 Android系統會根據隱式意圖中設置的動做(action)、類別(category)、數據(URI和數據類型)找到最合適的組件來處理這個意圖。

    簡單歸納就是: 意圖包括:Action(動做),Category(附加信息),Data(數據,具體內容),Tpye(類型)等等,舉個例子,說白了意圖就是啓動一個組件的的完整的動做信息,就像打人,打就是Action動做,人就是Data內容,而Type就是類型,打什麼人呢?打壞人,type就是壞指的類型,只有這些信息全了才能執行一個完整的意圖,固然還有一些信息,好比scheme就是URI類型的數據的前綴,就像這個例子當中的sms:,還有host主機名,path路徑等。





  • 其餘問題詳見答疑論壇或雲班課:https://group.cnblogs.com/pdds/

【返回目錄】


第 12 周 - 做業問題與解答



  • 【問題2】實驗五-密碼學相關算法參考資料及示例。

  • 解答 :參考Java 密碼學算法

    關於DH算法,亦可參考下圖,計算出的共享祕鑰是g^(ab):



  • 【問題3】什麼是協商密鑰?

  • 解答 :協商密鑰的意思就是客戶端給服務器發送個數據,而後服務器再給客戶端發送數據。客戶端根據接收到服務器的數據,而後根據本身再加上本身的私鑰計算出一個密鑰。而後服務器,是根據客戶端發送數據,再加上本身的私鑰在計算出一個祕鑰。這樣就能協商出來,他計算出來的祕鑰兩個是如出一轍的。這就是迪福哈爾曼那個協議的妙處。



  • 【問題4】關於實驗五-第三個實驗:如何傳給服務器密鑰?

  • 解答 :第一種方法,經過傳遞原文的方式將其傳遞過去,可是這裏就會有問題,由於,咱們不清楚究竟是如何去傳遞兩個東西,咱們並無被要求去用雙線程,何況咱們也沒有那麼厲害,所以經過和餘坤澎同窗的討論,咱們能夠用這個方法進行將兩個東西傳遞過去,舉個例子:假如咱們如今要傳遞字符串A和字符串B,可是咱們怎麼把兩個東西一塊兒傳遞過去呢,首先咱們想到,就字符串有一個split的方法,咱們能夠利用這個方法把這兩個字符串用一個字符進行切分,而後分別保存,好比String aa =A;B,咱們用String []bb =aa.split";";就能夠將其分紅bb[0]bb[1]這樣就把兩個東西都傳遞過去了。(參考王文彬同窗的博客

    第二種方式,用文件直接拷貝過去就能夠。



  • 【問題5】關於實驗五-第三個實驗:即將字節型數組的密文轉換成String類型時,傳輸過來時,老是會出現亂碼,結果致使沒有辦法解密。

  • 解答 :這裏顯示的密文是不合法的,咱們在這裏卡了好久,最後採用的是再也不進行轉換成String類型的轉換,咱們直接將密文的byte數組使用字節流傳輸,接收時使用一個byte的數組進行接收,這裏就沒有問題了,具體代碼是客戶端是outputStream.write(ctext);outputStream.flush();,服務器是byte[] ctext = inputStream.readAllBytes();,最後就是這樣,將密文傳輸過來,並完成後續步驟。(參考侯澤洋同窗的博客



  • 其餘問題詳見答疑論壇或雲班課:https://group.cnblogs.com/pdds/

    (一共十三次問題收集與解答整理完畢,大部分從同窗們的博客中摘錄,少部分來源於雲班課和QQ羣)

【返回目錄】

相關文章
相關標籤/搜索