這也算是這一年交出的一份答案吧
目錄
- 1、面向物件的特征有哪些方面?
- 2、訪問修飾符public,private,protected,以及不寫(默認)時的區別?
- 3、String 是最基本的資料型別嗎?
- 4、float f=3.4;是否正確?
- 5、short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎?
- 6、int和Integer有什么區別?
- 7、&和&&的區別?
- 8、解釋記憶體中的堆疊(stack)、堆(heap)和靜態區(static area)的用法,
- 9、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?
- 10、switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
- 11、用最有效率的方法計算2乘以8?
- 12、陣列有沒有length()方法?String有沒有length()方法?
- 13、構造器(constructor)是否可被重寫(override)?
- 14、兩個物件值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?
- 15、是否可以繼承String類?
- 16、當一個物件被當作引數傳遞到一個方法后,此方法可改變這個物件的屬性,并可回傳變化后的結果,那么這里到底是值傳遞還是參考傳遞?
- 17、String和StringBuilder、StringBuffer的區別?
- 18、多載(Overload)和重寫(Override)的區別,多載的方法能否根據回傳型別進行區分?
- 19、描述一下JVM加載class檔案的原理機制?
- 20、抽象類(abstract class)和介面(interface)有什么異同?
- 21、Java 中會存在記憶體泄漏嗎,請簡單描述,
- 22、GC是什么?為什么要有GC?
- 23、String s = new String(“xyz”);創建了幾個字串物件?
- 24、介面是否可繼承(extends)介面?抽象類是否可實作(implements)介面?抽象類是否可繼承具體類(concrete class)?
- 25、Java 中的final關鍵字有哪些用法?
- 26、指出下面程式的運行結果,
- 27、資料型別之間的轉換:
- 28、如何實作字串的反轉及替換?
- 29、怎樣將GB2312編碼的字串轉換為ISO-8859-1編碼的字串?
- 30、利用java.text.DataFormat 的子類(如SimpleDateFormat類)中的format(Date)方法可將日期格式化
- 31、比較一下Java和JavaSciprt,
- 32、try{}里有一個return陳述句,那么緊跟在這個try后的finally{}里的代碼會不會被執行,什么時候被執行,在return前還是后?
- 33、列出一些你常見的運行時例外?
- 34、類ExampleA繼承Exception,類ExampleB繼承ExampleA,
- 35、List、Set、Map是否繼承自Collection介面?
- 36、Collection和Collections的區別?
- 38、Thread類的sleep()方法和物件的wait()方法都可以讓執行緒暫停執行,它們有什么區別?
- 39、執行緒的sleep()方法和yield()方法有什么區別?
- 40、當一個執行緒進入一個物件的synchronized方法A之后,其它執行緒是否可進入此物件的synchronized方法
- 41、請說出與執行緒同步以及執行緒調度相關的方法,
- 42、撰寫多執行緒程式有幾種實作方式?
- 43、synchronized關鍵字的用法?
- 44、舉例說明同步和異步,
- 45、簡述synchronized 和java.util.concurrent.locks.Lock的異同?
- 46、事務的ACID是指什么?
- 47、獲得一個類的類物件有哪些方式?
- 48、簡述一下面向物件的”六原則一法則”,
- 49、簡述一下你了解的設計模式,
- 50、用Java寫一個冒泡排序,
- 51、用Java寫一個二分查找,
- 52、Servlet的運行程序?
- 54、JSP有哪些內置物件?作用分別是什么?
- 55、講解JSP中的四種作用域,
1、面向物件的特征有哪些方面?
-
抽象:抽象是將一類物件的共同特征總結出來構造類的程序,包括資料抽象和行為抽象兩方面,抽象只關注物件有哪些屬性和行為,并不關注這些行為的細節是什么,
-
繼承:繼承是從已有類得到繼承資訊創建新類的程序,提供繼承的類叫父類(超類、基類)、得到繼承的類叫子類(派生類),
-
封裝:通常認為封裝是把資料和操作資料的方法系結起來,對資料的訪問只能通過已定義的介面,可以說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程介面(可以想想普通洗衣機和全自動洗衣機的差別,明顯全自動洗衣機封裝更好因此操作起來更簡單;我們現在使用的智能手機也是封裝得足夠好的,因為幾個按鍵就搞定了所有的事情),
-
多型性:多型性是指允許不同子型別的物件對同一訊息作出不同的回應,簡單的說就是用同樣的物件參考呼叫同樣的方法但是做了不同的事情,實作多型需要做兩件事:1). 方法重寫(子類繼承父類并重寫父類中的方法);2). 物件造型(用父型別參考參考子型別物件,這樣同樣的參考呼叫同樣的方法就會根據子類物件的不同而表現出不同的行為)
歡迎各位大佬進群共同交流學習,我們的交流分享群:1149778920 暗號:CSDN
博主在這里給大家整理了包括但不限于:JAVA基礎和進階類、Spring、Spring boot、Spring MVC、MyBatis、MySQL、JVM等各種資料有,免費分享給各位進群的小伙伴


