牛客刷題筆記--(java基礎301-400)
301 不考慮反射機制,一個子類顯式呼叫父類的構造器必須用super關鍵字。( √ )
子類顯示呼叫父類中的構造方法必須使用super關鍵字;如果子類沒有顯示呼叫父類中的構造方法,則系統預設會呼叫父類中的無參構造方法;若此時父類中沒有定義無參構造方法則會報錯。
java中的super關鍵詞
super用於代表子類的直接父類的特徵
super可以訪問:
父類的成員變數,成員方法,構造方法
使用super關鍵詞的情況:
在子類中,存在與父類相同的屬性和方法,由於訪問子類中屬性和方法的優先順序高於父類,可以通過super關鍵詞來訪問父類中的屬性和方法
在子類中,可以通過super關鍵詞來顯示的呼叫父類的構造方法
子類的構造方法預設呼叫父類的無參構造方法,當父類中不存在無參構造方法時,可以同過super來呼叫父類的有參構造方法來避免編譯時錯誤。
302 在java中,無論在何處呼叫,使用靜態屬性必須以類名做字首。(×)
如果是本類使用,可以直接就用靜態變數名。2如果是其他類使用,可以使用類名來呼叫,也可以建立一個例項物件來呼叫。3如果靜態變數所在的類是靜態類,那麼不管在本類裡或者在其他外部類,都可以直接使用靜態變數名。
在靜態類裡面呼叫類成員變數,不需要類名字首、。
303 下面關於Java package的描述,哪個是正確的:(B)
I. 包不提供將所有類名分割槽為更易管理的塊的機制.
II. 包提供可見性控制機制.
III. 包的一個重要屬性是包內定義的所有類都可以通過該包外的程式碼訪問.
IV. 宣告為包的一部分的類的.class檔案可以儲存在多個目錄中.
只有I
只有II
只有III
只有IV
Java 提供了包機制,用於區別類名的名稱空間,訪問控制。
包名必須與相應的位元組碼所在的目錄結構相吻合。
為了更好地組織類,Java 提供了包機制,用於區別類名的名稱空間。
包的作用
1、把功能相似或相關的類或介面組織在同一個包中,方便類的查詢和使用。
2、如同資料夾一樣,包也採用了樹形目錄的儲存方式。同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時呼叫兩個不同包中相同類名的類時,應該加上包名加以區別。因此,包可以避免名字衝突。
3、包也限定了訪問許可權,擁有包訪問許可權的類才能訪問某個包中的類。
Java 使用包(package)這種機制是為了防止命名衝突,訪問控制,提供搜尋和定位類(class)、介面、列舉(enumerations)和註釋(annotation)等。
304 java語言的下面幾種陣列複製方法中,哪個效率最高?(B)
for 迴圈逐一複製
System.arraycopy
Array.copyOf
使用clone方法
複製的效率System.arraycopy>clone>Arrays.copyOf>for迴圈,這個有興趣自己測試一下就知道了。這裡面在System類原始碼中給出了arraycopy的方法,是native方法,也就是本地方法,肯定是最快的。而Arrays.copyOf(注意是Arrays類,不是Array)的實現,Arrays.copyOf方法中呼叫的是System.arraycopy方法!,多了一個步驟,肯定就不是最快的
總結:
(1)從速度上看:System.arraycopy > clone > Arrays.copyOf > for
(2)for的速度之所以最慢是因為下標表示法每次都從起點開始尋位到指定下標處(現代編譯器應該對其有進行優化,改為指標),另外就是它每一次迴圈都要判斷一次是否達到陣列最大長度和進行一次額外的記錄下標值的加法運算。
(3)檢視Arrays.copyOf的原始碼可以發現,它其實本質上是呼叫了System.arraycopy。之所以時間差距比較大,是因為很大一部分開銷全花在了Math.min函式上了。
305 Thread. sleep()是否會丟擲checked exception?(會)
Thread.sleep() 和 Object.wait(),都可以丟擲 InterruptedException。這個異常是不能忽略的,因為它是一個檢查異常(checked exception)
checked exception:指的是編譯時異常,該類異常需要本函式必須處理的,用try和catch處理,或者用throws丟擲異常,然後交給呼叫者去處理異常。
runtime exception:指的是執行時異常,該類異常不必須本函式必須處理,當然也可以處理。
Thread.sleep()丟擲的InterruptException屬於checked exception;IllegalArgumentException屬於Runtime exception;
Thread.sleep()會丟擲InterruptedException,這個屬於checked exception,也就是編譯時異常,我們必須顯式的捕獲異常而不能繼續上外層丟擲,因為這個異常需要該執行緒自己來解決。
306 下列關於JavaBean的說法正確的是:(A)
Java檔案與Bean所定義的類名可以不同,但一定要注意區分字母的大小寫
在JSP檔案中引用Bean,其實就是用語句
被引用的Bean檔案的檔名字尾為.java
Bean檔案放在任何目錄下都可以被引用
(1)懂得將 Bean 放在哪個目錄下:在 Resin 中 JavaBean 放在 doc\web-inf\classes 目錄 中。
(2)懂得如何使用 JBuilder 定義一個 Bean;其中的語法規範不一定要記住,但要理解
其中的結構。
(3)Java 檔案和 Bean所定義的類名一定要相同,並且是大小寫敏感。
(4)Bean中要宣告公共方法,與 Bean的名字相同。
(5)懂得如何在JSP 檔案中引用JavaBean,其實就是jsp:useBean的語句。
(6)一定要緊記Java 是區分大小寫的。
A: Bean定義的類名的含義應該是例項化的一個類,在JSP中相當於id,class屬性對應的是需要編譯的類,在後面用到id的例項化類名 需要區分大小寫
B: 是宣告瞭一個Bean 不是引用
C: 引用的檔案是web-Inf\class\下的class檔案
D: 需要放在web-Inf\class\
307 ResultSet中記錄行的第一列索引為?(1)
ResultSet結果集讀取資料的方法主要是getXXX() ,他的引數可以使整型表示第幾列(是從1開始的),還可以是列名。
Java ResultSet 概論
308 What might cause the current thread to stop or pause executing(ABE)
An InterruptedException is thrown.
The thread executes a wait() call.
The thread constructs a new Thread.
A thread of higher priority becomes ready.
The thread executes a waitforID()call on a MediaTracker.
題目:什麼操作會使得當前執行緒停止。
A:一個InterruptedException 異常被捕獲 大家都知道的嘛 (一般通過interrupt方法 中斷執行緒) 如果抓到一個執行緒 都會關緊catch裡面 然後中斷當前操作,A正確。
B:執行緒執行了wait()方法。 執行緒使用了wait方法,會強行打斷當前操作,(暫停狀態,不會中斷執行緒) 進入阻塞(暫停)狀態,然後需要notify方法或notifyAll方法才能進入就緒狀態。 B 正確。
C:當前執行緒建立了一個新的執行緒。 新建立的執行緒不會搶佔時間片,只有等當前執行緒把時間片用完,其他執行緒才有資格拿到時間片去執行。
D:一個高優先順序別的執行緒就緒。 如C相同,你優先順序別再高 也待等我現在弄完才會給你。(就像我們玩遊戲,會員雖然有排隊優先權,但是還是要等正在登陸的使用者進去遊戲之後才能搶到他原來那個位置,不能說我在過關卡的過程中你一腳把我踢開,然後霸佔我的位置吧,我原來的那些資料咋辦!!!)
E:執行緒在MediaTracker上執行了waitforID()呼叫。
這個應該大家也不太熟悉。這個類是awt裡面的,我查API才知道。
然後他的功能是載入影像,直到完成之前,該方法一直等待!這個方法是必須要丟擲A選項的InterruptedException 異常的 說明這玩意會讓其他執行緒 wait他完成! 所以會暫停當前執行緒~~大概是這樣吧哈哈哈! E選項我沒選對! 這還是真的!。!
309 以下說法錯誤的是(C)
陣列是一個物件
陣列不是一種原生類
陣列的大小可以任意改變
在Java中,陣列儲存在堆中連續記憶體空間裡
在java中,陣列是一個物件, 不是一種原生類,物件所以存放在堆中,又因為陣列特性,是連續的,只有C不對
Java中陣列是物件,不是基本資料型別(原生類),大小不可變且連續儲存,因為是物件所以存在堆中。
陣列長度在建立時就確定了,要改變陣列長度只能重新建立新的陣列,將原有陣列複製到新的陣列之中。這也是ArrayList擴容時候的效率低於LinkedList的原因。
310 Web程式中,當前使用者上下文資訊應該儲存在下面哪個物件中(C)
page
request
session
Application
JSP 四大作用域: page (作用範圍最小)、request、session、application(作用範圍最大)。
儲存在application物件中的屬性可以被同一個WEB應用程式中的所有Servlet和JSP頁面訪問。(屬性作用範圍最大)
儲存在session物件中的屬性可以被屬於同一個會話(瀏覽器開啟直到關閉稱為一次會話,且在此期間會話不失效)的所有Servlet和JSP頁面訪問。
儲存在request物件中的屬性可以被屬於同一個請求的所有Servlet和JSP頁面訪問(在有轉發的情況下可以跨頁面獲取屬性值),例如使用PageContext.forward和PageContext.include方法連線起來的多個Servlet和JSP頁面。
儲存在pageContext物件中的屬性僅可以被當前JSP頁面的當前響應過程中呼叫的各個元件訪問,例如,正在響應當前請求的JSP頁面和它呼叫的各個自定義標籤類。
當前使用者上下文資訊:session
appication:當前應用
pageContext:當前頁面
request:當前請求
重點在 當前使用者 , application能被同一個應用程式的所有使用者訪問,所以當前使用者的資訊就不宜儲存在application中
session會話物件,一個會話只可能是一個使用者的,生命週期預設30分鐘,也可以自行定義,當前會話結束(如關閉瀏覽器),當前session被銷燬。所以當前使用者的資訊應該儲存在session中
311 下列哪個選項是Java偵錯程式?如果編譯器返回程式程式碼的錯誤,可以用它對程式進行除錯。©
java.exe
javadoc.exe
jdb.exe
javaprof.exe
javac.exe是編譯.java檔案
java,exe是java虛擬機器
javadoc.exe用來製作java文件
jdb.exe是java的偵錯程式
javaprof,exe是剖析工具
312 下面哪一項不是載入驅動程式的方法?(A)
通過DriverManager.getConnection方法載入
呼叫方法 Class.forName
通過新增系統的jdbc.drivers屬性
通過registerDriver方法註冊
載入驅動方法
1.Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”);
2. DriverManager.registerDriver(new com.mysql.jdbc.Driver());
3.System.setProperty(“jdbc.drivers”, “com.mysql.jdbc.Driver”);
313在Java中,關於HashMap類的描述,以下錯誤的是(A)?
HashMap能夠保證其中元素的順序
HashMap允許將null用作值
HashMap允許將null用作鍵
HashMap使用鍵/值得形式儲存資料
HashMap的底層是由陣列加連結串列實現的,對於每一個key值,都需要計算雜湊值,然後通過雜湊值來確定順序,並不是按照加入順序來存放的,因此可以認為是無序的,但不管是有序還是無序,它都一個自己的順序。故A錯。
最開始有Hashtable,Hashtable是不允許key和value的值為空的,但後來開發者認為有時候也會有key值為空的情況,因為可以允許null為空,通過檢視HashMap的原始碼就知道:if(key = null) {putForNullKey(value);};
Map底層都是用key/value鍵值對的形式存放的
HashMap(集合)中值的儲存是無序的,依靠鍵值來存取元素,一個鍵對應一個值,就是說通過鍵來找值,並且鍵值都可為空
A.HashMap不能保證元素的順序,而LinkedHashMap可以保持資料的插入順序,TreeMap可以按照鍵值進行排序(可自定比較器)
B.HashMap允許存在多條null值
C.HashMap允許且僅允許一條null鍵
D.Map就是通過鍵/值形式儲存資料的
314 Which lines of the following will produce an error?A
1. byte a1 = 2, a2 = 4, a3;
2. short s = 16;
3. a2 = s;
4. a3 = a1 * a2;
Line 3 and Line 4
Line 1 only
Line 3 only
Line 4 only
short型別轉為byte型別出錯
a1*a2結果為int型別,轉為byte型別出錯
數值型變數在預設情況下為Int型,byte和short型在計算時會自動轉換為int型計算,結果也是int 型。所以a1*a2的結果是int 型的。
byte+byte=int,低階向高階是隱式型別轉換,高階向低階必須強制型別轉換,byte<char<short<int<long<float<double
315 當編譯並執行下面程式時會發生什麼結果(D)
public class Bground extends Thread{
public static void main(String argv[]){
Bground b = new Bground();
b.run();
}
public void start(){
for(int i=0;i<10;i++){
System.out.println("Value of i = "+i);
}
}
}
編譯錯誤,指明run方法沒有定義
執行錯誤,只鞥呢run方法沒有定義
編譯通過並輸出0到9
編譯通過,但無輸出
對於執行緒而言,start是讓執行緒從new變成runnable。run方法才是執行體的入口。
但是在Thread中,run方法是個空方法,沒有具體實現。
Bground繼承了Thread,但是沒有重寫run方法,那麼呼叫run方法肯定是無輸出。
這題可以用物件導向的思想即可解決
首先繼承Thread,然後呼叫run方法,bgroud並沒有重寫run方法,那麼就是呼叫父類Thread的run方法。
然後檢視父類程式碼
@Override
public void run() {
if (target != null) {
target.run();
}
}
private Runnable target;
其中target是Runnable物件
明顯target並沒有顯示初始化。
所以不會有顯示。
一般target的初始化是這樣的,將runnable物件作為thread引數進行執行緒的建立
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
再看init()
private void init(ThreadGroup g, Runnable target,String name,long stackSize) {
init(g, target, name, stackSize, null);
}
在init(g, target, name, stackSize, null),可以找到this.target = target;
此時進行了初始化。
最後說一說,Thread 的執行過程,Theard的啟動方法是start().執行緒類呼叫start();然後執行start0()本地方法,然後就沒辦法再追溯下去了。
start我聽過別人說,是一個準備工作(比如你要吃蘋果,不得先洗一下,真正吃時間是洗完後),並沒有獲得cpu,呼叫run()才是獲得了cpu
316 執行程式碼,輸出的結果是(A)
public class P {
public static int abc = 123;
static{
System.out.println("P is init");
}
}
public class S extends P {
static{
System.out.println("S is init");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(S.abc);
}
}
P is init<br />123
S is init<br />P is init<br />123
P is init<br />S is init<br />123
S is init<br />123
屬於被動引用不會出發子類初始化
1.子類引用父類的靜態欄位,只會觸發子類的載入、父類的初始化,不會導致子類初始化
2.通過陣列定義來引用類,不會觸發此類的初始化
3.常量在編譯階段會進行常量優化,將常量存入呼叫類的常量池中, 本質上並沒有直接引用到定義常量的類,因此不會觸發定義常量的類的初始化。
不會初始化子類的幾種
- 呼叫的是父類的static方法或者欄位
2.呼叫的是父類的final方法或者欄位 - 通過陣列來引用
子類引用父類的靜態欄位,只會觸發子類的載入、父類的初始化,不會導致子類初始化
而靜態程式碼塊在類初始化的時候執行!!
經過程式碼測試:
當直接new 子類 建立時的執行順序為:父類靜態塊、子類靜態塊、父類構造方法、子類構造方法。
當new建立子類陣列時,不載入任何東西
當用父類名呼叫父類靜態變數、方法時:載入父類靜態塊
當用子類名呼叫父類靜態變數、方法時:載入父類靜態塊
當用子類名呼叫子類特有靜態變數、方法時:載入父類靜態塊、載入子類靜態塊
觸發類初始化:
訪問類的靜態元素(包括靜態成員變數,靜態方法,建構函式)
子類初始化時會優先為父類初始化
只要記住,載入跟初始化不是一回事就好了,使用類的時候,不管怎樣,這個類必須已經載入到記憶體當中了,然而初始化沒有,就不好說了。被動引用不會觸發初始化,也就不會觸發static{}程式碼塊。
317 以下程式碼可以使用的修飾符是:(ABD)
public interface Status {
/*INSERT CODE HERE*/ int MY_VALUE=10;
}
final
static
abstract
public
abstract只能修飾類和方法 不能修飾欄位
介面中欄位的修飾符:public static final(預設不寫)
介面中方法的修飾符:public abstract(預設不寫)
318以下哪些記憶體區域屬於JVM規範?( ADE)
方法區
例項變數
靜態變數
程式計數器
虛擬機器棧
JVM記憶體區:程式計數器、虛擬機器棧、本地方法棧、堆、方法區(包括常量池)。
不屬於JVM記憶體區:直接記憶體(Direct Memory),使用者I/O操作
319關於volatile關鍵字,下列描述不正確的是?BD
用volatile修飾的變數,每次更新對其他執行緒都是立即可見的。
對volatile變數的操作是原子性的。
對volatile變數的操作不會造成阻塞。
不依賴其他鎖機制,多執行緒環境下的計數器可用volatile實現。
一旦一個共享變數(類的成員變數、類的靜態成員變數)被volatile修飾之後,那麼就具備了兩層語義:
1)保證了不同執行緒對這個變數進行操作時的可見性,即一個執行緒修改了某個變數的值,這新值對其他執行緒來說是立即可見的。
2)禁止進行指令重排序。
volatile只提供了保證訪問該變數時,每次都是從記憶體中讀取最新值,並不會使用暫存器快取該值——每次都會從記憶體中讀取。
而對該變數的修改,volatile並不提供原子性的保證。
由於及時更新,很可能導致另一執行緒訪問最新變數值,無法跳出迴圈的情況
多執行緒下計數器必須使用鎖保護。
所謂 volatile的措施,就是
- 每次從記憶體中取值,不從快取中什麼的拿值。這就保證了用 volatile修飾的共享變數,每次的更新對於其他執行緒都是可見的。
- volatile保證了其他執行緒的立即可見性,就沒有保證原子性。
3.由於有些時候對 volatile的操作,不會被儲存,說明不會造成阻塞。不可用與多執行緒環境下的計數器。
320 Java Application(Java 應用程式)源程式檔案編譯後的位元組碼檔案的副檔名是( B )。
java
class
exe
jar
A: .java是java程式的原始碼檔案 B: .class不是類的副檔名,JVM並不能直接執行java原始檔,需要通過javac將java原始檔編譯成位元組碼檔案,也就是.class檔案,JVM在執行某個類的時候,通過載入指定該.class檔案就可以,因為class檔名與類名相同,但是他倆並不是一回事,執行的是類,不是檔案。 C: java可以編寫成.exe,雖然是exe檔案,但是不代表是windows可執行檔案,儘管副檔名一樣 D: 可以打包成jar,需要有jdk支援,通過JVM執行,這個才是java真正的執行包。
java檔案的原始碼的字尾是.java
1, Java檔案經過JVM編譯成位元組碼檔案,即.class檔案,將位元組碼檔案在不同的作業系統中執行時,作業系統再將位元組碼檔案編譯成機器碼檔案。這就是Java跨平臺
2, JAR 檔案就是 Java Archive File,顧名思意,它的應用是與 Java 息息相關的,是 Java 的一種文件格式。JAR 檔案非常類似 ZIP 檔案——準確的說,它就是 ZIP 檔案,所以叫它檔案包。JAR 檔案與 ZIP 檔案唯一的區別就是在 JAR 檔案的內容中,包含了一個 META-INF/MANIFEST.MF 檔案,這個檔案是在生成 JAR 檔案的時候自動建立的
321 請問以下程式碼執行結果是:D
try catch
try finally catch
try finally
try catch finally
throws:寫在方法宣告之後,表示方法可能丟擲異常,呼叫者需要處理這個異常。
throw:寫在方法體中,表示方法一定會丟擲一個異常,要麼try…catch處理,要麼throws丟擲。
結果為try catch finally,執行過程如下: 在執行到try程式碼塊中,首先輸出try,然後丟擲異常,直接跳轉到catch中,輸出catch,然後跳轉到finally塊中,輸出finally。
322 從執行層面上來看,從四個選項選出不同的一個。B
JAVA
Python
objectC
C#
A,C,D都是類C語言,B不是 Python是解釋執行的,其他語言都需要先編譯
Python 只有它是動態語言
動態語言的定義:動態程式語言 是 高階程式設計語言 的一個類別,在電腦科學領域已被廣泛應用。它是一類 在 執行時可以改變其結構的語言 :例如新的函式、物件、甚至程式碼可以被引進,已有的函式可以被刪除或是其他結構上的變化。動態語言目前非常具有活力。眾所周知的 ECMAScript ( JavaScript )便是一個動態語言,除此之外如 PHP 、 Ruby 、 Python 等也都屬於動態語言,而 C 、 C++ 等語言則不屬於動態語言。
強型別strongly typed: 如果一種語言的所有程式都是well behaved——即不可能出現forbidden behaviors,則該語言為strongly typed。
弱型別weakly typed: 否則為weakly typed。比如C語言的緩衝區溢位,屬於trapped errors,即屬於forbidden behaviors…故C是弱型別
前面的人也說了,弱型別語言,型別檢查更不嚴格,如偏向於容忍隱式型別轉換。譬如說C語言的int可以變成double。 這樣的結果是:容易產生forbidden behaviours,所以是弱型別的
動態、靜態型別
靜態型別 statically: 如果在編譯時拒絕ill behaved程式,則是statically typed;
動態型別dynamiclly: 如果在執行時拒絕ill behaviors, 則是dynamiclly type
323以下JAVA程式程式碼的輸出是C
public static void main(String args[]) {
System.out.println(17^5);
}
12
22
20
1419857
位異運算子號。
運算規則是:兩個數轉為二進位制,然後從高位開始比較,如果相同則為0,不相同則為1。
17:0001 0001
5: 0000 0101
結果:0001 0100 轉10進位制:20
&按位與 |按位或 ~取反 ^異或
324 下面敘述那個是正確的?(B)
java中的集合類(如Vector)可以用來儲存任何型別的物件,且大小可以自動調整。但需要事先知道所儲存物件的型別,才能正常使用。
在java中,我們可以用違例(Exception)來丟擲一些並非錯誤的訊息,但這樣比直接從函式返回一個結果要更大的系統開銷。
java介面包含函式宣告和變數宣告。
java中,子類不可以訪問父類的私有成員和受保護的成員。
B選項說的情況就是我們自定義異常的情況,請仔細讀:我們可以用違例(Exception)來丟擲一些並非錯誤的訊息,可以,並非錯誤的訊息。比如我自定義一個異常,若一個變數大於10就丟擲一個異常,這樣就對應了B選項說的情況,我用丟擲異常說明這個變數大於10,而不是用一個函式體(函式體內判斷是否大於10,然後返回true或false)判斷,因為函式呼叫是入棧出棧,棧是在暫存器之下的速度最快,且佔的空間少,而自定義異常是存在堆中,肯定異常的記憶體開銷大!所以B對。
C選項說的是介面包含方法宣告和變數宣告。因為介面中方法預設是 abstract public,所以在介面只寫函式宣告是符合語法規則。但是變數預設是用public final static 修飾的,意思它是靜態常量,常量不管在介面中還是類中必須在宣告時初始化!所以C的後半句是錯的,必須在宣告時並給出初始化!
介面中只有常量定義,沒有變數宣告。
A.vector是執行緒安全的ArrayList,在記憶體中佔用連續的空間。初始時有一個初始大小,當資料條數大於這個初始大小後會重寫分配一個更大的連續空間。如果Vector定義為儲存Object則可以存放任意型別。
B.try{}catch{}會增加額外的開銷
C.介面中宣告的’變數’必須為public final static,所以為常量
D.子類可以訪問父類受保護的成員
325下面哪些語法結構是正確的?AC
public class A extends B implements C
public class A implements A B
public class A implements B,C,D
public implements B
A選項- 標準寫法,正確
public class A extends B implements C
B選項- implements接的是介面類 而A此處的定義又是class
迴圈矛盾,必然錯誤
public class A implements A B
C選項- 正確,一個類可以實現多個介面
public class A implements B,C,D
D選項- 錯誤。
public implements B
另外補充一點,如果一個類既繼承了某個基類,又實現了介面。那麼extends關鍵字必須在implements之前。
繼承只能有一個,介面可以有多個
326 下面程式碼將輸出什麼內容:(B)
public class SystemUtil{
public static boolean isAdmin(String userId){
return userId.toLowerCase()=="admin";
}
public static void main(String[] args){
System.out.println(isAdmin("Admin"));
}
}
true
false
1
編譯錯誤
equals和==的區別 ==操作比較的是兩個變數的值是否相等,對於引用型變數表示的是兩個變數在堆中儲存的地址是否相同,即棧中的內容是否相同。
在原始碼中 toLowerCase 是重新 new String()
所以為 == 是比較物件是否是同一個物件,所以為 false 。
首先要知道toLowerCase()的底層實現是
return new String(result, 0, len + resultOffset);
所以底層new 了一個新的字串並且返回。
因為0x0003 不等於0x0002 ,所以返回false,如果是equals 則返回true
因為== 比較的是地址。
equals 比較的話 先比較地址,如果相等,直接返回true
然後看比較的物件是不是String型別,如果不是直接返回false
如果是的話,則依次比較每個字元,如果全部相等,則返回true
327 What will happen when you attempt to compile and run the following code?D
public class Test{
static{
int x=5;
}
static int x,y;
public static void main(String args[]){
x--;
myMethod( );
System.out.println(x+y+ ++x);
}
public static void myMethod( ){
y=x++ + ++x;
}
}
compiletime error
prints:1
prints:2
prints:3
prints:7
prints:8
1.靜態語句塊中x為區域性變數,不影響靜態變數x的值
2.x和y為靜態變數,預設初始值為0,屬於當前類,其值得改變會影響整個類執行。
3.java中自增操作非原子性的
main方法中:
執行x--後 x=-1
呼叫myMethod方法,x執行x++結果為-1(後++),但x=0,++x結果1,x=1 ,則y=0
x+y+ ++x,先執行x+y,結果為1,執行++x結果為2,得到最終結果為3
328 抽象類方法的訪問許可權預設都是public。( × )
關於抽象類
JDK 1.8以前,抽象類的方法預設訪問許可權為protected
JDK 1.8時,抽象類的方法預設訪問許可權變為default
關於介面
JDK 1.8以前,介面中的方法必須是public的
JDK 1.8時,介面中的方法可以是public的,也可以是default的
JDK 1.9時,介面中的方法可以是private的
329 關於JSP生命週期的敘述,下列哪些為真?AC
JSP會先解釋成Servlet原始檔,然後編譯成Servlet類檔案
每當使用者端執行JSP時,jsp init()方法都會執行一次
每當使用者端執行JSP時,jsp service()方法都會執行一次
每當使用者端執行JSP時,jsp destroy()方法都會執行一次
Jsp只會在客戶端第一次發請求的時候被編譯,之後的請求不會再編譯,同時tomcat能自動檢測jsp變更與否,變更則再進行編譯。
第一次編譯並初始化時呼叫: init() ;銷燬呼叫: destroy() 。在整個jsp生命週期中均只呼叫一次。
service()方法是接收請求,返回響應的方法。每次請求都執行一次,該方法被HttpServlet封裝為doGet和doPost方法
servlet生命週期:init 、service、destory
除了init只初始化一次外、其他 使用者端執行JSP時方法都會執行一次
330下面程式的輸出是:(D)
String x="fmn";
x.toUpperCase();
String y=x.replace('f','F');
y=y+"wxy";
System.out.println(y);
FmNwxy
fmnwxy
wxyfmn
Fmnwxy
String x=“fmn”; “fmn”是在常量池裡的不可變物件。
x.toUpperCase(); 在堆中new一個"FMN"物件,但無任何引用指向它。
String y=x.replace(‘f’,‘F’); 在堆中 new一個"Fmn"物件,y指向它。
y=y+“wxy”; 在堆中 重新new一個"Fmnwxy"物件, 修改y指向,現在y指向它。
本題主要考察String物件的不可變性。
toUpperCase()會對當前物件進行檢查 如果不需要轉換直接返回當前物件,否則new一個新物件返回;
replace()如果兩個引數相同,則直接返回,否則new一個新物件,所以這裡y指向"Fmn";
y=y+“wxy” 這裡修改y所指向的字串物件,讓它由指向"Fmn"變成指向"Fmnxyz".
331 列舉(enum)屬於原始資料型別(primitive type)(X)
在Java中,變數有兩種型別,一種是原始型別,一種是引用型別。
原始型別一共有8種,它們分別是char,boolean,byte,short,int,long,float,double。在Java API中,有它們對應的包裝類,分別是(首字母大寫)Character,Boolean,Byte,Short,Integer,Long,Float,Double(char,int的變化稍微大點)。
JAVA JVM對於不同的原始型別會分配不同的儲存空間,具體分配如下:
byte : 1個位元組 8位
最大值: 127 (有符號)
short : 2個位元組 16位 32767
int : 4個位元組 32位 2147483647
long: 8個位元組 64位 9223372036854775807
float: 4個位元組 32位 3.4028235E38
double:8個位元組 64位 1.7976931348623157E308
列舉(enum)型別是Java 5新增的特性,它是一種新的型別,允許用常量來表示特定的資料片斷,而且全部都以型別安全的形式來表示,是特殊的類,可以擁有成員變數和方法。
列舉類是一種特殊的類,既然是類。那他就不是原始資料型別了
Java語言提供了八種基本型別。六種數字型別(四個整數型,兩個浮點型),一種字元型別,還有一種布林型。
byte,short,int,long,float,double,boolean,char.
332 關於ASCII碼和ANSI碼,以下說法不正確的是(D)?
標準ASCII只使用7個bit
在簡體中文的Windows系統中,ANSI就是GB2312
ASCII碼是ANSI碼的子集
ASCII碼都是可列印字元
A、標準ASCII只使用7個bit,擴充套件的ASCII使用8個bit。
B、ANSI通常使用 0x00~0x7f 範圍的1 個位元組來表示 1 個英文字元。超出此範圍的使用0x80~0xFFFF來編碼,即擴充套件的ASCII編碼。不同 ANSI 編碼之間互不相容。在簡體中文Windows作業系統中,ANSI 編碼代表 GBK 編碼;在繁體中文Windows作業系統中,ANSI編碼代表Big5;在日文Windows作業系統中,ANSI 編碼代表 Shift_JIS 編碼。
C、ANSI通常使用 0x00~0x7f 範圍的1 個位元組來表示 1 個英文字元,即ASCII碼
D、ASCII碼包含一些特殊空字元
333有如下一段程式碼,請選擇其執行結果(C)
public class StringDemo{
private static final String MESSAGE="taobao";
public static void main(String [] args) {
String a ="tao"+"bao";
String b="tao";
String c="bao";
System.out.println(a==MESSAGE);
System.out.println((b+c)==MESSAGE);
}
}
true true
false false
true false
false true
要注意兩個問題:
1,字串在java中儲存在字串常量區中
2,==判斷的是物件引用是否是同一個引用,判斷字串相等要用equals方法
首先判斷a==MESSAGE 同一份字串常量在記憶體中只有一份,因此是同一地址,返回true
再次比較(b+c)==MESSAGE 這相當於 new String(b+c)==MESSAGE 這裡new了一個String物件,所以返回false
334 以下哪幾個是java中的集合型別?ABD
Vector
Set
String
List
335 假定Base b = new Derived(); 呼叫執行b.methodOne()後,輸出結果是什麼? A
public class Base
{
public void methodOne()
{
System.out.print("A");
methodTwo();
}
public void methodTwo()
{
System.out.print("B");
}
}
public class Derived extends Base
{
public void methodOne()
{
super.methodOne();
System.out.print("C");
}
public void methodTwo()
{
super.methodTwo();
System.out.print("D");
}
}
ABDC
AB
ABCD
ABC
只要是被子類重寫的方法,不被super呼叫都是呼叫子類方法
關於子類繼承父類中方法的呼叫,只要不是用super呼叫,呼叫的都是子類中覆寫父類的方法。
如果將這道題目修改一下,將父類中的methodTwo()改成靜態方法,程式碼如下:
結果為:ABC
這是一道類多型的向上轉型題。
Base b = new Derived();
向上轉型:父類只能呼叫父類方法或者子類覆寫後的方法,而子類中的單獨方法則是無法呼叫的。
因此:
呼叫的順序是:(1)、(2)、(3)、(4)、(5)、(6)、(7) ; 得到的結果是:ABDC
class Base
{ public void methodOne() // (3)
{
System.out.print("A");
methodTwo(); //執行到這裡的時候呼叫子類的覆蓋方法 (4)
} public void methodTwo() // (7)
{
System.out.print("B");
}
}
class Derived extends Base { public void methodOne() // (1)
{ super.methodOne(); // (2)
System.out.print("C");
} public void methodTwo() //該方法為重寫了父類的方法 (5)
{ super.methodTwo(); //(6)
System.out.print("D");
}
}
繼承關係中,用多型建立子類物件,我們在呼叫一個父類被子類重寫的方法時,不管是在子類中呼叫還是在父類中呼叫,不被super呼叫都是呼叫子類方法,只有用super呼叫時才是呼叫父類的方法。
336 StringBuffer類物件建立之後可以再修改和變動.(√)
String,StringBuffer,StringBuilder,都實現了CharSequence介面。
String是個不可繼承類(final修飾),也是個不可變類(內部char陣列被final修飾)。
StringBuffer和StringBuilder內部都是一般的動態陣列,所以可變。前者是執行緒安全的,因為方法基本都被synchronized修飾了。
stringbuffer是可變長度的,可通過append,insert,remove等方法改變其長度
1.String物件不可變、StringBuffer物件可變的含義: 舉個例子:String str = “aa”; str = “aa”+“bb”; 此時str的值為"aabb",但是"aabb"不是在開始的字串"aa"後面直接連線的"bb",而是又新生成了字串"aabb",字串"aa"一旦被初始化,那麼它的值不可能再改變了。 StringBuffer strb = StringBuffer(“aa”); strb.append(“bb”); 此時的strb的值也為"aabb",但是"aabb"是直接在開始的字串"aa"後面連線的“bb”,並沒有生成新的字串。
337執行如下程式,輸出結果是( C)
class Test
{
private int data;
int result = 0;
public void m()
{
result += 2;
data += 2;
System.out.print(result + " " + data);
}
}
class ThreadExample extends Thread
{
private Test mv;
public ThreadExample(Test mv)
{
this.mv = mv;
}
public void run()
{
synchronized(mv)
{
mv.m();
}
}
}
class ThreadTest
{
public static void main(String args[])
{
Test mv = new Test();
Thread t1 = new ThreadExample(mv);
Thread t2 = new ThreadExample(mv);
Thread t3 = new ThreadExample(mv);
t1.start();
t2.start();
t3.start();
}
}
0 22 44 6
2 42 42 4
2 24 46 6
4 44 46 6
Test mv =newTest()宣告並初始化對data賦預設值
使用synchronized關鍵字加同步鎖執行緒依次操作m()
t1.start();使得result=2,data=2,輸出即為2 2
t2.start();使得result=4,data=4,輸出即為4 4
t3.start();使得result=6,data=6,輸出即為6 6
System.out.print(result +" "+ data);是print()方法不會換行,輸出結果為2 24 46 6
加了鎖,所以三條執行緒依次計算就好了,嗯,很和諧
只是new出執行緒物件,所以呼叫的方法是同一個物件中的方法,三個執行緒所訪問的資料data和result都是同一個堆上的內容。
338 有關finally語句塊說法正確的是(ABC )
不管catch是否捕獲異常,finally語句塊都是要被執行的
在try語句塊或catch語句塊中執行到System.exit(0)直接退出程式
finally塊中的return語句會覆蓋try塊中的return返回
finally 語句塊在 catch語句塊中的return語句之前執行
如果try語句裡有return,那麼程式碼的行為如下:
1.如果有返回值,就把返回值儲存到區域性變數中
2.執行jsr指令跳到finally語句裡執行
3.執行完finally語句後,返回之前儲存在區域性變數表裡的值
如果try,finally語句裡均有return,忽略try的return,而使用finally的return.
D.不是return之前,是return執行完成之前,return表示式的結果會暫時儲存起來,不會被改變
1、不管有木有出現異常,finally塊中程式碼都會執行;
2、當try和catch中有return時,finally仍然會執行;
3、finally是在return後面的表示式運算後執行的(此時並沒有返回運算後的值,而是先把要返回的值儲存起來,管finally中的程式碼怎麼樣,返回的值都不會改變,任然是之前儲存的值),所以函式返回值是在finally執行前確定的;
4、finally中最好不要包含return,否則程式會提前退出,返回值不是try或catch中儲存的返回值。
舉例:
情況1:try{} catch(){}finally{} return;
顯然程式按順序執行。
情況2:try{ return; }catch(){} finally{} return;
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼;
再執行finally塊,最後執行try中return;
finally塊之後的語句return,因為程式在try中已經return所以不再執行。
情況3:try{ } catch(){return;} finally{} return;
程式先執行try,如果遇到異常執行catch塊,
有異常:則執行catch中return之前(包括return語句中的表示式運算)程式碼,再執行finally語句中全部程式碼,
最後執行catch塊中return. finally之後也就是4處的程式碼不再執行。
無異常:執行完try再finally再return.
情況4:try{ return; }catch(){} finally{return;}
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼;
再執行finally塊,因為finally塊中有return所以提前退出。
情況5:try{} catch(){return;}finally{return;}
程式執行catch塊中return之前(包括return語句中的表示式運算)程式碼;
再執行finally塊,因為finally塊中有return所以提前退出。
情況6:try{ return;}catch(){return;} finally{return;}
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼;
有異常:執行catch塊中return之前(包括return語句中的表示式運算)程式碼;
則再執行finally塊,因為finally塊中有return所以提前退出。
無異常:則再執行finally塊,因為finally塊中有return所以提前退出。
最終結論:任何執行try 或者catch中的return語句之前,都會先執行finally語句,如果finally存在的話。
如果finally中有return語句,那麼程式就return了,所以finally中的return是一定會被return的,
編譯器把finally中的return實現為一個warning。
339 下面關於變數及其範圍的陳述哪些是不正確的(BC)
例項變數是類的成員變數
例項變數用關鍵字static宣告
在方法中定義的區域性變數在該方法被執行時建立
區域性變數在使用前必須被初始化
A.類的成員變數包括例項變數和類變數(靜態變數),成員方法包括例項方法和類方法(靜態方法)。 A正確
B.類變數(靜態變數)用關鍵字static宣告,B錯誤
C.方法中的區域性變數在方法被呼叫載入時開始入棧時建立,方法入棧建立棧幀包括區域性變數表運算元棧,區域性變數表存放區域性變數,並非在執行該方法時被建立,C錯誤
D.區域性變數被使用前必須初始化,否則程式報錯。D正確
c選項應該是線上程為該方法建立棧楨時被建立,而不是方法執行時建立
不是區域性變數在該方法被執行/呼叫時建立,而是應該為在該變數被宣告並賦值時建立,可以理解為“當程式碼執行到該變數被賦值的程式碼時才被建立”
棧會為每個方法在執行的時候分配一塊獨立的棧幀記憶體區域,棧幀又包含“區域性變數表”、“運算元棧”、“動態連結”以及“方法出口”四個部分。
340 關鍵字super的作用是? D
用來訪問父類被隱藏的非私有成員變數
用來呼叫父類中被重寫的方法
用來呼叫父類的建構函式
以上都是
正確答案D:
1:特殊變數super,提供了對父類的訪問。
2:可以使用super訪問父類被子類隱藏的變數或覆蓋的方法。
3:每個子類構造方法的第一條語句,都是隱含地呼叫super(),如果父類沒有這種形式的建構函式,那麼在編譯的時候就會報錯。
4:構造是不能被繼承的。
341以下敘述正確的是 D
例項方法可直接呼叫超類的例項方法
例項方法可直接呼叫超類的類方法、
例項方法可直接呼叫子類的例項方法
例項方法可直接呼叫本類的例項方法
首先,例項成員包括例項變數和例項方法,也就是我們平時說的成員變數和成員方法。其次,靜態變數也叫做類變數,靜態方法也叫類方法,靜態變數和靜態方法統稱靜態成員也叫作類成員。類成員是可以用類名.類變數或類方法的。最後,這道題就是考你父類子類之間變數區分。答案是D
A錯誤,類的例項方法是與該類的例項物件相關聯的,不能直接呼叫,只能通過建立超類的一個例項物件,再進行呼叫
B錯誤,當父類的類方法定義為private時,對子類是不可見的,所以子類無法呼叫
C錯誤,子類具體的例項方法對父類是不可見的,所以無法直接呼叫, 只能通過建立子類的一個例項物件,再進行呼叫
D正確,例項方法可以呼叫自己類中的例項方法
在java中我們稱超類為父類。這題涉及父子類關係,如果父類裡被private修飾,則子類是無法繼承和訪問的,而父類訪問子類,需要new一個物件才能訪問,不能直接訪問。本題中只有d選項是正確的,一個類訪問本類是絕對可行的。
342 執行下面的程式段,語句3的執行次數為(C)
for (i=0; i<=n-1; i++) (1)
for (j=n; j>i; j--) (2)
state; (3)
n(n+2)/2
(n-1)(n+2)/2
n(n+1)/2
(n-1)(n+2)
選c,外迴圈有n次,當i=0,內迴圈為n次,當i=1,內迴圈為n-1次,當i=2時,內迴圈為n-2次,以此類推,總次數為n+(n-1)+(n-2)+…+2+1,就是個等差數列,等於n(n+1)/2。
343指出下列程式執行的結果(B)
public class Example{
String str = new String("good");
char[ ] ch = { 'a' , 'b' , 'c' };
public static void main(String args[]){
Example ex = new Example();
ex.change(ex.str,ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str,char ch[ ]){
str = "test ok";
ch[0] = 'g';
}
}
good and abc
good and gbc
test ok and abc
test ok and gbc
簡單總結一下:直接賦值而不是使用new關鍵字給字串初始化,在編譯時就將String物件放進字串常量池中;使用new關鍵字初始化字串時,是在堆疊區存放變數名和內容;字串的拼接操作在程式執行時,才在堆中建立物件。一般,可以認為使用"=="比較的是引用,equals比較的是內容。對於上面的題,看完下面的幾個例子,你就會有所感悟:String str = new String("good");是在編譯時在堆疊中建立物件和分配內容,而在傳參的時候,傳遞的是地址,把外面的str引用地址複製了一份給方法內的str而不是裡面的內容。
看例子:;
例子A:
String str1 = "java";
String str2 = "java";
System.out.print(str1==str2);
大部分人也許認為會輸出false,因為==比較的是引用,equals比較的是內容。可以在自己的機子上執行一 下,結果是true!原因很簡單,String物件被放進常量池裡了,再次出現“java”字串的時候,JVM很興奮地把str2的引用也指向了 “java”物件,它認為自己節省了記憶體開銷。不難理解吧 呵呵
例子B:
String str1 = new String("java");
String str2 = new String("java");
System.out.print(str1==str2);
看過上例的都學聰明瞭,這次肯定會輸出true!很不幸,JVM並沒有這麼做,結果是false。原因很簡單,例子A中那種直接賦值(而沒有通過new關鍵字例項化的字串變數)宣告的方式確實是在 String常量池建立“java”物件,但是一旦看到new關鍵字,JVM會在堆中為String分配空間。兩者宣告方式貌合神離,這也是我把“如何創 建字串物件”放到後面來講的原因。大家要沉住氣,還有一個例子。
例子C:
String str1 = "java"; //直接賦值而不是使用new關鍵字給字串初始化,在編譯時就將String物件放進字串常量池中
String str2 = "blog"; //直接賦值而不是使用new關鍵字給字串初始化,在編譯時就將String物件放進字串常量池中
String s = str1+str2; //字串的拼接操作在程式執行時,才在堆中建立物件,
System.out.print(s=="javablog");
再看這個例子,很多同志不敢妄言是true還是false了吧。愛玩腦筋急轉彎的人會說是false吧……恭喜你,你會搶答了!把那個“吧”字去掉你就完 全正確。原因很簡單,JVM確實會對型如String str1 = "java"; 的String物件放在字串常量池裡,但是它是在編譯時刻那麼做的,而String s = str1+str2; 是在執行時刻才能知道(我們當然一眼就看穿了,可是Java必須在執行時才知道的,人腦和電腦的結構不同),也就是說str1+str2是在堆裡建立的, s引用當然不可能指向字串常量池裡的物件。沒崩潰的人繼續看例子D。
例子D:
String s1 = "java";
String s2 = new String("java");
System.out.print(s1.intern()==s2.intern());
intern()是什麼東東?反正結果是true。如果沒用過這個方法,而且訓練有素的程式設計師會去看JDK文件了。簡單點說就是用intern()方法就可以用“==”比較字串的內容了。在我看到intern()方法到底有什麼用之前,我認為它太多餘了。其實我寫的這一條也很多餘,intern()方法 還存在諸多的問題,如效率、實現上的不統一……
例子E:
String str1 = "java";
String str2 = new String("java");
System.out.print(str1.equals(str2));
無論在常量池還是堆中的物件,用equals()方法比較的就是內容,就這麼簡單!
首先說下String確實是個不可變物件,這個不可變是JDK特有的,寫JAVA的人特意針對的
但是這與本題無關,題目中的形參str只是原引用ex.str的一個引用副本,傳的是一個副本地址值,這個值與ex.str地址值是不一樣的,但是它們同時指向了堆中的物件new String(“good”),當你在函式中改變形參也就是地址的副本值也就是這句str=“test ok"只是將副本地址指向常量"test ok”,並沒有改變原ex.str的指向方向,它還是指向物件new String(“good”)的
char陣列與String一樣傳的也是地址的副本,但是關鍵是形參ch它沒有新的指向 ch[0]只是ch在指向原物件時改變了物件的內部結構, 所以在ex.ch指向與它是同一個物件的情況下當然也會隨之變化
344 下面有關servlet service描述錯誤的是?B
不管是post還是get方法提交過來的連線,都會在service中處理
doGet/doPost 則是在 javax.servlet.GenericServlet 中實現的
service()是在javax.servlet.Servlet介面中定義的
service判斷請求型別,決定是呼叫doGet還是doPost方法
doGet/doPost 則是在 javax.servlet.http.HttpServlet 中實現的
doget/dopost與Http協議有關,是在 javax.servlet.http.HttpServlet 中實現的
注意以下幾點:
1.service方法是在servlet生命週期中的服務期,預設在HttpServlet類中實現,根據HTTP請求方法(GET、POST等),將請求分發到doGet、doPost等方法實現。
2.GenericServlet 抽象類給出了設計servlet的一些骨架,定義了servlet生命週期還有一些得到名字、配置、初始化引數的方法,其設計的是和應用層協議無關的。doget/dopost與Http協議有關,是在 javax.servlet.http.HttpServlet 中實現的。
3.doGet和doPost方法在HttpServlet類中實現,GenericServlet中實現了service()
4.常說所有的請求都先由service方法處理,而javax.servlet.GenericServlet介面實現了javax.servlet.Servle介面,且javax.servlet.http.HttpServlet 是 javax.servlet.GenericServlet 的子類。只有最先定義好了的service方法才可以處理所有的請求。
345 下面哪些Java中的流物件是位元組流?ABCD
FileInputStream
BufferedInputStream
PushbackInputStream
ByteArrayInputStream
stream結尾都是位元組流,reader和writer結尾都是字元流 兩者的區別就是讀寫的時候一個是按位元組讀寫,一個是按字元。 實際使用通常差不多。 在讀寫檔案需要對內容按行處理,比如比較特定字元,處理某一行資料的時候一般會選擇字元流。 只是讀寫檔案,和檔案內容無關的,一般選擇位元組流。
Java主要分為位元組流和字元流如下:
位元組流:
InputStream
|-- FileInputStream (基本檔案流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream
字元流
Reader
|-- InputStreamReader (byte->char 橋樑)
|-- BufferedReader (常用)
Writer
|-- OutputStreamWriter (char->byte 橋樑)
|-- BufferedWriter
|-- PrintWriter (常用)
346 關於equals和hashCode描述正確的是 (ABC)
兩個obj,如果equals()相等,hashCode()一定相等(符合程式碼規範的情況下)
兩個obj,如果hashCode()相等,equals()不一定相等
兩個不同的obj, hashCode()可能相等
其他都不對
==”:作用是判斷兩個物件的地址是否相等,即,判斷兩個物件是不是同一個物件,如果是基本資料型別,則比較的是值是否相等。
"equal":作用是判斷兩個物件是否相等,但一般有兩種使用情況
1.類沒有覆蓋equals()方法,則相當於通過“==”比較
2.類覆蓋equals()方法,一般,我們都通過equals()方法來比較兩個物件的內容是否相等,相等則返回true,如String
地址比較是通過計算物件的雜湊值來比較的,hashcode屬於Object的本地方法,物件相等(地址相等),hashcode相等,物件不相等,hashcode()可能相等,雜湊衝突
兩個物件的equals比較為true,那麼他們的HashCode一定相同,反之,兩個物件的HashCode相同不一滿足equals比較為true,解釋一下為什麼,這是因為HashCode採用的其實是一種雜湊演算法,當然,這業務Java認為最有效的演算法,既然是湊出來的那麼就有一種情況就是兩個不同的物件返回相同的hashCode,並且這種演算法越糟糕返回相同的概率越大
hashCode()的存在是為了查詢的快捷性,用於在雜湊儲存結構中確定物件的儲存地址
如果兩個物件 equals相等,則 hashCode()也一定相等
如果 equals方法被重寫,則 hashCode()也應該被重寫
如果兩個物件的 hashCode()相等, equals()方法不一定相等
equals方法沒有重寫,比較的就是應用型別的變數所指向的物件的地址
347 關於java中的陣列,下面的一些描述,哪些描述是準確的:(ACF)
陣列是一個物件,不同型別的陣列具有不同的類
陣列長度是可以動態調整的
陣列是一個連續的儲存結構
一個固定長度的陣列可類似這樣定義:int array[100]
兩個陣列用Object 裡equals方法比較時,會逐個遍歷其中的元素,對每個元素進行比較
java中不存在 int *a這樣的東西做陣列的形參
陣列用equals比較時,不是比較內容,而是比較的是值(地址,顯然是兩個物件,地址不同),預設採用的object中的equals來進行比較,看原始碼的都知道
equals原始碼
陣列a.equals(陣列b),和Arrays.equals(陣列a,陣列b)是不同的
348 在異常處理中,若try中的程式碼可能產生多種異常則可以對應多個catch語句,若catch中的引數型別有父類子類關係,此時應該將父類放在後面,子類放在前面。(√)
簡單記憶:老將(牛X的)都是最後出馬
( 若 catch 中的引數型別有父類子類關係,此時應該將父類放在後面,子類放在前面 )
349Java 的螢幕座標是以畫素為單位,容器的左下角被確定為座標的起點。(×)
容器的左上角被確定為座標的起點。
350Java資料庫連線庫JDBC用到哪種設計模式?(B)
生成器
橋接模式
抽象工廠
單例模式
橋接模式:
定義 :將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
意圖 :將抽象與實現解耦。
橋接模式所涉及的角色
- Abstraction :定義抽象介面,擁有一個Implementor型別的物件引用
- RefinedAbstraction :擴充套件Abstraction中的介面定義
- Implementor :是具體實現的介面,Implementor和RefinedAbstraction介面並不一定完全一致,實際上這兩個介面可以完全不一樣Implementor提供具體操作方法,而Abstraction提供更高層次的呼叫
- ConcreteImplementor :實現Implementor介面,給出具體實現
Jdk中的橋接模式:JDBC
JDBC連線 資料庫 的時候,在各個資料庫之間進行切換,基本不需要動太多的程式碼,甚至絲毫不動,原因就是JDBC提供了統一介面,每個資料庫提供各自的實現,用一個叫做資料庫驅動的程式來橋接就行了
B.橋接模式。JDBC提供兩套介面,一個面向資料庫廠商,一個面向JDBC使用者。
橋接模式是結構型模式,關注點在依賴關係的維護。對於jdbc技術來說,它解耦了業務與資料庫通訊協議這兩個緯度之間的關係,所以這兩個緯度之間的關係就需要一個橋,即Driver,至於DriverManager把這個關係接到哪裡就是執行時的事情了。
微觀上,從connection的建立來看,它更像一個抽象工廠模式,特定的Driver建立對應的connection。
巨集觀上,從業務程式碼與connection的關係來看,關鍵點在於一個sql怎麼轉化為對應的通訊協議,就屬於橋接。
351 以下宣告合法的是B
default String s
public final static native int w( )
abstract double d
abstract final double hyperbolicCosine( )
A:java的訪問許可權有public、protected、private和default的,default不能修飾變數
C:普通變數不能用abstract修飾,abstract一般修飾方法和類
D:被定義為abstract的類需要被子類繼承,但是被修飾為final的類是不能被繼承和改寫的
A:變數不能被defalut修飾
B:native修飾方法,native修飾的方法簡單來說就是:一個Java方法呼叫了一個非Java程式碼的介面。
定義navtive方法時,並不提供實現體,因為其實現體是用非Java語言在外面實現的。native可以和任何修飾符連用,abstract除外。因為native暗示這個方法時有實現體的,而abstract卻顯式指明瞭這個方法沒有實現體。
C:abstract修飾方法和類
D:final修飾的方法不能被重寫。而abstract定義的方法沒有實現,必須被子類重寫,明顯不能一起使用。
b中的問題涉及到JNI:
native是方法修飾符。Native方法是由另外一種語言(如c/c++,FORTRAN,彙編)實現的本地方法。因為在外部實現了方法,所以在java程式碼中,就不需要宣告瞭,有點類似於介面方法。Native可以和其他一些修飾符連用,但是abstract方法和Interface方法不能用native來修飾
352 jvm中垃圾回收分為scanvenge gc和full GC,其中full GC觸發的條件可能有哪些 CDE
棧空間滿
年輕代空間滿
老年代滿
持久代滿
System.gc()
1,新生代:(1)所有物件建立在新生代的Eden區,當Eden區滿後觸發新生代的Minor GC,將Eden區和非空閒Survivor區存活的物件複製到另外一個空閒的Survivor區中。(2)保證一個Survivor區是空的,新生代Minor GC就是在兩個Survivor區之間相互複製存活物件,直到Survivor區滿為止。
2,老年代:當Survivor區也滿了之後就通過Minor GC將物件複製到老年代。老年代也滿了的話,就將觸發Full GC,針對整個堆(包括新生代、老年代、持久代)進行垃圾回收。
3,持久代:持久代如果滿了,將觸發Full GC。
353 以下哪幾種方式可用來實現執行緒間通知和喚醒:AC
Object.wait/notify/notifyAll
ReentrantLock.wait/notify/notifyAll
Condition.await/signal/signalAll
Thread.wait/notify/notifyAll
wait()、notify()和notifyAll()是 Object類 中的方法 ;
Condition是在java 1.5中才出現的,它用來替代傳統的Object的wait()、notify()實現執行緒間的協作,相比使用Object的wait()、 notify(),使用Condition1的await()、signal()這種方式實現執行緒間協作更加安全和高效。
354 下列關於Java語言中String和char的說法,正確的是(C)
String是Java定義的一種基本資料型別。
String是以“\0”結尾的char型別的陣列char[]。
使用equals()方法比較兩個String是否內容一樣(即字串中的各個字元都一樣)。
Char型別在Java語言裡面儲存的是ASCII碼。
A 基本資料型別包括byte,short,int,long,float,double,char,boolean,所以A錯。
B,C語言當中是這樣,java不是, String內部是用char[]陣列實現的,不過結尾不用\0。
C 對,字串內容比較用equals方法。
D char儲存的unicode碼,不僅可以儲存ascII碼,漢字也可以。
Java中的char是Unicode編碼。
Unicode編碼佔兩個位元組,就是16位,足夠儲存一個漢字。
基本資料型別 byte,short,int,long char float,double boolean String是類 2.String底層是用char[] 陣列實現的,但不以"\0"結尾 3.equals()方法比較內容是否相等 4.byte型別儲存的是ASCll碼
355 Java中基本的程式設計單元為:A
類
函式
變數
資料
java的基本程式設計單元是類,基本儲存單元是變數。
沒有類就沒有函式
Java的基本程式設計單位是類,基本儲存單元是變數
356如果一個list初始化為{5,3,1},執行以下程式碼後,其結果為(B)?
nums.add(6);
nums.add(0,4);
nums.remove(1);
[5, 3, 1, 6]
[4, 3, 1, 6]
[4, 3, 6]
[5, 3, 6]
初始化為{5,3,1}
nums.add(6)後list為{5,3,1,6}
nums.add(0,4)是在0號索引上新增數字4得到list為{4,5,3,1,6}
nums.remove(1)是將1號索引上的5進行remove得到list為{4,3,1,6}索引從0開始的,,,
357 DBMS 中實現事務永續性的子系統是(D)
安全性管理子系統
完整性管理子系統
併發控制子系統
恢復管理子系統
原子性:事務是一組不可分割的操作單元,這組單元要麼同時成功要麼同時失敗(由DBMS的事務管理子系統來實現);
一致性:事務前後的資料完整性要保持一致(由DBMS的完整性子系統執行測試任務);
隔離性:多個使用者的事務之間不要相互影響,要相互隔離(由DBMS的併發控制子系統實現);
永續性:一個事務一旦提交,那麼它對資料庫產生的影響就是永久的不可逆的,如果後面再回滾或者出異常,都不會影響已提交的事務(由DBMS的恢復管理子系統實現的)
要想事物具有永續性,就得在事物出錯時及時恢復。
原子性-事務管理子系統。一致性-完整子系統。隔離性-併發控制子系統。永續性-恢復管理子系統
原事~一完~隔並~持恢
358 下面有關Java的說法正確的是( ACDF )
一個類可以實現多個介面
抽象類必須有抽象方法
protected成員在子類可見性可以修改
通過super可以呼叫父類建構函式
final的成員方法實現中只能讀取類的成員變數
String是不可修改的,且java執行環境中對string物件有一個物件池儲存
解釋一下c選項,意思是父類中的protected方法子類在重寫的時候訪問許可權可以修改,其實就是重寫的要素之一,換了個說法而已
final 的成員方法除了能讀取類的成員變數,還能讀取類變數
359 可以把任何一種資料型別的變數賦給Object型別的變數。(√)
物件型別的不必多說可以賦值;而八大基礎資料型別會自動裝箱後賦值給Object,所以編譯執行都不會報錯
Java中一切都是物件,Object是所有類的根類!
360要使某個類能被同一個包中的其他類訪問,但不能被這個包以外的類訪問,可以( A)
讓該類不使用任何關鍵字
使用private關鍵字
使用protected關鍵字
使用void關鍵字
default和protected的區別是:
前者只要是外部包,就不允許訪問。
後者只要是子類就允許訪問,即使子類位於外部包。
總結:default拒絕一切包外訪問;protected接受包外的子類訪問
包以外的類包括子類
外部包 > 子類 > 本包 > 該類內部
publi c> protected > default > private
361對於子類的建構函式說明,下列敘述中錯誤的是( A )。
子類可以繼承父類的建構函式。
子類中呼叫父類建構函式不可以直接書寫父類建構函式,而應該用super();。
用new建立子類的物件時,若子類沒有帶參建構函式,將先執行父類的無參建構函式,然後再執行自己的建構函式。
子類的建構函式中可以呼叫其他函式。
A.java繼承中對建構函式是不繼承的,只是顯式或者隱式呼叫,所以A選項不對
A、構造器不是繼承,方法不說繼承的。方法說的最多的就是過載和重寫
B、C 子類構造器的第一行預設都是super(),但是一旦父類中沒有無參構造,第一行必須顯式的呼叫某一個有參構造
D、構造器中可以呼叫別的方法。
首先不管子類有沒有 有參建構函式,在建立子類的物件的時候,若子類建構函式沒有顯式呼叫父類建構函式,就會先呼叫父類的無參建構函式;若是在子類的建構函式顯式呼叫了父類的建構函式(包括有參的可以),則會先呼叫剛剛顯示呼叫的父類建構函式。
362下面哪些情況下需要使用抽象類?ABD
當一個類的一個或多個方法是抽象方法時
當類是一個抽象類的子類,並且不能為任何抽象方法提供任何實現細節或方法體時
當一個類實現多個介面時
當一個類實現一個介面,並且不能為任何抽象方法提供實現細節或方法體時
抽象類:用abstract修飾,抽象類中可以沒有抽象方法,但抽象方法肯定在抽象類中,且抽象方法定義時不能有方法體;抽象類不可以例項化只能通過繼承在子類中實現其所有的抽象方法;抽象類如果加粗樣式不被繼承就沒有任何意義;抽象類為子類定義了一個公共型別,封裝了子類中的重複內容。
介面:同Interface關鍵字定義介面,是特殊的抽象類因為類中只包含抽象方法;介面中不能定義成員變數可以定義常量;介面是其通過其他類使用implements關鍵字定義實現類,一個類一旦實現介面就必須實現其中的所有抽象方法,一個類可以實現多個介面,介面名之間用逗號隔開即可;一個介面可以通過extends關鍵字繼承另一個介面,與此同時繼承了父類中的所有方法。
A項 一個類中有抽象方法則必須宣告為抽象類
B項 抽象類中的抽象方法必須由其子類實現,若子類不能實現則子類也必須定義為抽象類
D項 一個類實現一個介面就必須實現其中所有的抽象方法,若該實現類不能實現介面中的所有方法則實現類定義為抽象類
363 Java是一門支援反射的語言,基於反射為Java提供了豐富的動態性支援,下面關於Java反射的描述,哪些是錯誤的:( ADF )
Java反射主要涉及的類如Class, Method, Filed,等,他們都在java.lang.reflet包下
通過反射可以動態的實現一個介面,形成一個新的類,並可以用這個類建立物件,呼叫物件方法
通過反射,可以突破Java語言提供的物件成員、類成員的保護機制,訪問一般方式不能訪問的成員
Java反射機制提供了位元組碼修改的技術,可以動態的修剪一個類
Java的反射機制會給記憶體帶來額外的開銷。例如對永生堆的要求比不通過反射要求的更多
Java反射機制一般會帶來效率問題,效率問題主要發生在查詢類的方法和欄位物件,因此通過快取需要反射類的欄位和方法就能達到與之間呼叫類的方法和訪問類的欄位一樣的效率
A Class類在java.lang包
B 動態代理技術可以動態建立一個代理物件,反射不行
C 反射訪問私有成員時,Field呼叫setAccessible可解除訪問符限制
D CGLIB實現了位元組碼修改,反射不行
E 反射會動態建立額外的物件,比如每個成員方法只有一個Method物件作為root,他不胡直接暴露給使用者。呼叫時會返回一個Method的包裝類
F 反射帶來的效率問題主要是動態解析類,JVM沒法對反射程式碼優化。
364 下面有關java classloader說法錯誤的是? C
Java預設提供的三個ClassLoader是BootStrap ClassLoader,Extension ClassLoader,App ClassLoader
ClassLoader使用的是雙親委託模型來搜尋類的
JVM在判定兩個class是否相同時,只用判斷類名相同即可,和類載入器無關
ClassLoader就是用來動態載入class檔案到記憶體當中用的
比較兩個類是否相等,只有這兩個類是由同一個類載入器載入才有意義。否則,即使這兩個類是來源於同一個Class檔案,只要載入它們的類載入器不同,那麼這兩個類必定不相等。
補充:
- 什麼是類載入器?
把類載入的過程放到Java虛擬機器外部去實現,讓應用程式決定如何去獲取所需要的類。實現這個動作的程式碼模組稱為“類載入器”。
- 有哪些類載入器,分別載入哪些類
類載入器按照層次,從頂層到底層,分為以下三種:
(1)啟動類載入器 : 它用來載入 Java 的核心庫,比如String、System這些類
(2)擴充套件類載入器 : 它用來載入 Java 的擴充套件庫。
(3) 應用程式類載入器 : 負責載入使用者類路徑上所指定的類庫,一般來說,Java 應用的類都是由它來完成載入的。
- 雙親委派模型
我們應用程式都是由以上三種類載入器互相配合進行載入的,還可以加入自己定義的類載入器。稱為 類載入器的雙親委派模型 ,這裡類載入器之間的父子關係一般不會以繼承的關係來實現,而是都使用 組合關係 來複用父載入器的。
- 雙親委託模型的工作原理
是當一個類載入器收到了類載入的請求,它首先不會自己去嘗試載入這個類,而是把這個請求委派給父類載入器去完成,每一個層次的類載入都是如此,因此所有的載入請求最終都應該傳送到頂層的啟動類載入器中,只有當父載入器反饋自己無法載入這個載入請求的時候,子載入器才會嘗試自己去載入。
- 使用雙親委派模型好處?(原因)
第一:可以避免重複載入,當父親已經載入了該類的時候,子類不需要再次載入。
第二:考慮到安全因素,如果不使用這種委託模式,那我們就可以隨時使用自定義的String來動態替代java核心api中定義型別,這樣會存在非常大的安全隱患,而雙親委託的方式,就可以避免這種情況,因為String已經在啟動時被載入,所以使用者自定義類是無法載入一個自定義的類裝載器。
365 對抽象類的描述正確的是(D)
抽象類的方法都是抽象方法
一個類可以繼承多個抽象類
抽象類不能有構造方法
抽象類不能被例項化
解釋:
A.抽象類可以有非抽象的方法,而介面中的方法都是抽象方法
B.java中類只能單繼承,介面可以‘繼承’多個介面
C.抽象類可以有構造方法,介面一定沒有構造方法
D.例項化一般指new一個物件,所以抽象類不能例項化
366 What is the result? C
public class IfTest{
public static void main(string[]args){
int x=3;
int y=1;
if(x=y)
System.out.println(“Not equal”);
else
System.out.println(“Equal”);
}
}
The output is “Equal”
The output in “Not Equal”
An error at line 5 causes compilation to fall.
The program executes but does not print a message.
if()語句括號中為比較表示式,返回值要麼是true,要麼是false,if(x=y)是將y賦值給x,但是資料型別是int型別的,編譯不能通過,如果把程式碼改為這樣:
boolean x = false;
boolean y = ture;
if(x=y){…}這樣就就不會報錯了,編譯正常通過。
1、Java中,賦值是有返回值的 ,賦什麼值,就返回什麼值。比如這題,x=y,返回y的值,所以括號裡的值是1。
2、Java跟C的區別,C中賦值後會與0進行比較,如果大於0,就認為是true;而Java不會與0比較,而是直接把賦值後的結果放入括號。
367下列不屬於Java語言性特點的是D
Java致力於檢查程式在編譯和執行時的錯誤
Java能執行虛擬機器實現跨平臺
Java自己操縱記憶體減少了記憶體出錯的可能性
Java還實現了真陣列,避免了覆蓋資料型別的可能
程式設計語言中,陣列元素在記憶體中是一個接著一個線性存放的,通過第一個元素就能訪問隨後的元素,這樣的陣列稱之為“真陣列”。
實現了真陣列為Java語言健壯性的特點之一。
真陣列: 陣列元素在記憶體中是一個接著一個線性存放的,通過第一個元素就能訪問隨後的元素,避免了資料覆蓋的可能性,和資料型別覆蓋並沒有關係。
Java致力於檢查程式在編譯和執行時的錯誤。
Java虛擬機器實現了跨平臺介面
型別檢查幫助檢查出許多開發早期出現的錯誤。
Java自己操縱記憶體減少了記憶體出錯的可能性。
Java還實現了真陣列,避免了覆蓋資料的可能。
注意,是避免資料覆蓋的可能,而不是資料覆蓋型別
368 下列程式碼輸出結果為( D )
class Animal{
public void move(){
System.out.println("動物可以移動");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal();
Animal b = new Dog();
a.move();
b.move();
b.bark();
}
}
動物可以移動
狗可以跑和走
狗可以吠叫
動物可以移動
動物可以移動
狗可以吠叫
執行錯誤
編譯錯誤
編譯看左邊,執行看右邊。 父型別引用指向子型別物件,無法呼叫只在子型別裡定義的方法
編譯錯誤:The method bark() is undefined for the type Animal。Animal中沒有定義bark()方法。
Dog繼承自Animal。
當用Dog物件初始化Animal類物件時,完成了對Animal物件中方法與變數的覆蓋與隱藏,也就是b.move()呼叫的是Dog中move()方法。而Animal中本身並沒有bark()方法,不存在被覆蓋的情況,亦無法訪問,也就是b.bark()會報錯。
369 有如下4條語句:() 以下輸出結果為false的是: C
Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);
System.out.println(i01==i02);
System.out.println(i01==i03);
System.out.println(i03==i04);
System.out.println(i02==i04);
①無論如何,Integer與new Integer不會相等。不會經歷拆箱過程,
②兩個都是非new出來的Integer,如果數在-128到127之間,則是true,否則為false
java在編譯Integer i2 = 128的時候,被翻譯成-> Integer i2 = Integer.valueOf(128);而valueOf()函式會對-128到127之間的數進行快取
③兩個都是new出來的,都為false
④int和integer(無論new否)比,都為true,因為會把Integer自動拆箱為int再去比
注: ==比較的是地址
但是當為基本型別時,比較的是值,如果倆邊有包裝型別,則先將包裝型別轉換為基本型別在比較值是否相等。
當倆邊都為包裝型別時,即為物件,比較的是地址
Integer.valueOf方法中也有判斷,如果傳遞的整型變數>= -128並且小於127時會返回IntegerCache類中一個靜態陣列中的某一個物件, 否則會返回一個新的Integer物件,程式碼如下
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.***[i + (-IntegerCache.low)];
return new Integer(i);
}
所以如果你測試如下程式碼
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
}
結合自動封裝、常量池以及Integer.valueOf方法就不難得出,答案時true和false;
再看本題
Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);
第一行:由於59在-128~127範圍之內,所以在自動裝箱的時候,會返回IntegerCache[59 - (-128)];
第三行:同第一行
第四行:因為有new關鍵字,所以在heap中開闢了一塊新記憶體放置值為59的Integer物件。
System.out.println(i01==i02);//正確
System.out.println(i01==i03);//正確,都指向IntegerCache[59-(-128)]物件
System.out.println(i03==i04);//錯誤,引用指向的物件地址不同
System.out.println(i02==i04);//正確
370 下列程式碼執行結果為(A)
下列程式碼執行結果為()
public static void main(String args[])throws InterruptedException{
Thread t=new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.print("2");
}
});
t.start();
t.join();
System.out.print("1");
}
21
12
可能為12,也可能為21
以上答案都不對
thread.Join把指定的執行緒加入到當前執行緒,可以將兩個交替執行的執行緒合併為順序執行的執行緒。比如線上程B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。
t.join(); //使呼叫執行緒 t 在此之前執行完畢。
t.join(1000); //等待 t 執行緒,等待時間是1000毫秒
因為子執行緒的休眠時間太長,因此主執行緒很有可能在子執行緒之前結束也就是輸出結果是12,但是子執行緒用了join函式,因此主執行緒必須等待子執行緒執行完畢才結束因此輸出結果只能是21
join()的作用是:“等待該執行緒終止”,這裡需要理解的就是該執行緒是指的主執行緒等待子執行緒的終止。也就是在子執行緒呼叫了join()方法後面的程式碼,只有等到子執行緒結束了才能執行。
371 java8中,下面哪個類用到了解決雜湊衝突的開放定址法 C
LinkedHashSet
HashMap
ThreadLocal
TreeMap
ThreadLocalMap中使用開放地址法來處理雜湊衝突,而HashMap中使用的是分離連結串列法。之所以採用不同的方式主要是因為:在ThreadLocalMap中的雜湊值分散得十分均勻,很少會出現衝突。並且ThreadLocalMap經常需要清除無用的物件,使用純陣列更加方便。
threadlocal 使用開放地址法 - 線性探測法:當前雜湊槽有其他物件佔了,順著陣列索引尋找下一個,直到找到為止
hashset 中呼叫 hashmap 來儲存資料的,hashmap 採用的鏈地址法:當雜湊槽中有其他物件了,使用連結串列的方式連線到那個物件上
ThreadLocalMap通過key(ThreadLocal型別)的hashcode來計算陣列儲存的索引位置i。如果i位置已經儲存了物件,那麼就往後挪一個位置依次類推,直到找到空的位置,再將物件存放。另外,在最後還需要判斷一下當前的儲存的物件個數是否已經超出了閾值(threshold的值)大小,如果超出了,需要重新擴充並將所有的物件重新計算位置。
372對於執行緒區域性儲存TLS(thread local storage),以下表述正確的是ABD
解決多執行緒中的對同一變數的訪問衝突的一種技術
TLS會為每一個執行緒維護一個和該執行緒繫結的變數的副本
每一個執行緒都擁有自己的變數副本,從而也就沒有必要對該變數進行同步了
Java平臺的java.lang.ThreadLocal是TLS技術的一種實現
C:同一全域性變數或者靜態變數每個執行緒訪問的是同一變數,多個執行緒同時訪存同一全域性變數或者靜態變數時會導致衝突,尤其是多個執行緒同時需要修改這一變數時,通過TLS機制,為每一個使用該全域性變數的執行緒都提供一個變數值的副本,每一個執行緒均可以獨立地改變自己的副本,而不會和其它執行緒的副本衝突。
ThreadLocal可以給一個初始值,而每個執行緒都會獲得這個初始化值的一個副本,這樣才能保證不同的執行緒都有一份拷貝。ThreadLocal 不是用於解決共享變數的問題的,不是為了協調執行緒同步而存在,而是為了方便每個執行緒處理自己的狀態而引入的一個機制.
如果是靜態變數是共享的話,那必須同步,否則儘管有副本,還是會出錯,故C錯
373 通過HttpServletRequest. getParameter獲取的引數. C
總是採用UTF-8編碼
總是採用lS08859-1編碼
由客戶端瀏覽器和Web容器配置共同決定編碼
由伺服器所在的作業系統決定編碼
1、瀏覽器根據jsp頁面開頭宣告的編碼方式對request中引數編碼;
2、tomcat預設解碼是ISO-8859-1, 但是我們可以顯示指定解碼格式通過呼叫 request.setCharacterEncoding(“UTF-8”),或者修改tomcat的配置檔案server.xml中的編碼,新增uriEncoding屬性。
亂碼問題之所以一直存在,就是由於編碼的靈活性,也就是說,編碼與其他工作是解耦的。此外,Web 的編碼問題與伺服器所在的作業系統無關,Web 容器諸如Tomcat可以配置預設編碼方式,例如,Tomcat 的預設編碼方式是 iso8859-1。亂碼的解決之道就是直接或間接的使客戶端與Web 容器編碼方式相容。
編碼格式由瀏覽器決定,瀏覽器根據html中指定的編碼格式進行編碼,tomcat根據指定的格式進行解碼,另外get請求和post請求對編碼格式的處理也是不同的
374 JVM記憶體不包含如下哪個部分(D )
Stacks
PC暫存器
Heap
Heap Frame
PC暫存器即程式計數器
375 保留的字元數為(C)
假定str0,…,str4後序程式碼都是隻讀引用。
Java 7中,以上述程式碼為基礎,在發生過一次FullGC後,上述程式碼在Heap空間(不包括PermGen)保留的字元數為()
static String str0="0123456789";
static String str1="0123456789";
String str2=str1.substring(5);
String str3=new String(str2);
String str4=new String(str3.toCharArray());
str0=null;
5
10
15
20
解析:這是一個關於java的垃圾回收機制的題目。垃圾回收主要針對的是堆區的回收,因為棧區的記憶體是隨著執行緒而釋放的。堆區分為三個區:年輕代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation,也就是方法區)。
年輕代:物件被建立時(new)的物件通常被放在Young(除了一些佔據記憶體比較大的物件),經過一定的Minor GC(針對年輕代的記憶體回收)還活著的物件會被移動到年老代(一些具體的移動細節省略)。
年老代:就是上述年輕代移動過來的和一些比較大的物件。Minor GC(FullGC)是針對年老代的回收
永久代:儲存的是final常量,static變數,常量池。
str3,str4都是直接new的物件,而substring的原始碼其實也是new一個string物件返回,如下圖:
經過fullgc之後,年老區的記憶體回收,則年輕區的佔了15個,不算PermGen。所以答案選C
應該是C
substring實際是new,5字元
str3和4也都是new,每個5字元
分別都會建立新的物件
常量池是PermGen的
因此應該是一共15字元
376 下面這段java程式碼,當 T 分別是引用型別和值型別的時候,分別產生了多少個 T物件和T型別的值(D)
T t = new T();(值型別時:T t;)
Func(t);
Func 定義如下:
public void Func(T t) { }
1 1
2 1
2 2
1 2
引用型別作為函式的引數時,複製的是引用的地址,不會產生一個新的T;而如果T是值型別,其作為函式實參時會複製其值,也就是產生了一個新的T
這個題考查的應該是 Java 中只有值傳遞。
對於引用型別來說,傳參時傳遞的是引用型別的值,會在方法的棧幀中建立一個引用型別的變數,接收傳遞過來的值,但是兩個變數指向的是堆記憶體中同一個物件,所以只建立了一個 T 物件的值。
對於基本型別來說,傳參時直接傳遞基本型別的值,所以會建立兩個 T 型別的值。
377 關於Java記憶體區域下列說法不正確的有哪些 BC
程式計數器是一塊較小的記憶體空間,它的作用可以看做是當前執行緒所執行的位元組碼的訊號指示器,每個執行緒都需要一個獨立的程式計數器.
Java虛擬機器棧描述的是java方法執行的記憶體模型,每個方法被執行的時候都會建立一個棧幀,用於儲存區域性變數表、類資訊、動態連結等資訊
Java堆是java虛擬機器所管理的記憶體中最大的一塊,每個執行緒都擁有一塊記憶體區域,所有的物件例項以及陣列都在這裡分配記憶體。
方法區是各個執行緒共享的記憶體區域,它用於儲存已經被虛擬機器載入的常量、即時編譯器編譯後的程式碼、靜態變數等資料。
B.類資訊不是儲存在java虛擬機器棧中,而是儲存在方法區中;
C.java堆是被所有執行緒共享的一塊記憶體區域,而不是每個執行緒都擁有一塊記憶體區域。
A.程式計數器是一塊較小的記憶體空間,它的作用可以看做是當前執行緒所執行的位元組碼的訊號指示器(偏移地址),Java編譯過程中產生的位元組碼有點類似編譯原理的指令,程式計數器的記憶體空間儲存的是當前執行的位元組碼的偏移地址,每一個執行緒都有一個獨立的程式計數器(程式計數器的記憶體空間是執行緒私有的),因為當執行語句時,改變的是程式計數器的記憶體空間,因此它不會發生記憶體溢位 ,並且程式計數器是jvm虛擬機器規範中唯一一個沒有規定 OutOfMemoryError 異常 的區域;
B.java虛擬機器棧:執行緒私有,生命週期和執行緒一致。描述的是 Java 方法執行的記憶體模型:每個方法在執行時都會建立一個棧幀(Stack Frame)用於儲存區域性變數表、運算元棧、動態連結、方法出口等資訊。每一個方法從呼叫直至執行結束,就對應著一個棧幀從虛擬機器棧中入棧到出棧的過程。 沒有類資訊,類資訊是在方法區中
C.java堆:對於絕大多數應用來說,這塊區域是 JVM 所管理的記憶體中最大的一塊。執行緒共享,主要是存放物件例項和陣列
D.方法區:屬於共享記憶體區域,儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。
378 下面語句正確的是(D)
x+1=5
i++=1
a++b=1
x+=1
賦值運算子左側必須為變數
總結一下: 1-首先賦值運算子“=”右值可以是任何常數、變數或者表示式(只要能生成一個值就行)。但左值必須是一個明確的、已命名的變數。 2-常用的雙元運算子:+=,-=,*=,/= 解析: A:x+1=5,賦值運算子左邊是表示式,不對; B:i++=1,從左到右運算是i=i+1=1,賦值運算子左邊是表示式,錯誤; C:a++b=1,賦值運算子左邊為表示式,錯誤。D:x+=1,既x=x+1,正確。 注意背一下各個運算子的先後順序。
379 下列說法正確的是(B)
在類方法中可用this來呼叫本類的類方法
在類方法中呼叫本類的類方法時可直接呼叫
在類方法中只能呼叫本類中的類方法
在類方法中絕對不能呼叫例項方法
B :類方法是指用static修飾的方法,普通方法叫物件方法。 A.this指的是當前物件,類方法依附於類而不是物件this會編譯出錯 C.類方法中也可以呼叫其他類的類方法。同時可以通過建立物件來呼叫普通方法 D.類方法中可以建立物件,所以可以呼叫例項方法
380 以下程式碼段執行後的輸出結果為 D
public class Test {
public static void main(String args[]) {
int x = -5;
int y = -12;
System.out.println(y % x);
}
}
-1
2
1
-2
Y(被除數) % X(除數) 當除數與被除數的符號相同時,取餘和取模的結果是完全相同的; 當除數與被除數的符號不相同時,結果不同。 具體說,取餘結果的符號與被除數相同;取模結果的符號與除數相同。 通常取模運算也叫取餘運算,他們都遵循除法法則,返回結果都是餘數; 1.取餘 rem(3,2)=1 rem(-3,-2)=-1 rem(3,-2)=1 rem(-3,2)=-1 2.取模 mod(3,2)=1 mod(-3,-2)=-1 mod(3,-2)=-1 mod(-3,2)=1
381下面程式的執行結果:(B)
public static void main(String args[]) {
Thread t=new Thread(){
public void run(){
dianping();
}
};
t.run();
System.out.print("dazhong");
}
static void dianping(){
System.out.print("dianping");
}
dazhongdianping
dianpingdazhong
a和b都有可能
dianping迴圈輸出,dazhong夾雜在中間
在上面main()方法中,並沒有建立一個新的執行緒,只是簡單地方法呼叫而已,如果想要建立執行緒,需要t.start();建立執行緒,等待cpu時間片,而run()方法只是簡單地方法呼叫,所以先執行run(),再輸出dazhong
如果呼叫run() 選b
如果呼叫start() 選c
因為呼叫start後並不保證執行緒啟動的順序
這裡僅僅是呼叫了run()方法,程式就只能順序執行;開啟執行緒是呼叫start()方法,這樣才能併發執行。
382 對檔名為Test.java的java程式碼描述正確的是©
class Person {
String name = "No name";
public Person(String nm) {
name = nm;
}
}
class Employee extends Person {
String empID = "0000";
public Employee(String id) {
empID = id;
}
}
public class Test {
public static void main(String args[]) {
Employee e = new Employee("123");
System.out.println(e.empID);
}
}
輸出:0000
輸出:123
編譯報錯
輸出:No name
父類沒有無參的建構函式,所以子類需要在自己的建構函式中顯式呼叫父類的建構函式,
新增
super(“nm”);
否則報錯:
Implicit super constructor Person() is undefined. Must explicitly invoke another constructor
子類的構造方法總是先呼叫父類的構造方法,如果子類的構造方法沒有明顯地指明使用父類的哪個構造方法,子類就呼叫父類不帶引數的構造方法。
而父類沒有無參的建構函式,所以子類需要在自己的建構函式中顯示的呼叫父類的建構函式。
383 表示式(short)10/10.2*2運算後結果是什麼型別?C
short
int
double
float
首先,要注意是(short)10/10.22,而不是(short) (10/10.22),前者只是把10強轉為short,又由於式子中存在浮點數,所以會對結果值進行一個自動型別的提升,浮點數預設為double,所以答案是double;後者是把計算完之後值強轉short。
384 在Web應用程式中,( )負責將HTTP請求轉換為HttpServletRequest物件C
Servlet物件
HTTP伺服器
Web容器
JSP網頁
web容器是一種服務程式,在伺服器一個埠就有一個提供相應服務的程式,而這個程式就是處理從客戶端發出的請求,如JAVA中的Tomcat容器,ASP的IIS或PWS都是這樣的容器。一個伺服器可以多個容器。
Apache就是一個Http伺服器,Tomcat是一個web容器,靜態的htmlApache還可以處理,但是動態的需要轉發給Tomcat去處理了,比如jsp頁面,請求先經由Apache轉發給Tomcat再由Tomcat解析請求。所以應該是web容器去解析成request物件。
servlet是執行在伺服器端的小應用程式,是接收網路服務的請求和產生響應的一種方式。
servlet的功能:接受http請求,產生動態http響應。
385 在 myjsp.jsp 中,關於下面的程式碼說法錯誤的是: ( A)
<%@ page language=“java” import=“java.util.*” errorPage=“error.jsp” isErrorPage=“false” %>
該頁面可以使用 exception 物件
該頁面發生異常會轉向 error.jsp
存在 errorPage 屬性時,isErrorPage 是預設為 false
error.jsp 頁面一定要有isErrorPage 屬性且值為 true
exception是JSP九大內建物件之一,其例項代表其他頁面的異常和錯誤。只有當頁面是錯誤處理頁面時,即isErroePage為 true時,該物件才可以使用。對於C項,errorPage的實質就是JSP的異常處理機制,發生異常時才會跳轉到 errorPage指定的頁面,沒必要給errorPage再設定一個errorPage。所以當errorPage屬性存在時, isErrorPage屬性值為false
當isErrorPage ="false"時,用errorPage=“error.jsp”(isErrorPage預設是false)
當isErrorPage ="true"時,頁面會直接使用exception
errorPage 的意思是設定當前頁面要引入錯誤的頁面。也就是浮面當前頁面如果出現錯誤就會跳轉到errorPage所指定的頁面。
isErrorpage 的意思是當前頁面為錯誤頁面。
isErrorPage預設值為false,若要當前頁面為錯誤頁面就設定isErrorPage=true。
386 下列整型常量 i 的定義中,正確的是( C )
final i;
static int i;
static final int i=234;
final float i=3.14f;
因為是整型所以要申明 int
所以A D不對又因為是常量所以 要用final限制所以答案 C
題目中有要求是‘整型’‘常量’ ,所以int final這兩個關鍵字必須有,而被final修飾的常量必須賦值,所以選C
== java中final修飾的變數有三種:靜態變數、例項變數和區域性變數==,分別表示三種型別的常量。int關鍵字修飾整型型別。static修飾靜態變數,即當利用這個關鍵字來修飾一個變數的時候,在建立物件之前就會為這個變數在記憶體中建立一個儲存空間。以後建立對物件如果需要用到這個靜態變數,那麼就會共享這一個變數的儲存空間。
A:缺少必要的整型型別宣告
B:缺少常量關鍵字final
D:定義一個浮點常量
387 以下Java程式執行的結果是:A
public class Tester{
public static void main(String[] args){
Integer var1=new Integer(1);
Integer var2=var1;
doSomething(var2);
System.out.print(var1.intValue());
System.out.print(var1==var2);
}
public static void doSomething(Integer integer){
integer=new Integer(2);
}
}
1true
2true
1false
2false
Java中處理8種基本的資料型別用的是值傳遞,其他所有型別都用的是引用傳遞,由於這8種基本資料型別的包裝型別都是不可變類,因此增加了對“按引用傳遞”的理解難度。其實還是很好理解的,題目中doSomething方法中new了一個物件,這是誤導大家選擇答案C的原因。其實,按引用傳遞的實質是將地址值的副本作為實參代替方法中的形參,因此var2與var1裡面儲存的地址值仍然是一樣的,方法中操作的只是var2的一個副本值,並不影響var2本身儲存的地址值,所以答案選擇A。
388 Java 提供的事件處理模型是一種人機互動模型。它有三個基本要素 ABD
事件源
事件物件
事件過程
事件監聽器
解釋:
物件導向的語言裡沒有“過程”
程式導向的語言裡沒有“物件”
Java 提供的事件處理模型是一種人機互動模型。它有三個基本要素:
-
事件源(Event Source):即事件發生的場所,就是指各個元件,如按鈕等,點選按鈕其實就是元件上發生的一個事件;
-
事件(Event):事件封裝了元件上發生的事情,比如按鈕單擊、按鈕鬆開等等;
-
事件***(Event Listener):負責監聽事件源上發生的特定型別的事件,當事件到來時還必須負責處理相應的事件;
389 true、false、null、sizeof、goto、synchronized 哪些是Java關鍵字?EF
true
false
null
sizeof
goto
synchronized
1,Java 關鍵字列表 (依字母排序 共50組):
abstract, assert, boolean, break, byte, case, catch, char, class, const(保留關鍵字), continue, default, do, double, else, enum, extends, final, finally, float, for, goto(保留關鍵字), if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while
2,保留字列表 (依字母排序 共14組),Java保留字是指現有Java版本尚未使用,但以後版本可能會作為關鍵字使用:
byValue, cast, false, future, generic, inner, operator, outer, rest, true, var, goto (保留關鍵字) , const (保留關鍵字) , null
java的關鍵字對Java的編譯器有特殊的意義,他們用來表示一種資料型別,或者表示程式的結構等,關鍵字不能用作變數名、方法名、類名、包名和引數。
true false 是boolean的變數值,是編譯器賦予特定含義的,但並不是關鍵字
390 以下程式碼將列印出 B
public static void main(String args[]) {
List Listlist1 = new ArrayList();
Listlist1.add(0);
List Listlist2 = Listlist1;
System.out.println(Listlist1.get(0) instanceof Integer);
System.out.println(Listlist2.get(0) instanceof Integer);
}
編譯錯誤
true true
true false
false false
collection型別的集合(ArrayList,LinkedList)只能裝入物件型別的資料,該題中裝入了0,是一個基本型別,但是JDK5以後提供了自動裝箱與自動拆箱,所以int型別自動裝箱變為了Integer型別。編譯能夠正常通過。
將list1的引用賦值給了list2,那麼list1和list2都將指向同一個堆記憶體空間。instanceof是Java中關鍵字,用於判斷一個物件是否屬於某個特定類的例項,並且返回boolean型別的返回值。顯然,list1.get(0)和list2.get(0)都屬於Integer的例項
答案B 不指定ArrayList型別,存入資料,再次取出時,預設是Object型別;但這個題的關鍵是instanceof關鍵字,instanceof執行時類似利用java反射機制,識別物件資訊。
List集合中的元素必須是物件。
Listlist1.add(0);JDK1.5之後支援自動裝箱(int型別自動裝箱成Integer),編譯通過。
instanceof:前一個引數通常是一個引用型別變數,後一個運算元通常是一個類(也可以是一個介面, 它用於判斷前面的物件是否是後面的類,或者其子類、實現類的例項。
List沒有使用泛型,說明使用get(0)取出的元素的編譯型別是Object型的, 但執行時型別是Integer。所以列印true。這便體現了多型。
而Listlist1把引用賦給了List list2,說明兩個指向同一個物件。第二個列印的也是true。
391 變數a是一個64位有符號的整數,初始值用16進製表示為:0x7FFFFFFFFFFFFFFF;變數b是一個64位有符號的整數,初始值用16進製表示為:0x8000000000000000。則a+b的結果用10進製表示為多少?B
1
-1
2^63+2^62+…+2^2+2^1+2^0
–(2^63+2^62+…+2^2+2^1+2^0)
(1)a+b的16進製表示為:OxFFFFFFFFFFFFFFF(16位F),轉為2進製為111……111(64位1,每個F->4位2)。
(2)有符號數:是針對二進位制來講的。用最高位作為符號位,“0”代表“+”,“1”代表“-”。所以a+b的結果是一個負數。
(3)計算機中負數是以補碼的形式儲存的,將補碼轉換成原碼的計算方式如下:
①. 對於正數,原碼與補碼相同。
②.對於負數,將補碼除符號位之外,按位取反,末位加1,即得到原碼。
(4)a + b = 111……111(64位1)
取反:100……000(1位1,後面63位0)
加一:100……00(中間62位0)
10進位制:-1。
392 java中Hashtable, Vector, TreeSet, LinkedList哪些執行緒是安全的?AB
Hashtable
Vector
TreeSet
LinkedList
Hashtable是執行緒安全的HashMap
Vector是執行緒安全的ArrayList
TreeSet和LinkedList都不是執行緒安全的
執行緒安全概念:
如果你的程式碼所在的程式中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段程式碼。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。
執行緒安全問題都是由全域性變數及靜態變數引起的。
若每個執行緒中對全域性變數、靜態變數只有讀操作,而無寫操作,一般來說,這個全域性變數是執行緒安全的;若有多個執行緒同時執行寫操作,一般都需要考慮執行緒同步,否則的話就可能影響執行緒安全。
LinkedList 和 ArrayList 都是不同步的,執行緒不安全;
Vector 和 Stack 都是同步的,執行緒安全;
Set是執行緒不安全的;
Hashtable的方法是同步的,執行緒安全;
HashMap的方法不是同步的,執行緒不安全;
簡單記憶執行緒安全的集合類: 喂! SHE ! 喂是指 vector , S 是指 stack , H 是指 hashtable , E 是指: Eenumeration
393 判斷一塊記憶體空間是否符合垃圾收集器收集的標準有哪些?ABD
給物件賦予了空值null,以下再沒有呼叫過
物件重新分配了記憶體空間
給物件賦予了空值null
給物件賦予了新值
在java語言中,判斷一塊記憶體空間是否符合垃圾收集器收集標準的標準只有兩個:
1.給物件賦值為null,以下沒有呼叫過。
2.給物件賦了新的值,重新分配了記憶體空間。
Cat obj=new Cat();
obj=null;//這個應該叫物件的引用置為了null,回收的是之前new Cat()時申請到的記憶體
obj=new Cat();//這個叫物件引用重新指向了另外一個物件,賦予了新值,回收的是上次new Cat()的記憶體
應該是這麼理解吧
394 在 Java 中,存放字串常量的物件屬於( B)類物件。
Character
String
StringBuffer
Vector
Character 字元封裝類
String 常量池中字串
StringBuffer 存放字元陣列
Vector 陣列
存放字串的可以為String和StringBuffer,前者定義的字串不可變,後者可變,Character為字元型的包裝型別
Vector與ArrayList類似,都實現了list介面,內部都是通過陣列實現的,但是Vector支援執行緒的同步,避免了多執行緒引起的不一致性
生成字串的兩個類String和StringBuffer中,前者生成的字串是不變字串,不能直接對它的內容進行修改,而後者生成的字串是可變的,可以對其內容進行修改。而Character類是對字元型別的類封裝。Vector類是Java語言提供給使用者的一種通用類,是一種連結串列結構的型別。
395 下面的程式 編譯執行後,在螢幕上顯示的結果是(A)
public class test {
public static void main(String args[]) {
int x,y;
x=5>>2;
y=x>>>2;
System.out.println(y);
}
}
5 >> 2 相當於 5除於2的平方,等於1 ,>>> 表示無符號 右移,高位用0 填充,0001 右移兩位 0000,所以答案選 A
Java中的位運算子:
>>表示右移,如果該數為正,則高位補0,若為負數,則高位補1;
>>>表示無符號右移,也叫邏輯右移,即若該數為正,則高位補0,而若該數為負數,則右移後高位同樣補0。
5的二進位制是0101。
x=5>>2 (>>帶符號右移)
將0101右移2位,為:0001。
y=x>>>2 (>>>無符號右移,左邊空缺補充為0)
將0001右移2位,補0。結果為:0000。
所以得出答案0
這道題首先要知道二進位制的計算方式
舉例:0011
二進位制換算十進位制,從右到左,以當前位數字 乘以 2 的索引字冪,然後相加,索引從0開始計算。
如:
右一數字為1,索引為0。所以為:1*2^0(1乘以2的0次方)
右二數字為1,索引為1。所以為:1*2^1(1乘以2的1次方)
右三數字為0,索引為2。所以為:0*2^2(0乘以2的2次方)
右四數字為0,索引為3。所以為:0*2^3(0乘以2的3次方)
最後把結果相加。所以計算方式為:
023+0*22+121+1*20
=0+0+2+1
=3
396 計算機所能處理的最小的資料項稱為(A)
位
位元組
字
雙字
位<位元組<字<雙字
1雙字=2字=4位元組=32位
位、位元組、字是計算機資料儲存的單位。位是最小的儲存單位,每一個位儲存一個1位的二進位制碼,一個位元組由8位組成。而字通常為16、32或64個位組成。
397 執行語句“int a= ’ 2 ’ ”後,a的值是( B)
2
50
49
0
常用ASCII碼值:空格為32;數字0為48;“A”為65;“a”值為97。
常見字元的ASCII碼值如下:空格的ASCII碼值為32;數字0到9的ASCII碼值分別為48到57;大寫字母“A”到“Z”的ASCII碼值分別為65到90;小寫字母“a”到“z”的ASCII碼值分別為97到到122。
398 下面不是物件導向的基本原則的是?C
單一職責原則(Single-Resposibility Principle)
開放封閉原則(Open-Closed principle)
抽象類原則(Abstract-Class principle)
依賴倒置原則(Dependecy-Inversion Principle)
介面隔離原則(Interface-Segregation Principle)
s( Single-Resposibility Principle ): 單一職責原則
o( Open-Closed principle ): 開放封閉原則
l( Liskov-Substituion Principle ): 里氏原則
i( Interface-Segregation Principle ): 介面隔離原則
d( Dependecy-Inversion Principle ): 依賴倒置原則
一個單詞:立方體(solid),很好記!!!
五個基本原則:
單一職責原則(Single-Resposibility Principle):一個類,最好只做一件事,只有一個引起它的變化。單一職責原則可以看做是低耦合、高內聚在物件導向原則上的引申,將職責定義為引起變化的原因,以提高內聚性來減少引起變化的原因。
開放封閉原則(Open-Closed principle):軟體實體應該是可擴充套件的,而不可修改的。也就是,對擴充套件開放,對修改封閉的。
Liskov替換原則(Liskov-Substituion Principle):子類必須能夠替換其基類。這一思想體現為對繼承機制的約束規範,只有子類能夠替換基類時,才能保證系統在執行期內識別子類,這是保證繼承複用的基礎。
依賴倒置原則(Dependecy-Inversion Principle):依賴於抽象。具體而言就是高層模組不依賴於底層模組,二者都同依賴於抽象;抽象不依賴於具體,具體依賴於抽象。
介面隔離原則(Interface-Segregation Principle):使用多個小的專門的介面,而不要使用一個大的總介面
399 說明輸出結果。 C
package test;
import java.util.Date;
public class SuperTest extends Date{
private static final long serialVersionUID = 1L;
private void test(){
System.out.println(super.getClass().getName());
}
public static void main(String[]args){
new SuperTest().test();
}
}
SuperTest
SuperTest.class
test.SuperTest
test.SuperTest.class
TestSuper和Date的getClass都沒有重寫,他們都是呼叫Object的getClass,而Object的getClass作用是返回的是執行時的類的名字。這個執行時的類就是當前類,所以
super.getClass().getName()
返回的是test.SuperTest,與Date類無關
要返回Date類的名字需要寫super.getClass().getSuperclass()
1.首先 super.getClass() 是父類的getClass()方法,其父類是Date,它的getClass()方法是繼承自Object類而且沒有重寫,
所以就是呼叫object的getClass()方法。而看一下getclass的方法解釋如下圖
所以可以知道是返回當前執行時的類。
2.==在呼叫getName()方法而getName()是:包名+類名 ==
super.getClass().getName()
返回:包名+類名
400 如下哪些是 java 中有效的關鍵字(AD)
native
NULL
false
this
這個關鍵字常見的坑:
true、false不是關鍵字,而是保留字
goto、const、是保留的關鍵字
null是java中的關鍵字,但是本題中大寫的NULL就不是了
相關文章
- Java基礎知識(牛客刷題)記錄..(持續輸出中)Java
- 牛客網刷題(純java題型 31~60題)Java
- 牛客網刷題(純java題型 1~30題)Java
- 牛客網刷題(純java題型 91~120題)Java
- 牛客網刷題(純java題型 241~270題)Java
- 牛客網刷題(純java題型 421~450題)Java
- 牛客網SQL刷題31-40SQL
- 牛客網SQL刷題41-50SQL
- 牛客網刷題hj1-hj4
- 牛客錯題集(Java)Java
- java基礎 -反射筆記Java反射筆記
- Java基礎回顧(牛客網專案課程)Java
- leetcode刷題筆記LeetCode筆記
- 刷題筆記02筆記
- 刷題筆記03筆記
- LeetCode 刷題筆記LeetCode筆記
- 牛客網Java評估題Java
- Java基礎 語法筆記Java筆記
- Java基礎語法筆記Java筆記
- Java基礎學習筆記Java筆記
- noip刷題筆記1筆記
- 【刷題筆記】2024.10.4 test筆記
- leetcode刷題筆記605LeetCode筆記
- Java基礎-學習筆記17Java筆記
- Java基礎-學習筆記07Java筆記
- Java基礎-學習筆記06Java筆記
- Java基礎-學習筆記05Java筆記
- Java基礎-學習筆記04Java筆記
- Java 基礎程式設計筆記Java程式設計筆記
- (Java筆記)物件導向基礎Java筆記物件
- Java學習筆記01 - JavaSE基礎Java筆記
- leetcode刷題筆記(3)(python)LeetCode筆記Python
- 牛客網初級專案筆記(一)筆記
- [Java] Introduction to Java Programming 筆記: Chapter 2. 基礎Java筆記APT
- Java基礎題目記錄-01Java
- 【刷題1】LeetCode 39. 組合總和 java基礎LeetCodeJava
- 牛客15天刷題ZT50_小美的樹上染色
- Golang 學習筆記(一) - HTTP 客戶端 - 基礎Golang筆記HTTP客戶端