1.&和&&的區別?
&:邏輯與(and),運算符兩邊的表達式均爲true時,整個結果才爲true。
&&:短路與,如果第一個表達式爲false時,第二個表達式就不會計算了。
2.在java中如何跳出當前的多重循環?
在循環語句外前面定義一個標號,然後在裏層循環體的代碼中使用帶有標號的break語句,即可跳出循環。
比如:
ok:
for (int i = 0; i < 10; i++) {
{
for (int j = 0; j < 10; j++) {
break ok;
}
}
}
3.最有效率的方法算出2X8等於幾?
使用位運算,效率最高:2<<3,表示2向左移動了3位,就相當於2乘以2的3次方,結果:16。
4.”==”和equals方法究竟有什麼區別?
“==”:表示兩個變量的值是否相等,比較兩個基本數據類型的數據或者引用變量,用==。
equals:用於比較兩個獨立對象的內容是否相同。字符串的比較也用equals。
- Int和integer的區別?
Int是Java的8中基本數據類型之一,integer是int的封裝類。Int類型的默認值爲0,integer默認值爲null,所以區別在於,integer能區分出null值和0的區別。
6.三個與取整有關的方法:
Math.ceil():表示向上取整;Math.ceil(11.3)=12;Math.ceil(-11.3)=-12。
Math.floor():表示向下取整;Math.floor(11.6)=11;Math.floor(-11.6)=-12。
Math.round():表示四捨五入;Math.round(11.5)=12;Math.round(-11.5)=-11;
Marh.round(11.3)=11;Math.round(-11.3)=–11;
7.重載和重寫的區別?
重載(Overload):函數名相同,參數不同。可以改變返回值類型,參數的個數和類型。
重寫(Override):和父類的的方法名稱、參數完全相同。
8.面向對象的特徵?
封裝:將對象屬性和方法的代碼封裝到一個模塊中,也就是一個類中,保證軟件內部具有優良的模塊性的基礎,實現“高內聚,低耦合”。
抽象:找出一些事物的相似和共性之處,然後歸爲一個類,該類只考慮事物的相似和共性之處。抽象包括行爲抽象和狀態抽象。
繼承:在已經存在的類的基礎上進行,將其定義的內容作爲自己的內容,並可以加入新的內容或者修改原來的方法適合特殊的需要。
多態:同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果,就是多態,簡單點說:就是用父類的引用指向子類的對象。目的:提高代碼複用性,解決項目中緊耦合問題,提高可擴展性。
多態的機制:靠的是父類的或者接口的引用變量可以指向子類或者具體實現類的實例對象。
9.String和StringBuffuer、StringBuilder的區別?
String:字符串數值不可變;
StringBuffer:字符串可修改,可以動態構造字符數據。StringBuffer類是可以通過Append()來修改值。線程安全。
StringBuilder:線程不安全。
三者在執行速度方面的比較:StringBuilder > StringBuffer > String
對於三者使用的總結:
1.如果要操作少量的數據用 = String
2.單線程操作字符串緩衝區下操作大量數據 = StringBuilder
3.多線程操作字符串緩衝區下操作大量數據 = StringBuffer
10.java中有幾種方法實現一個線程?用什麼關鍵字修飾同步方法?stop()和suspend()方法爲何不推薦使用?
第一種:繼承Thread類。New Thread(){}.start():表示調用子類對象的run方法。
第二種:實現Runable接口。
第三種:線程池創建多線程。
第四種:實現Callable接口,重寫call函數(
繼承Thread類實現多線程,重寫run方法時沒有返回值也不能拋出異常,使用Callable接口就可以解決這個問題。
Callable接口和Runnable接口的不同之處:
1.Callable規定的方法是call,而Runnable是run
2.call方法可以拋出異常,但是run方法不行
3.Callable對象執行後可以有返回值,運行Callable任務可以得到一個Future對象,通過Future對象可以瞭解任務執行情況,可以取消任務的執行,而Runnable不可有返回值
)
用synchronized 關鍵字修飾同步方法。
反對使用stop(),是因爲它不安全。它會解除由線程獲取的所有鎖定,而且如果對象處於一種不連貫狀態,那麼其他線程能在那種狀態下檢查和修改它們,結果很難檢查出真正的問題所在。
suspend() 方法容易發生死鎖。調用 suspend() 的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定的資源,除非被" 掛起"的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應該使用 suspend() ,而應在自己的 Thread 類中置入一個標誌,指出線程應該活動還是掛起。若標誌指出線程應該掛起,便用 wait() 命其進入等待狀態。若標誌指出線程應當恢復,則用一個 notify()重新啓動線程。
11.sleep()和wait()有什麼區別?
sleep是線程被調用時,佔着cpu休眠,其他線程不能佔用cpu,os認爲該線程正在工作,不會讓出系統資源,wait是進入等待池等待,讓出系統資源,其他線程可以佔用cpu。
sleep()和wait()方法的區別可從兩個角度闡述:
1.cpu的搶佔權;2.鎖旗標是否釋放
兩者都會釋放cpu的搶佔權;
wait()方法執行完即可釋放鎖旗標,進入線程的等待隊列;
sleep()執行完,不會釋放,進入等待隊列;
- 同步和異步的區別?同步的實現方法?
同步:發送一個請求,等待返回,然後再發送下一個請求。實現:1. Synchronized修飾;2.wait和notify。
異步:發送一個請求,不等待返回,隨時可以再發送下一個請求。
同步可以避免出現死鎖,讀髒數據的發生,一般共享某一資源的時候用,如果每個人都有修改權限,同時修改一個文件,有可能使一個人讀取另一個人已經刪除的內容,就會出錯,同步就會按順序來修改。
同步和異步最大的區別就在於,一個需要等待,一個不需要等待。
比如廣播,就是一個異步例子。發起者不關心接收者的狀態。不需要等待接收者的返回信息。
電話,就是一個同步例子。發起者需要等待接收者,接通電話後,通信纔開始。需要等待接收者的返回信息。
- 請對比synchronized與java.util.concurrent.locks.Lock的異同?
主要相同點:Lock能完成synchronized所實現的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,並且必須在finally從句中釋放。
14.String s =new String (“syz”);創建了幾個String Object?
1.如果String常理池(常量緩衝區)中,已經創建"xyz",則不會繼續創建,此時只創建了一個對象new String(“xyz”);
2.如果String常理池中,沒有創建"xyz",則會創建兩個對象,一個對象的值是"xyz",一個對象new String(“xyz”)。
15.作用域public、private、protected 以及不寫時的區別?
private修飾的成員變量和函數只能在類本身和內部類中被訪問。
protected 修飾的成員變量和函數能被類本身、子類及同一個包中的類訪問。
public修飾的成員變量和函數可以被類、子類、同一個包中的類以及任意其他類訪問。
默認情況(不寫)下,屬於一種包訪問,即能被類本身以及同一個包中的類訪問。
作用域
當前類
同一package
子孫類
其他package
public
√
√
√
√
protected
√
√
√
×
friendly
√
√
×
×
private
√
×
×
×
16.forward和redirect兩種跳轉方式的區別?
1.從地址欄顯示來說
forward是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然後把這些內容再發給瀏覽器.瀏覽器根本不知道服務器發送的內容從哪裏來的,所以它的地址欄還是原來的地址.
redirect是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址.所以地址欄顯示的是新的URL.
2.從數據共享來說
forward:轉發頁面和轉發到的頁面可以共享request裏面的數據.
redirect:不能共享數據.
3.從運用地方來說
forward:一般用於用戶登陸的時候,根據角色轉發到相應的模塊.
redirect:一般用於用戶註銷登陸時返回主頁面和跳轉到其它的網站等.
4.從效率來說
forward:高.
redirect:低.
本質上說, 轉發是服務器行爲,重定向是客戶端行爲。其工作流程如下:
轉發過程:客戶瀏覽器發送http請求----》web服務器接受此請求–》調用內部的一個方法在容器內部完成請求處理和轉發動作----》將目標資源發送給客戶;在這裏,轉發的路徑必須是同一個web容器下的url,其不能轉向到其他的web路徑上去,中間傳遞的是自己的容器內的request。在客戶瀏覽器路徑欄顯示的仍然是其第一次訪問的路徑,也就是說客戶是感覺不到服務器做了轉發的。轉發行爲是瀏覽器只做了一次訪問請求。
重定向過程:客戶瀏覽器發送http請求----》web服務器接受後發送302狀態碼響應及對應新的location給客戶瀏覽器–》客戶瀏覽器發現是302響應,則自動再發送一個新的http請求,請求url是新的location地址----》服務器根據此請求尋找資源併發送給客戶。在這裏 location可以重定向到任意URL,既然是瀏覽器重新發出了請求,則就沒有什麼request傳遞的概念了。在客戶瀏覽器路徑欄顯示的是其重定向的路徑,客戶可以觀察到地址的變化的。重定向行爲是瀏覽器做了至少兩次的訪問請求的。
18.編程單例模式:寫一個singleton出來
Singleton分爲:飽漢模式、飢漢模式、雙重鎖模式
//飽漢模式:類加載時完成初始化,創建出實例對象(不管用不用,先創建)。
public class SingleTon {
//實例化對象放到靜態代碼塊中,可提高執行效率,但是可能更佔用空間
private final static SingleTon instence=new SingleTon();
private SingleTon(){};//私有的構造函數
//獲取方法
public static SingleTon getinstance(){
return instence;
};
}
//飢漢模式:延遲加載,在第一次用的時候才創建出對象,存在線程安全問題。
public class SingleTon {
private static SingleTon instence=null;
private SingleTon(){};//私有的構造函數
//獲取方法
public static synchronized SingleTon getinstance(){
if(instence==null){
//第一次使用的時候創建對象
instence=new SingleTon();
}
return instence;
};
}
19.編程冒泡排序:用java實現冒泡排序?快速排序的方法。
冒泡排序:
int temp = 0;
int[] sortNum = {12,33,28,86,15,62,9,38};
for (int i = 0; i < sortNum.length-1; i++) { //第一個for循環控制排序要走多少趟,最多做n-1趟排序
for (int j = 0; j < sortNum.length-1-i; j++) { //第2個for循環控制每趟比較多少次
if(sortNum[j+1]<sortNum[j]){ //大的 往後面排
temp = sortNum[j];
sortNum[j] = sortNum[j+1];
sortNum[j+1] = temp;
}
}
}
System.out.println(Arrays.toString(sortNum));
1.對基本數據類型數組的排序
1>數字排序:
int[] intArray = new int[]{1,56,-5,33};
Arrays.sort(intArray);
System.out.println(Arrays.toString(intArray));
2>字符串排序(先大寫後小寫):
String[] strArray = new String[]{“Z”, “a”, “D”};
Arrays.sort(strArray);
System.out.println(Arrays.toString(strArray));
20.HashMap和Hashtable的區別?
HashMap:實現了Map接口,允許空(null)鍵值(key),由於非線程安全,在只有一個線程訪問的情況下,效率高於Hashtable。
Hashtable:不能將null作爲key或者value。方法是同步的,線程安全。
21.List、Set和Map的區別?
List:是存儲單列數據的集合,存儲有順序,允許重複。繼承Collection接口。
Set: 是存儲單列數據的集合。繼承Collection接口。不允許重複。
Map:存儲鍵和值這樣的雙列數據的集合,存儲數據無順序,鍵(key)不能重複,值(value)。可以重複。
22.什麼時候用assert?
在調試程序時使用,對一個boolean表達式進行檢查。爲true,則程序正確,如果爲false,系統則給出警告或者退出。
23.使用java.lang.Math,生成100個0到99之間的隨機整數,找出最大和最小,並統計大於50的整數個數?
import java.util.Random;
public class RandomTest {
public static void main(String args[]) {
int max = 0;
int min = 0;
String sum="";
int num=0;
for (int i = 0; i <= 100; i++) {
Random rand = new Random();
int r = rand.nextInt(99);
if (r >= max) {
max = r;
} else if (r < min) {
min = r;
}
String s= “”+r;
if (r > 50) {
sum=sum+s+",";
++num;
}
}
System.out.println(“最大數max=” + max + “\n” + “最小數min=” + min);
System.out.println(“大於50的個數:”+num);
}
}
備註:Random rand = new Random();
int r = rand.nextInt(99);
表示產生的隨機數爲0-99的整數,不包括99。
24.java創建對象的方式有哪些?
1.使用new關鍵字
2.使用反射機制創建對象:
(1)使用Class類的newInstance方法
(2)java.lang.reflect.Constructor類裏也有一個newInstance方法可以創建對象。
3.使用clone方法:先實現Cloneable接口並實現其定義的clone方法
4.使用反序列化
25.java垃圾回收機制
GC是垃圾回收機制,是用來釋放內存中的資源的。
垃圾回收可以有效的防止內存泄露,有效的使用空閒的內存。
26.error和exception有什麼區別?
Error(錯誤)表示系統級的錯誤和程序不必處理的異常,是java運行環境中的內部錯誤或者硬件問題。比如:內存資源不足等。對於這種錯誤,程序基本無能爲力,除了退出運行外別無選擇,它是由Java虛擬機拋出的。
Exception(違例)表示需要捕捉或者需要程序進行處理的異搜索常,它處理的是因爲程序設計的瑕疵而引起的問題或者在外的輸入等引起的一般性問題,是程序必須處理的。
Exception又分爲運行時異常,受檢查異常。
運行時異常,表示無法讓程序恢復的異常,導致的原因通常是因爲執行了錯誤的操作,建議終止程序,因此,編譯器不檢查這些異常。
受檢查異常,是表示程序可以處理的異常,也即表示程序可以修復(由程序自己接受異常並且做出處理), 所以稱之爲受檢查異常。
27.Int如何去重複?
1.For循環
2.Set集合
28.JDBC使用步驟過程?
1、加載JDBC驅動程序:
2、提供JDBC連接的URL
3、創建數據庫的連接
4、創建一個Statement
5、執行SQL語句
6、處理結果
7、關閉JDBC對象
29.運行時異常與一般異常有何異同?
Java提供了兩類主要的異常:運行時異常runtime exception和一般異常checked exception。對於後者這種一般異常,JAVA要求程序員對其進行catch處理。所以,面對這種異常不管我們是否願意,只能自己去寫一大堆catch塊去處理可能的異常。
運行時異常我們可以不處理。這樣的異常由虛擬機接管。出現運行時異常後,系統會把異常一直往上層拋,一直遇到處理代碼。如果不對運行時異常進行處理,那麼出現運行時異常之後,要麼是線程中止,要麼是主程序終止。
30.抽象類和接口區別?
抽象類:用abstract修飾,抽象類不能創建實例對象。抽象方法必須在子類中實現,不能有抽象構造方法或者抽象靜態方法。
接口:抽象類的一種特例,接口中的方法必須是抽象的。
兩者的區別:
抽象類可以有構造方法,接口沒有構造方法
抽象類可以有普通成員變量,接口沒有普通成員變量。
抽象類可以有非抽象的普通方法,接口中的方法必須是抽象的。
抽象類中的抽象方法訪問類型可以是public,protected,接口中抽閒方法必須是public類型的。
抽象類可以包含靜態方法,接口中不能包含靜態方法。
一個類可以實現多個接口,但是隻能繼承一個抽象類。
7.接口中基本數據類型的數據成員,都默認爲static和final,抽象類則不是。
31.如何獲取map集合中的數據?
// 方法一: for each + map.keySet();
Set set = map.keySet();
for (Integer key : set) {
System.out.println("key:" + key + ", value:" + map.get(key));
}
// 方法二:while循環(Iterator + map.keySet()😉
Set set = map.keySet();
Iterator it = set.iterator();
while(it.hasNext()){
Integer key = it.next();
System.out.println("key:" + key + ", value:" + map.get(key));
}
// 方法三:while循環(Iterator +Map.Entry<Key, Value>)
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
System.out.println("key:"+entry.getKey() + ", value:"+entry.getValue());
}
// 方法四:for循環(Iterator + Map.Entry<Key, Value>)
for(Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator(); it.hasNext()😉{
Map.Entry<Integer, String> entry = it.next();
System.out.println("key:" + entry.getKey() + ", value:" +entry.getValue());
}
// 方法五:for each + Map.Entry<Key, Value>
for(Map.Entry<Integer, String> entry : map.entrySet()){
System.out.println("key:" + entry.getKey() + ", value:" +entry.getValue());
}
32.hashCode與equals的區別與聯繫?
一、equals方法的作用
1、默認情況(沒有覆蓋equals方法)下equals方法都是調用Object類的equals方法,而Object的equals方法主要用於判斷對象的內存地址引用是不是同一個地址(是不是同一個對象)。
2 、要是類中覆蓋了equals方法,那麼就要根據具體的代碼來確定equals方法的作用了,覆蓋後一般都是通過對象的內容是否相等來判斷對象是否相等。
二、Hashcode()方法:
1、我們並沒有覆蓋equals方法只覆蓋了hashCode方法,兩個對象雖然hashCode一樣,但在將stu1和stu2放入set集合時由於equals方法比較的兩個對象是false,所以就沒有在比較兩個對象的hashcode值。
2、覆蓋一下equals方法和hashCode方法,stu1和stu2通過equals方法比較相等,而且返回的hashCode值一樣,所以放入set集合中時只放入了一個對象。
3、我們讓兩個對象equals方法比較相等,但hashCode值不相等試試,雖然stu1和stu2通過equals方法比較相等,但兩個對象的hashcode的值並不相等,所以在將stu1和stu2放入set集合中時認爲是兩個不同的對象。
總結:
1、equals方法用於比較對象的內容是否相等(覆蓋以後)
2、hashcode方法只有在集合中用到
3、當覆蓋了equals方法時,比較對象是否相等將通過覆蓋後的equals方法進行比較(判斷對象的內容是否相等)。
4、將對象放入到集合中時,首先判斷要放入對象的hashcode值與集合中的任意一個元素的hashcode值是否相等,如果不相等直接將該對象放入集合中。如果hashcode值相等,然後再通過equals方法判斷要放入對象與集合中的任意一個對象是否相等,如果equals判斷不相等,直接將該元素放入到集合中,否則不放入。
33.Java中什麼是競態條件?
當兩個線程競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。導致競態條件發生的代碼區稱作臨界區。在臨界區中使用適當的同步就可以避免競態條件。 界區實現方法有兩種,一種是用synchronized,一種是用Lock顯式鎖實現。
34.線程死鎖及解決辦法
1)、讓所有的線程按照同樣的順序獲得一組鎖。這種方法消除了 X 和 Y 的擁有者分別等待對方的資源的問題。
2)、將多個鎖組成一組並放到同一個鎖下。前面Java線程死鎖的例子中,可以創建一個銀器對象的鎖。於是在獲得刀或叉之前都必須獲得這個銀器的鎖。
3)、將那些不會阻塞的可獲得資源用變量標誌出來。當某個線程獲得銀器對象的鎖時,就可以通過檢查變量來判斷是否整個銀器集合中的對象鎖都可獲得。如果是,它就可以獲得相關的鎖,否則,就要釋放掉銀器這個鎖並稍後再嘗試。
35.ArrayList和LinkList的區別
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。
2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因爲LinkedList要移動指針。
3.對於新增和刪除操作add和remove,LinedList比較佔優勢,因爲ArrayList要移動數據,而查詢和修改ArrayList佔優勢。
36.Socket和HTTP區別?
socket則是對TCP/IP協議的封裝和應用(程序員層面上), Socket本身並不是協議,而是一個調用接口(API)。也可以說,TPC/IP協議是傳輸層協議,主要解決數據如何在網絡中傳輸,而HTTP是應用層協議,主要解決如何包裝數據。
37.BS與CS的聯繫與區別?
C/S 與 B/S 區別:
(bs 面向龐大、不同羣體、不同平臺的客戶;cs 面向比較單一的客戶)
1.硬件環境不同:
C/S 一般建立在專用的網絡上, 小範圍裏的網絡環境, 局域網之間再通過專門服務器提供連接和數據交換服務.
B/S 建立在廣域網之上的, 不必是專門的網絡硬件環境,例與電話上網, 租用設備. 信息自己管理. 有比C/S更強的適應範圍, 一般只要有操作系統和瀏覽器就行
2.對安全要求不同
C/S 一般面向相對固定的用戶羣, 對信息安全的控制能力很強. 一般高度機密的信息系統採用C/S 結構適宜. 可以通過B/S發佈部分可公開信息.
B/S 建立在廣域網之上, 對安全的控制能力相對弱, 可能面向不可知的用戶。
3.對程序架構不同
C/S 程序可以更加註重流程, 可以對權限多層次校驗, 對系統運行速度可以較少考慮.
B/S 對安全以及訪問速度的多重的考慮, 建立在需要更加優化的基礎之上. 比C/S有更高的要求 B/S結構的程序架構是發展的趨勢, 從MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持網絡的構件搭建的系統. SUN 和IBM推的JavaBean 構件技術等,使 B/S更加成熟.
4.軟件重用不同
C/S 程序可以不可避免的整體性考慮, 構件的重用性不如在B/S要求下的構件的重用性好.
B/S 對的多重結構,要求構件相對獨立的功能. 能夠相對較好的重用.就入買來的餐桌可以再利用,而不是做在牆上的石頭桌子
5.系統維護不同
C/S 程序由於整體性, 必須整體考察, 處理出現的問題以及系統升級. 升級難. 可能是再做一個全新的系統
B/S 構件組成,方面構件個別的更換,實現系統的無縫升級. 系統維護開銷減到最小.用戶從網上自己下載安裝就可以實現升級.
6.處理問題不同
C/S 程序可以處理用戶面固定, 並且在相同區域, 安全要求高需求, 與操作系統相關. 應該都是相同的系統
B/S 建立在廣域網上, 面向不同的用戶羣, 分散地域, 這是C/S無法作到的. 與操作系統平臺關係最小.
7.用戶接口不同
C/S 多是建立的Window平臺上,表現方法有限,對程序員普遍要求較高
B/S 建立在瀏覽器上, 有更加豐富和生動的表現方式與用戶交流. 並且大部分難度減低,減低開發成本.
8.信息流不同
C/S 程序一般是典型的中央集權的機械式處理, 交互性相對低
B/S 信息流向可變化, B-B B-C B-G等信息、流向的變化, 更像交易中心。
38.多線程中thread的start()和run()的區別?
1) start:
用start方法來啓動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。通過調用Thread類的start()方法來啓動一個線程,這時此線程處於就緒(可運行)狀態,並沒有運行,一旦得到cpu時間片,就開始執行run()方法,這裏方法 run()稱爲線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程隨即終止。
2) run:
run()方法只是類的一個普通方法而已,如果直接調用Run方法,程序中依然只有主線程這一個線程,其程序執行路徑還是隻有一條,還是要順序執行,還是要等待run方法體執行完畢後纔可繼續執行下面的代碼,這樣就沒有達到寫線程的目的。總結:調用start方法方可啓動線程,而run方法只是thread的一個普通方法調用,還是在主線程裏執行。這兩個方法應該都比較熟悉,把需要並行處理的代碼放在run()方法中,start()方法啓動線程將自動調用 run()方法,這是由jvm的內存機制規定的。並且run()方法必須是public訪問權限,返回值類型爲void。
39.final關鍵字的用法
一、final修飾類:
被final修飾的類,是不可以被繼承的,這樣做的目的可以保證該類不被修改,Java的一些核心的API都是final類,例如String、Integer、Math等。
二、final修飾方法:
子類不可以重寫父類中被final修飾的方法。
三、final修飾實例變量(類的屬性,定義在類內,但是在類內的方法之外)
final修飾實例變量時必須初始化,且不可再修改。//
四、final修飾局部變量(方法體內的變量)
final修飾局部變量時只能初始化(賦值)一次,但也可以不初始化。
五、final修飾方法參數
final修飾方法參數時,是在調用方法傳遞參數時候初始化的。
轉自https://www.cnblogs.com/talenter/p/9652976.html