2、訪問修飾符public,private,protected,以及不寫(默認)時的區別?
定義:Java中,可以使用訪問修飾符來保護對類、變數、方法和構造方法的訪問,Java 支持 4 種不同的訪問權限,
分類
private : 在同一類內可見,使用物件:變數、方法, 注意:不能修飾類(外部類)
default (即預設,什么也不寫,不使用任何關鍵字): 在同一包內可見,不使用任何修飾符,使用物件:類、介面、變數、方法,
protected : 對同一包內的類和所有子類可見,使用物件:變數、方法, 注意:不能修飾類(外部類),
public : 對所有類可見,使用物件:類、介面、變數、方法

3、String 是最基本的資料型別嗎?
答:不是,Java中的基本資料型別只有8個:byte、short、int、long、float、double、char、boolean;除了基本型別(primitive type)和列舉型別(enumeration type),剩下的都是參考型別(reference type),
4、float f=3.4;是否正確?
答:不正確,3.4是雙精度數,將雙精度型(double)賦值給浮點型(float)屬于下轉型(down-casting,也稱為窄化)會造成精度損失,因此需要強制型別轉換float f =(float)3.4; 或者寫成float f =3.4F;,
5、short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎?
答:對于short s1 = 1; s1 = s1 + 1;由于1是int型別,因此s1+1運算結果也是int 型,需要強制轉換型別才能賦值給short型,而short s1 = 1; s1 += 1;可以正確編譯,因為s1+= 1;相當于s1 = (short)(s1 + 1);其中有隱含的強制型別轉換,
6、int和Integer有什么區別?
答:Java是一個近乎純潔的面向物件編程語言,但是為了編程的方便還是引入了基本資料型別,但是為了能夠將這些基本資料型別當成物件操作,Java為每一個基本資料型別都引入了對應的包裝型別(wrapper class),int的包裝類就是Integer,從Java 5開始引入了自動裝箱/拆箱機制,使得二者可以相互轉換,
class AutoUnboxingTest {
public static void main(String[] args) {
Integer a = new Integer(3);
Integer b = 3; // 將3自動裝箱成Integer型別
int c = 3;
System.out.println(a == b); // false 兩個參考沒有參考同一物件
System.out.println(a == c); // true a自動拆箱成int型別再和c比較
}
}
最近還遇到一個面試題,也是和自動裝箱和拆箱有點關系的,代碼如下所示:
```java
public class Test03 {
public static void main(String[] args) {
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);
System.out.println(f3 == f4);
}
}
如果不明就里很容易認為兩個輸出要么都是true要么都是false,首先需要注意的是f1、f2、f3、f4四個變數都是Integer物件參考,所以下面的==運算比較的不是值而是參考,裝箱的本質是什么呢?當我們給一個Integer物件賦一個int值的時候,會呼叫Integer類的靜態方法valueOf
```java
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
簡單的說,如果整型字面量的值在-128到127之間,那么不會new新的Integer物件,而是直接參考常量池中的Integer物件,所以上面的面試題中f1f2的結果是true,而f3f4的結果是false,
7、&和&&的區別?
雖然二者都要求運算子左右兩端的布林值都是true整個運算式的值才是true,&&之所以稱為短路運算是因為,如果&&左邊的運算式的值是false,右邊的運算式會被直接短路掉,不會進行運算,很多時候我們可能都需要用&&而不是&,例如在驗證用戶登錄時判定用戶名不是null而且不是空字串,應當寫為:username != null &&!username.equals(“”),二者的順序不能交換,更不能用&運算子,因為第一個條件如果不成立,根本不能進行字串的equals比較,否則會產生NullPointerException例外,注意:邏輯或運算子(|)和短路或運算子(||)的差別也是如此,
8、解釋記憶體中的堆疊(stack)、堆(heap)和靜態區(static area)的用法,
堆疊空間操作起來最快但是堆疊很小,通常大量的物件都是放在堆空間
String str = new String(“hello”);
上面的陳述句中變數str放在堆疊上,用new創建出來的字串物件放在堆上,而”hello”這個字面量放在靜態區,
9、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?
答:Math.round(11.5)的回傳值是12,Math.round(-11.5)的回傳值是-11,四舍五入的原理是在引數上加0.5然后進行下取整,
10、switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
expr可以是byte、short、char、int、enum、String型別,但是long型別不能
11、用最有效率的方法計算2乘以8?
答: 2 << 3(左移3位相當于乘以2的3次方,右移3位相當于除以2的3次方),
12、陣列有沒有length()方法?String有沒有length()方法?
答:陣列沒有length()方法,有length 的屬性,String 有length()方法,JavaScript中,獲得字串的長度是通過length屬性得到的,這一點容易和Java混淆,
13、構造器(constructor)是否可被重寫(override)?
答:構造器不能被繼承,因此不能被重寫,但可以被多載,
14、兩個物件值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?
答:不對,如果兩個物件x和y滿足x.equals(y) == true,它們的哈希碼(hash code)應當相同,Java對于eqauls方法和hashCode方法是這樣規定的:(1)如果兩個物件相同(equals方法回傳true),那么它們的hashCode值一定要相同;(2)如果兩個物件的hashCode相同,它們并不一定相同
15、是否可以繼承String類?
答:String 類是final類,不可以被繼承,
16、當一個物件被當作引數傳遞到一個方法后,此方法可改變這個物件的屬性,并可回傳變化后的結果,那么這里到底是值傳遞還是參考傳遞?
答:是值傳遞,Java語言的方法呼叫只支持引數的值傳遞,當一個物件實體作為一個引數被傳遞到方法中時,引數的值就是對該物件的參考,物件的屬性可以在被呼叫程序中被改變,但對物件參考的改變是不會影響到呼叫者的
17、String和StringBuilder、StringBuffer的區別?
答:Java平臺提供了兩種型別的字串:String和StringBuffer/StringBuilder,它們可以儲存和操作字串,其中String是只讀字串,也就意味著String參考的字串內容是不能被改變的,而StringBuffer/StringBuilder類表示的字串物件可以直接進行修改,StringBuilder是Java 5中引入的,它和StringBuffer的方法完全相同,區別在于它是在單執行緒環境下使用的,因為它的所有方面都沒有被synchronized修飾,因此它的效率也比StringBuffer要高,
18、多載(Overload)和重寫(Override)的區別,多載的方法能否根據回傳型別進行區分?
答:方法的多載和重寫都是實作多型的方式,區別在于前者實作的是編譯時的多型性,而后者實作的是運行時的多型性,多載發生在一個類中,同名的方法如果有不同的引數串列(引數型別不同、引數個數不同或者二者都不同)則視為多載;重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的回傳型別,比父類被重寫方法更好訪問,不能比父類被重寫方法宣告更多的例外(里氏代換原則),多載對回傳型別沒有特殊的要求,
19、描述一下JVM加載class檔案的原理機制?
答:JVM中類的裝載是由類加載器(ClassLoader)和它的子類來實作的,Java中的類加載器是一個重要的Java運行時系統組件,它負責在運行時查找和裝入類檔案中的類,類的加載是指把類的.class檔案中的資料讀入到記憶體中,通常是創建一個位元組陣列讀入.class檔案
20、抽象類(abstract class)和介面(interface)有什么異同?
答:抽象類和介面都不能夠實體化,但可以定義抽象類和介面型別的參考,一個類如果繼承了某個抽象類或者實作了某個介面都需要對其中的抽象方法全部進行實作,否則該類仍然需要被宣告為抽象類,介面比抽象類更加抽象,因為抽象類中可以定義構造器,可以有抽象方法和具體方法,而介面中不能定義構造器而且其中的方法全部都是抽象方法,抽象類中的成員可以是private、默認、protected、public的,而介面中的成員全都是public的,抽象類中可以定義成員變數,而介面中定義的成員變數實際上都是常量,有抽象方法的類必須被宣告為抽象類,而抽象類未必要有抽象方法,
21、Java 中會存在記憶體泄漏嗎,請簡單描述,
答:理論上Java因為有垃圾回識訓制(GC)不會存在記憶體泄露問題(這也是Java被廣泛使用于服務器端編程的一個重要原因);然而在實際開發中,可能會存在無用但可達的物件,這些物件不能被GC回收,因此也會導致記憶體泄露的發生,例如hibernate的Session(一級快取)中的物件屬于持久態,垃圾回收器是不會回收這些物件的,然而這些物件中可能存在無用的垃圾物件,如果不及時關閉(close)或清空(flush)一級快取就可能導致記憶體泄露
22、GC是什么?為什么要有GC?
答:GC是垃圾收集的意思,垃圾回收可以有效的防止記憶體泄露,有效的使用可以使用的記憶體
23、String s = new String(“xyz”);創建了幾個字串物件?
答:兩個物件,一個是靜態區的”xyz”,一個是用new創建在堆上的物件,
24、介面是否可繼承(extends)介面?抽象類是否可實作(implements)介面?抽象類是否可繼承具體類(concrete class)?
答:介面可以繼承介面,而且支持多重繼承,抽象類可以實作(implements)介面,抽象類可繼承具體類也可以繼承抽象類,
25、Java 中的final關鍵字有哪些用法?
答:(1)修飾類:表示該類不能被繼承;(2)修飾方法:表示方法不能被重寫;(3)修飾變數:表示變數只能一次賦值以后值不能被修改(常量),
26、指出下面程式的運行結果,
class A {
static {
System.out.print("1");
}
public A() {
System.out.print("2");
}
}
class B extends A{
static {
System.out.print("a");
}
public B() {
System.out.print("b");
}
}
public class Hello {
public static void main(String[] args) {
A ab = new B();
ab = new B();
}
}
答:執行結果:1a2b2b,創建物件時構造器的呼叫順序是:先初始化靜態成員,然后呼叫父類構造器,再初始化非靜態成員,最后呼叫自身構造器,
27、資料型別之間的轉換:
如何將字串轉換為基本資料型別?
- 如何將基本資料型別轉換為字串?
答: - 呼叫基本資料型別對應的包裝類中的方法parseXXX(String)或valueOf(String)即可回傳相應基本型別;
- 一種方法是將基本資料型別與空字串(”")連接(+)即可獲得其所對應的字串;另一種方法是呼叫String 類中的valueOf()方法回傳相應字串
28、如何實作字串的反轉及替換?
答:方法很多,可以自己寫實作也可以使用String或StringBuffer/StringBuilder中的方法,有一道很常見的面試題是用遞回實作字串反轉,代碼如下所示:
public static String reverse(String originStr) {
if(originStr == null || originStr.length() <= 1)
return originStr;
return reverse(originStr.substring(1)) + originStr.charAt(0);
}
29、怎樣將GB2312編碼的字串轉換為ISO-8859-1編碼的字串?
答:代碼如下所示:
String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");
30、利用java.text.DataFormat 的子類(如SimpleDateFormat類)中的format(Date)方法可將日期格式化
class DateFormatTest {
public static void main(String[] args) {
SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd");
Date date1 = new Date();
System.out.println(oldFormatter.format(date1));
}
}
31、比較一下Java和JavaSciprt,
java是靜態語言,js是動態語言
-
基于物件和面向物件:Java是一種真正的面向物件的語言,即使是開發簡單的程式,必須設計物件;JavaScript是種腳本語言,它可以用來制作與網路無關的,與用戶互動作用的復雜軟體,它是一種基于物件(Object-Based)和事件驅動(Event-Driven)的編程語言,因而它本身提供了非常豐富的內部物件供設計人員使用,
-
解釋和編譯:Java的源代碼在執行之前,必須經過編譯,JavaScript是一種解釋性編程語言,其源代碼不需經過編譯,由瀏覽器解釋執行,(目前的瀏覽器幾乎都使用了JIT(即時編譯)技術來提升JavaScript的運行效率)
-
強型別變數和型別弱變數:Java采用強型別變數檢查,即所有變數在編譯之前必須作宣告;JavaScript中變數是弱型別的,甚至在使用變數前可以不作宣告,JavaScript的解釋器在運行時檢查推斷其資料型別,
-
代碼格式不一樣,
32、try{}里有一個return陳述句,那么緊跟在這個try后的finally{}里的代碼會不會被執行,什么時候被執行,在return前還是后?
答:會執行,在方法回傳呼叫者前執行,
在finally中改變回傳值的做法是不好的,因為如果存在finally代碼塊,try中的return陳述句不會立馬回傳呼叫者,而是記錄下回傳值待finally代碼塊執行完畢之后再向呼叫者回傳其值,然后如果在finally中修改了回傳值,就會回傳修改后的值
33、列出一些你常見的運行時例外?
答:
-
ArithmeticException(算術例外)
-
ClassCastException (類轉換例外)
-
IllegalArgumentException (非法引數例外)
-
IndexOutOfBoundsException (下標越界例外)
-
NullPointerException (空指標例外)
-
SecurityException (安全例外)
34、類ExampleA繼承Exception,類ExampleB繼承ExampleA,
有如下代碼片斷:
try {
throw new ExampleB("b")
} catch(ExampleA e){
System.out.println("ExampleA");
} catch(Exception e){
System.out.println("Exception");
}
請問執行此段代碼的輸出是什么?
答:輸出:ExampleA,(根據里氏代換原則[能使用父型別的地方一定能使用子型別],抓取ExampleA型別例外的catch塊能夠抓住try塊中拋出的ExampleB型別的例外)
面試題 - 說出下面代碼的運行結果,(此題的出處是《Java編程思想》一書)
class Annoyance extends Exception {}
class Sneeze extends Annoyance {}
class Human {
public static void main(String[] args)
throws Exception {
try {
try {
throw new Sneeze();
}
catch ( Annoyance a ) {
System.out.println("Caught Annoyance");
throw a;
}
}
catch ( Sneeze s ) {
System.out.println("Caught Sneeze");
return ;
}
finally {
System.out.println("Hello World!");
}
}
}
輸出:
Caught Annoyance
Caught Sneeze
Hello World!
try {
throw new Annoyance();
} catch (Sneeze s) {
System.out.println("Caught Sneeze");
return;
} finally {
System.out.println("Hello World!");
}
輸出:(父類throw出來的例外,子類并沒有捕獲到)
Hello World!
Exception in thread "main" com.xq.exceptions.Annoyance
at com.xq.exceptions.Human.main(ExceptionTest.java:14)
try {
throw new Annoyance();
} catch (Sneeze s) {
System.out.println("Caught Sneeze");
return;
} catch (Exception e) {
System.out.println("Caught Exception");
return;
} finally {
System.out.println("Hello World!");
}
輸出:(既然子類捕獲不了,那就使用Exception),可以看到結果如下:
Caught Exception
Hello World!
35、List、Set、Map是否繼承自Collection介面?
答:List、Set 是,Map 不是,Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存盤的零散的元素且不允許有重復元素(數學中的集合也是如此),List是線性結構的容器,適用于按數值索引訪問元素的情形,
36、Collection和Collections的區別?
答:Collection是一個介面,它是Set、List等容器的父介面;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操作,這些方法包括對容器的搜索、排序、執行緒安全化等等,
37、List、Map、Set三個介面存取元素時,各有什么特點?
答:List以特定索引來存取元素,可以有重復元素,Set不能存放重復元素(用物件的equals()方法來區分元素是否重復),Map保存鍵值對(key-value pair)映射,映射關系可以是一對一或多對一
38、Thread類的sleep()方法和物件的wait()方法都可以讓執行緒暫停執行,它們有什么區別?
答:sleep()方法(休眠)是執行緒類(Thread)的靜態方法,呼叫此方法會讓當前執行緒暫停執行指定的時間,將執行機會(CPU)讓給其他執行緒,但是物件的鎖依然保持,因此休眠時間結束后會自動恢復,wait()是Object類的方法,呼叫物件的wait()方法導致當前執行緒放棄物件的鎖(執行緒暫停執行),進入物件的等待池(wait pool),只有呼叫物件的notify()方法(或notifyAll()方法)時才能喚醒等待池中的執行緒進入等鎖池(lock pool),如果執行緒重新獲得物件的鎖就可以進入就緒狀態,
39、執行緒的sleep()方法和yield()方法有什么區別?
答:
① sleep()方法給其他執行緒運行機會時不考慮執行緒的優先級,因此會給低優先級的執行緒以運行的機會;yield()方法只會給相同優先級或更高優先級的執行緒以運行的機會;
② 執行緒執行sleep()方法后轉入阻塞(blocked)狀態,而執行yield()方法后轉入就緒(ready)狀態;
③ sleep()方法宣告拋出InterruptedException,而yield()方法沒有宣告任何例外;
④ sleep()方法比yield()方法(跟作業系統CPU調度相關)具有更好的可移植性,
40、當一個執行緒進入一個物件的synchronized方法A之后,其它執行緒是否可進入此物件的synchronized方法
B?
答:不能,其它執行緒只能訪問該物件的非同步方法,同步方法則不能進入,因為非靜態方法上的synchronized修飾符要求執行方法時要獲得物件的鎖,如果已經進入A方法說明物件鎖已經被取走,那么試圖進入B方法的執行緒就只能在等鎖池(注意不是等待池哦)中等待物件的鎖,
41、請說出與執行緒同步以及執行緒調度相關的方法,
答:
- wait():使一個執行緒處于等待(阻塞)狀態,并且釋放所持有的物件的鎖;
- sleep():使一個正在運行的執行緒處于睡眠狀態,是一個靜態方法,呼叫此方法要處理InterruptedException例外;
- notify():喚醒一個處于等待狀態的執行緒,當然在呼叫此方法的時候,并不能確切的喚醒某一個等待狀態的執行緒,而是由JVM確定喚醒哪個執行緒,而且與優先級無關;
- notityAll():喚醒所有處于等待狀態的執行緒,該方法并不是將物件的鎖給所有執行緒,而是讓它們競爭,只有獲得鎖的執行緒才能進入就緒狀態;
42、撰寫多執行緒程式有幾種實作方式?
答:一種是繼承Thread類;另一種是實作Runnable介面,兩種方式都要通過重寫run()方法來定義執行緒的行為,推薦使用后者,因為Java中的繼承是單繼承,一個類有一個父類,如果繼承了Thread類就無法再繼承其他類了,顯然使用Runnable介面更為靈活,
43、synchronized關鍵字的用法?
答:synchronized關鍵字可以將物件或者方法標記為同步,以實作對物件和方法的互斥訪問,可以用synchronized(物件) { … }定義同步代碼塊,或者在宣告方法時將synchronized作為方法的修飾符,
44、舉例說明同步和異步,
答:如果系統中存在臨界資源(資源數量少于競爭資源的執行緒數量的資源),例如正在寫的資料以后可能被另一個執行緒讀到,或者正在讀的資料可能已經被另一個執行緒寫過了,那么這些資料就必須進行同步存取(資料庫操作中的排他鎖就是最好的例子),當應用程式在物件上呼叫了一個需要花費很長時間來執行的方法,并且不希望讓程式等待方法的回傳時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率,事實上,所謂的同步就是指阻塞式操作,而異步就是非阻塞式操作,
45、簡述synchronized 和java.util.concurrent.locks.Lock的異同?
答:Lock是Java 5以后引入的新的API,和關鍵字synchronized相比主要相同點:Lock 能完成synchronized所實作的所有功能;主要不同點:Lock有比synchronized更精確的執行緒語意和更好的性能,而且不強制性的要求一定要獲得鎖,synchronized會自動釋放鎖,而Lock一定要求程式員手工釋放,并且最好在finally 塊中釋放(這是釋放外部資源的最好的地方)
46、事務的ACID是指什么?
答:
- 原子性(Atomic):事務中各項操作,要么全做要么全不做,任何一項操作的失敗都會導致整個事務的失敗;
- 一致性(Consistent):事務結束后系統狀態是一致的;
- 隔離性(Isolated):并發執行的事務彼此無法看到對方的中間狀態;
- 持久性(Durable):事務完成后所做的改動都會被持久化,即使發生災難性的失敗,通過日志和同步備份可以在故障發生后重建資料,
47、獲得一個類的類物件有哪些方式?
答:
-
方法1:型別.class,例如:String.class
-
方法2:物件.getClass(),例如:”hello”.getClass()
-
方法3:Class.forName(),例如:Class.forName(“java.lang.String”)
48、簡述一下面向物件的”六原則一法則”,
答:
-
單一職責原則:一個類只做它該做的事情,(單一職責原則想表達的就是”高內聚”,寫代碼最終極的原則只有六個字”高內聚、低耦合”,就如同葵花寶典或辟邪劍譜的中心思想就八個字”欲練此功必先自宮”,所謂的高內聚就是一個代碼模塊只完成一項功能,在面向物件中,如果只讓一個類完成它該做的事,而不涉及與它無關的領域就是踐行了高內聚的原則,這個類就只有單一職責,我們都知道一句話叫”因為專注,所以專業”,一個物件如果承擔太多的職責,那么注定它什么都做不好,這個世界上任何好的東西都有兩個特征,一個是功能單一,好的相機絕對不是電視購物里面賣的那種一個機器有一百多種功能的,它基本上只能照相;另一個是模塊化,好的自行車是組裝車,從減震叉、剎車到變速器,所有的部件都是可以拆卸和重新組裝的,好的乒乓球拍也不是成品拍,一定是底板和膠皮可以拆分和自行組裝的,一個好的軟體系統,它里面的每個功能模塊也應該是可以輕易的拿到其他系統中使用的,這樣才能實作軟體復用的目標,)
-
開閉原則:軟體物體應當對擴展開放,對修改關閉,(在理想的狀態下,當我們需要為一個軟體系統增加新功能時,只需要從原來的系統派生出一些新類就可以,不需要修改原來的任何一行代碼,要做到開閉有兩個要點:①抽象是關鍵,一個系統中如果沒有抽象類或介面系統就沒有擴展點;②封裝可變性,將系統中的各種可變因素封裝到一個繼承結構中,如果多個可變因素混雜在一起,系統將變得復雜
-
依賴倒轉原則:面向介面編程,
-
里氏替換原則:任何時候都可以用子型別替換掉父型別,(關于里氏替換原則的描述,Barbara Liskov女士的描述比這個要復雜得多,但簡單的說就是能用父型別的地方就一定能使用子型別,里氏替換原則可以檢查繼承關系是否合理,如果一個繼承關系違背了里氏替換原則,那么這個繼承關系一定是錯誤的,需要對代碼進行重構,例如讓貓繼承狗,或者狗繼承貓,又或者讓正方形繼承長方形都是錯誤的繼承關系,因為你很容易找到違反里氏替換原則的場景,需要注意的是:子類一定是增加父類的能力而不是減少父類的能力,因為子類比父類的能力更多,把能力多的物件當成能力少的物件來用當然沒有任何問題,)
-
介面隔離原則:介面要小而專,絕不能大而全,(臃腫的介面是對介面的污染,既然介面表示能力,那么一個介面只應該描述一種能力,介面也應該是高度內聚的,例如,琴棋書畫就應該分別設計為四個介面,而不應設計成一個介面中的四個方法,因為如果設計成一個介面中的四個方法,那么這個介面很難用,畢竟琴棋書畫四樣都精通的人還是少數,而如果設計成四個介面,會幾項就實作幾個介面,這樣的話每個介面被復用的可能性是很高的,Java中的介面代表能力、代表約定、代表角色,能否正確的使用介面一定是編程水平高低的重要標識,)
-
合成聚合復用原則:優先使用聚合或合成關系復用代碼,
-
迪米特法則:迪米特法則又叫最少知識原則,一個物件應當對其他物件有盡可能少的了解,(迪米特法則簡單的說就是如何做到”低耦合”,門面模式和調停者模式就是對迪米特法則的踐行,對于門面模式可以舉一個簡單的例子,你去一家公司洽談業務,你不需要了解這個公司內部是如何運作的,你甚至可以對這個公司一無所知,去的時候只需要找到公司入口處的前臺美女,告訴她們你要做什么,她們會找到合適的人跟你接洽,前臺的美女就是公司這個系統的門面,再復雜的系統都可以為用戶提供一個簡單的門面,Java Web開發中作為前端控制器的Servlet或Filter不就是一個門面嗎,瀏覽器對服務器的運作方式一無所知,但是通過前端控制器就能夠根據你的請求得到相應的服務,調停者模式也可以舉一個簡單的例子來說明,例如一臺計算機,CPU、記憶體、硬碟、顯卡、聲卡各種設備需要相互配合才能很好的作業,但是如果這些東西都直接連接到一起,計算機的布線將例外復雜,在這種情況下,主板作為一個調停者的身份出現,它將各個設備連接在一起而不需要每個設備之間直接交換資料,這樣就減小了系統的耦合度和復雜度,如下圖所示,迪米特法則用通俗的話來將就是不要和陌生人打交道,如果真的需要,找一個自己的朋友,讓他替你和陌生人打交道,)
49、簡述一下你了解的設計模式,
答:所謂設計模式,就是一套被反復使用的代碼設計經驗的總結(情境中一個問題經過證實的一個解決方案),使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
幾個常用的設計模式:
-
工廠模式:工廠類可以根據條件生成不同的子類實體,這些子類有一個公共的抽象父類并且實作了相同的方法,但是這些方法針對不同的資料進行了不同的操作(多型方法),當得到子類的實體后,開發人員可以呼叫基類中的方法而不必考慮到底回傳的是哪一個子類的實體,
-
代理模式:給一個物件提供一個代理物件,并由代理物件控制原物件的參考,
-
配接器模式:把一個類的介面變換成客戶端所期待的另一種介面,從而使原本因介面不匹配而無法在一起使用的類能夠一起作業,
-
單例模式:一個類只有一個實體,即一個類只有一個物件實體,
懶漢式單例模式,執行緒不安全,致命的是在多執行緒不能正常作業
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance(){
if (instance == null) instance = new Singleton();
return instance;
}
}
餓漢式單例模式,避免了多執行緒的同步問題
public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
50、用Java寫一個冒泡排序,
for(int i=0;i<arr.length-1;i++){//外層回圈控制排序趟數
for(int j=0;j<arr.length-1-i;j++){//內層回圈控制每一趟排序多少次
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
51、用Java寫一個二分查找,
非遞回實作:
```java
public static int biSearch(int []array,int a){
int lo=0;
int hi=array.length-1;
int mid;
while(lo<=hi){
mid=(lo+hi)/2;
if(array[mid]==a){
return mid+1;
}else if(array[mid]<a){
lo=mid+1;
}else{
hi=mid-1;
}
}
return -1;
}
遞回實作:
public static int sort(int []array,int a,int lo,int hi){
if(lo<=hi){
int mid=(lo+hi)/2;
if(a==array[mid]){
return mid+1;
}
else if(a>array[mid]){
return sort(array,a,mid+1,hi);
}else{
return sort(array,a,lo,mid-1);
}
}
return -1;
}
52、Servlet的運行程序?
Web容器加載Servlet并將其實體化后,Servlet生命周期開始,容器運行其init()方法進行Servlet的初始化;請求到達時呼叫Servlet的service()方法,service()方法會根據需要呼叫與請求對應的doGet或doPost等方法;當服務器關倍訓專案被卸載時服務器會將Servlet實體銷毀,此時會呼叫Servlet的destroy()方法,
53、轉發(forward)和重定向(redirect)的區別?
答:forward是容器中控制權的轉向,是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL 的回應內容讀取過來,然后把這些內容再發給瀏覽器,瀏覽器根本不知道服務器發送的內容是從哪兒來的,所以它的地址欄中還是原來的地址,redirect就是服務器端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址,因此從瀏覽器的地址欄中可以看到跳轉后的鏈接地址,很明顯redirect無法訪問到服務器保護起來資源,但是可以從一個網站redirect到其他網站,forward更加高效,所以在滿足需要時盡量使用forward(通過呼叫RequestDispatcher物件的forward()方法,該物件可以通過ServletRequest物件的getRequestDispatcher()方法獲得),并且這樣也有助于隱藏實際的鏈接;在有些情況下,比如需要訪問一個其它服務器上的資源,則必須使用重定向(通過HttpServletResponse物件呼叫其sendRedirect()方法實作),
54、JSP有哪些內置物件?作用分別是什么?
答:JSP有9個內置物件:
- request:封裝客戶端的請求,其中包含來自GET或POST請求的引數;
- response:封裝服務器對客戶端的回應;
- pageContext:通過該物件可以獲取其他物件;
- session:封裝用戶會話的物件;
- application:封裝服務器運行環境的物件;
- out:輸出服務器回應的輸出流物件;
- config:Web應用的配置物件;
- page:JSP頁面本身(相當于Java程式中的this);
- exception:封裝頁面拋出例外的物件,
55、講解JSP中的四種作用域,
答:JSP中的四種作用域包括page、request、session和application,具體來說:
-
page代表與一個頁面相關的物件和屬性,
-
request代表與Web客戶機發出的一個請求相關的物件和屬性,一個請求可能跨越多個頁面,涉及多個Web組件;需要在頁面顯示的臨時資料可以置于此作用域,
-
session代表與某個用戶與服務器建立的一次會話相關的物件和屬性,跟某個用戶相關的資料應該放在用戶自己的session中,
-
application代表與整個Web應用程式相關的物件和屬性,它實質上是跨越整個Web應用程式,包括多個頁面、請求和會話的一個全域作用域,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/232027.html
標籤:java
