日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java常问面试题

發布時間:2023/12/31 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java常问面试题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

知識點1:

&運算符:兩個數都轉為二進制,然后從兩個數的最高位進行與運算,兩個都為真(1),結果才為真(1),否則為假(0)13:01101 17:10001結果:00001,既為1。

補充:

與運算 (“ & ”)
參與運算的兩個數據,按照二進制位進行“與運算”。
運算規則:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:兩位同時為1,則值為1。否則為0
例如:6 & 7 = 110 & 111 = 110 = 6
8 & 3 = 1000 & 11 = 0 = 0

或運算 (“ | ”) 
參與運算的兩個數據,按照二進制位進行“或運算”。
運算規則:0&0=0; 0&1=1; 1&0=1; 1&1=1;
即:參與運算的兩個數據只要有一個值為1 那么值為1
例如:12 | 5 = 1100 | 101 = 1101 = 13
4 | 5 = 100 | 101 = 101 = 5

異或運算 (“ ^ ”)
參與 運算的兩個數據,按照二進制位進行“異或運算”。
運算規則: 0&0=0; 0&1=1; 1&0=1; 1&1=0;
即:參加運算的兩個對象,如果兩個相應位為“異”(值不同),則該位結果為1,否則為0。
例如:9^5可寫成算式如下: 00001001^00000101=00001100 (十進制為12)可見9^5=12

知識點2:

包的作用
1、把功能相似或相關的類或接口組織在同一個包中,方便類的查找和使用。

2、如同文件夾一樣,包也采用了樹形目錄的存儲方式。同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時調用兩個不同包中相同類名的類時,應該加上包名加以區別。因此,包可以避免名字沖突。

3、包也限定了訪問權限,擁有包訪問權限的類才能訪問某個包中的類。

Java 使用包(package)這種機制是為了防止命名沖突,訪問控制,提供搜索和定位類(class)、接口、枚舉(enumerations)和注釋(annotation)等。

知識點3:

把常用的tar解壓命令總結下,當作備忘:

tar

-c: 建立壓縮檔案
-x:解壓
-t:查看內容
-r:向壓縮歸檔文件末尾追加文件
-u:更新原壓縮包中的文件

知識點4:

i++和++i命令的區別有:

1、賦值順序不同

++ i 是先加后賦值;i ++ 是先賦值后加;++i和i++都是分兩步完成的。

因為++i 是后面一步才賦值的,所以它能夠當作一個變量進行級聯賦值,++i = a =b,即 ++i 是一個左值;i++ 的后面一步是自增,不是左值。

形象的理解可以是i++先做別的事,再自己加1,++i先自己加1,再做別的事情。

2、效率不同

比如i=3,b=i++就是說b=3,完成之后讓i變成4,b=++i就是先讓i++變成4,然后b=4,其中++i比i++效率要高些。一般來說在循環域里面,這兩者并沒有什么很大的區別,但是要注意其生存周期,以及i值在程序流中的變化。

3、 i++ 不能作為左值,而++i 可以。

知識點5:

shell中的特殊變量: 變量名 含義 $0 shell或shell腳本的名字 $* 以一對雙引號給出參數列表 $@ 將各個參數分別加雙引號返回 $# 參數的個數 $_ 代表上一個命令的最后一個參數 $$ 代表所在命令的PID $! 代表最后執行的后臺命令的PID $? 代表上一個命令執行后的退出狀態 echo $? 如果返回值是0,就是執行成功;如果是返回值是0以外的值,就是失敗。

知識點6:

Stack 棧 先進后出
Queue 隊列 先進先出
List 集合 有下標 存的順序與取得的順序一致
LinedList 類 是Queue的子類 存的順序與取得的順序一致

知識點7:

Java只支持單繼承,實現多重繼承三種方式:

(1)直接實現多個接口

(2)擴展(extends)一個類然后實現一個或多個接口

(3)通過內部類去繼承其他類

知識點8:

flush()函數強制將緩沖區中的字符流、字節流等輸出,目的是如果輸出流輸出到緩沖區完成后,緩沖區并沒有填滿,那么緩沖區將會一直等待被填滿。所以在關閉輸出流之前要調用flush()。

線程圖

知識點9:

數據段 :數據段(data segment)通常是指用來存放程序中 已初始化 的 全局變量 的一塊內存區域。數據段屬于靜態內存分配。
代碼段: 代碼段(code segment/text segment)通常是指用來存放 程序執行代碼 的一塊內存區域。這部分區域的大小在程序運行前就已經確定,并且內存區域通常屬于 只讀 , 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些 只讀的常數變量 ,例如字符串常量等。程序段為程序代碼在內存中的映射.一個程序可以在內存中多有個副本.

堆(heap) :堆是用于存放進程運行中被動態分配的內存段,它的大小并不固定,可動態擴張或縮減。當進程調用malloc/free等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張)/釋放的內存從堆中被剔除(堆被縮減)

棧(stack) :棧又稱堆棧, 存放程序的 局部變量 (但不包括static聲明的變量, static 意味著 在數據段中 存放變量)。除此以外,在函數被調用時,棧用來傳遞參數和返回值。由于棧的先進先出特點,所以棧特別方便用來保存/恢復調用現場。儲動態內存分配,需要程序員手工分配,手工釋放

知識點10:

大多數 JVM 將內存區域劃分為 Method Area(Non-Heap)(方法區) ,Heap(堆) , Program Counter Register(程序計數器) , VM Stack(虛擬機棧,也有翻譯成JAVA 方法棧的),Native Method Stack本地方法棧 ),其中Method AreaHeap 是線程共享的 ,VM Stack,Native Method Stack 和Program Counter Register 是非線程共享的。為什么分為 線程共享和非線程共享的呢?請繼續往下看。

首先我們熟悉一下一個一般性的 Java 程序的工作過程。一個 Java 源程序文件,會被編譯為字節碼文件(以 class 為擴展名),每個java程序都需要運行在自己的JVM上,然后告知 JVM 程序的運行入口,再被 JVM 通過字節碼解釋器加載運行。那么程序開始運行后,都是如何涉及到各內存區域的呢?

概括地說來,JVM初始運行的時候都會分配好 Method Area(方法區)Heap(堆) ,而JVM 每遇到一個線程,就為其分配一個 Program Counter Register(程序計數器) , VM Stack(虛擬機棧)和Native Method Stack (本地方法棧), 當線程終止時,三者(虛擬機棧,本地方法棧和程序計數器)所占用的內存空間也會被釋放掉。這也是為什么我把內存區域分為線程共享和非線程共享的原因,非線程共享的那三個區域的生命周期與所屬線程相同,而線程共享的區域與JAVA程序運行的生命周期相同,所以這也是系統垃圾回收的場所只發生在線程共享的區域(實際上對大部分虛擬機來說知發生在Heap上)的原因。

知識點11:

PROPAGATION_SUPPORTS 從翻譯上看--僅僅支持事務,沒有就沒有唄 PROPAGATION_REQUIRED 支持事務,如果有,就用著,沒有的話就自己弄一個 PROPAGATION_REQUIRES_NEW 比較有個性,不管有沒有,都自己弄一個(把原來的放在一邊) PROPAGATION_MANDATORY 強制必須要有事務,要是沒有,就不開心了(拋出異常) PROPAGATION_NOT_SUPPORTED 不支持事務,有就掛起來 PROPAGATION_NEVER 此處事務與狗不得入內,如果有,就趕出去(拋出異常)

知識點12:

Servlet的生命周期分為5個階段:加載、創建、初始化、處理客戶請求、卸載。

(1)加載:容器通過類加載器使用servlet類對應的文件加載servlet

(2)創建:通過調用servlet構造函數創建一個servlet對象

(3)初始化:調用init方法初始化

(4)處理客戶請求:每當有一個客戶請求,容器會創建一個線程來處理客戶請求

(5)卸載:調用destroy方法讓servlet自己釋放其占用的資源

servlet在多線程下其本身并不是線程安全的。

如果在類中定義成員變量,而在service中根據不同的線程對該成員變量進行更改,那么在并發的時候就會引起錯誤。最好是在方法中,定義局部變量,而不是類變量或者對象的成員變量。由于方法中的局部變量是在棧中,彼此各自都擁有獨立的運行空間而不會互相干擾,因此才做到線程安全。

知識點13:

redirect:請求重定向:客戶端行為,本質上為2次請求,地址欄改變,前一次請求對象消失。舉例:你去銀行辦事(forward.jsp),結果告訴你少帶了東西,你得先去局辦(index.html)臨時身份證,這時你就會走出銀行,自己前往***局,地址欄變為index.html.

forward:請求轉發:服務器行為,地址欄不變。舉例:你把錢包落在出租車上,你去警察局(forward.jsp)報案,警察局說錢包落在某某公司的出租車上(index.html),這時你不用親自去找某某公司的出租車,警察局讓出租車自己給你送來,你只要在警察局等就行。所以地址欄不變,依然為forward.jsp

知識點14:

-Xmx10240m:代表最大堆

-Xms10240m:代表最小堆

-Xmn5120m:代表新生代

-XXSurvivorRatio=3:代表Eden:Survivor = 3 根據Generation-Collection算法(目前大部分JVM采用的算法),一般根據對象的生存周期將堆內存分為若干不同的區域,一般情況將新生代分為Eden ,兩塊Survivor; 計算Survivor大小, Eden:Survivor = 3,總大小為5120,3x+x+x=5120 x=1024

新生代大部分要回收,采用Copying算法,快!

老年代 大部分不需要回收,采用Mark-Compact算法

知識點15:

**選擇排序:**每次從數組中選出一個最小數(最大數)放到數組最前面,存放在序列的起始位置,直到全部待排序的數據元素排完。

**希爾排序:**設置增量分割數組,逐步進行直接插入排序,增量逐趟減少,并最后使得整個數組基本有序,再對整體進行直接插入排序。

**插入排序:**構建有序序列,未排序數據依次從已排序數據按從后往前比較,插入到合適的位置。

**歸并排序:**把序列分成兩個長度為n/2的子序列,對這兩個子序列分別歸并排序(循環將兩個數組的第一個值比較,并彈出第一個值, 直到數組長度都不存在),將兩個排序好的子序列合并成一個最終的排序序列

知識點16:

信號量的P、V操作,P表示申請一個資源,每次P操作使信號量減1,V是釋放一個資源,每次V操作使信號量加1.信號量表示的是當前可用的資源個數,當信號量為負時,申請資源的進程就只能等待了.所以,信號量是負的多少,就表明有多少個進程申請了資源但無資源可用只能處于等待狀態.

NIO是同步非阻塞,通過選擇器Selector監聽多個通道(Channel),響應其感興趣的事件(每個通道在選擇器上注冊的事件).(Reactor模式)

知識點17:

1.數據庫的事務交給JDBC的Connection去處理.

? connection.autoCommit(false); //相當于在數據庫端開啟事務 start transaction;

? connection.setTransactioIsolation(isolation); //設置隔離級別;

? connection.commit(); //提交事務

? connection.rollback(savePoint);//回滾

2.JTA是指Java Transaction API,JTA允許應用程序執行分布式事務處理.

? 分布式事務(distributed transaction)包括一個事務管理器(transaction manager)和一個或多個資源管理器(resource manager).

知識點18:

1.抽象方法只能定義在抽象類中,抽象方法和抽象類必須由abstract修飾,abstract關鍵字只能描述類和方法,不能描述變量。抽象方法只定義方法聲明,不定義方法實現。抽象類不可以被實例化(創建對象),只有通過子類繼承抽象類并覆蓋抽象類中的所有抽象方法后,該子類才可以被實例化,否則該子類還是一個抽象類。抽象類中有構造函數用于給子類對象進行初始化,同時抽象類中可以含有非抽象方法。abstract關鍵字不可以與final,private,static關鍵字共存,因為被final修飾的方法不可以被重寫,意味著子類不可以重寫該方法,如果abstract和final共同修飾父類中的方法,子類要實現抽象方法(abstract的作用),而final又不讓該方法重寫,這相互矛盾。如果private和abstract共同修飾父類中的方法,private修飾則該方法不可以被子類訪問,但是abstract修飾需要子類去實現,兩者產生矛盾。如果static和abstract共同修飾父類中的方法,static表示是靜態的方法,隨著類的加載而加載,則該方法不需要在子類中去實現,這與abstract關鍵字矛盾。 2.static用于修飾成員變量和成員函數,想要實現對象中的共性數據的對象共享,可以將這個數據進行靜態修飾,被靜態修飾的成員可以直接被類名調用,靜態隨著類的加載而加載,而且優先于對象存在。靜態方法只能訪問靜態成員(靜態方法和靜態變量),不可以訪問非靜態成員,這是因為靜態方法加載時,優先于對象存在,所以沒有辦法訪問對象中的成員。靜態方法中不能使用this和super關鍵字,因為this代表本類對象,super代表父類對象,而靜態時,有可能沒有對象存在,所以this和super無法使用。 3.final關鍵字可以修飾類,方法,變量(成員變量內,局部變量,靜態變量),被final修飾的類是一個最終類,不可以被繼承,被final修飾的方法是一個最終方法,不可以被覆蓋,但是可以被繼承。被final修飾的變量只能是一個常量,只能賦值一次。內部類被定義在類中的局部位置上時,只能訪問局部被final修飾的局部變量。

知識點19:

JDK中提供了三個ClassLoader,根據層級從高到低為:

  • Bootstrap ClassLoader,主要加載JVM自身工作需要的類。
  • Extension ClassLoader,主要加載%JAVA_HOME%\lib\ext目錄下的庫類。
  • Application ClassLoader,主要加載Classpath指定的庫類,一般情況下這是程序中的默認類加載器,也是ClassLoader.getSystemClassLoader() 的返回值。(這里的Classpath默認指的是環境變量中配置的Classpath,但是可以在執行Java命令的時候使用-cp 參數來修改當前程序使用的Classpath)
  • JVM加載類的實現方式,我們稱為 雙親委托模型

    如果一個類加載器收到了類加載的請求,他首先不會自己去嘗試加載這個類,而是把這個請求委托給自己的父加載器,每一層的類加載器都是如此,因此所有的類加載請求最終都應該傳送到頂層的Bootstrap ClassLoader中,只有當父加載器反饋自己無法完成加載請求時,子加載器才會嘗試自己加載。

    雙親委托模型的重要用途是為了解決類載入過程中的安全性問題。

    假設有一個開發者自己編寫了一個名為Java.lang.Object的類,想借此欺騙JVM。現在他要使用自定義ClassLoader來加載自己編寫的java.lang.Object類。然而幸運的是,雙親委托模型不會讓他成功。因為JVM會優先在Bootstrap ClassLoader的路徑下找到java.lang.Object類,并載入它

    知識點20:

    final

    如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為 abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在new一個對象時初始化(即只能在聲明變量或構造器或代碼塊內初始化),而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能覆蓋(重寫)。

    finally

    在異常處理時提供 finally 塊來執行任何清除操作。如果拋出一個異常,那么相匹配的 catch 子句就會執行,然后控制就會進入 finally 塊(如果有的話)。

    finalize

    方法名。Java 技術允許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個對象調用的。注意:finalize不一定被jvm調用,只有當垃圾回收器要清除垃圾時才被調用。

    知識點21:

    /*** Definition of TreeNode:* public class TreeNode {* public int val;* public TreeNode left, right;* public TreeNode(int val) {* this.val = val;* this.left = this.right = null;* }* }*/public class Solution {/*** @param root: A Tree* @return: Preorder in ArrayList which contains node values.*//*** 先序遍歷二叉樹*/public List<Integer> preorderTraversal(TreeNode root) {// write your code hereArrayList<Integer> list = new ArrayList<Integer>();if(root == null){return list;}else{list.add(root.val);}if(root.left != null){list.addAll(preorderTraversal(root.left));}if(root.right != null){list.addAll(preorderTraversal(root.right));}return list;} }

    知識點22:

    初始化過程:

    1. 初始化父類中的靜態成員變量和靜態代碼塊

    2. 初始化子類中的靜態成員變量和靜態代碼塊

    3.初始化父類的普通成員變量和代碼塊,再執行父類的構造方法;

    4.初始化子類的普通成員變量和代碼塊,再執行子類的構造方法;

    (1)初始化父類的普通成員變量和代碼塊,執行 Y y=new Y(); 輸出Y

    (2)再執行父類的構造方法;輸出X

    (3) 初始化子類的普通成員變量和代碼塊,執行 Y y=new Y(); 輸出Y

    (4)再執行子類的構造方法;輸出Z

    所以輸出YXYZ

    知識點23:

    按照流是否直接與特定的地方(如磁盤、內存、設備等)相連,分為節點流和處理流兩類。

    • 節點流:可以從或向一個特定的地方(節點)讀寫數據。如FileReader.
    • 處理流:是對一個已存在的流的連接和封裝,通過所封裝的流的功能調用實現數據讀寫。如BufferedReader.處理流的構造方法總是要帶一個其他的流對象做參數。一個流對象經過其他流的多次包裝,稱為流的鏈接。

    JAVA常用的節點流:

    • 文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件進行處理的節點流。
    • 字符串 StringReader StringWriter 對字符串進行處理的節點流。
    • 數 組 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 對數組進行處理的節點流(對應的不再是文件,而是內存中的一個數組)。
    • 管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter對管道進行處理的節點流。

    常用處理流(關閉處理流使用關閉里面的節點流)

    • 緩沖流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter 增加緩沖功能,避免頻繁讀寫硬盤。

    • 轉換流:InputStreamReader OutputStreamReader 實現字節流和字符流之間的轉換。

    • 數據流 DataInputStream DataOutputStream 等-提供將基礎數據類型寫入到文件中,或者讀取出來.

    流的關閉順序

  • 一般情況下是:先打開的后關閉,后打開的先關閉
  • 另一種情況:看依賴關系,如果流a依賴流b,應該先關閉流a,再關閉流b。例如,處理流a依賴節點流b,應該先關閉處理流a,再關閉節點流b
  • 可以只關閉處理流,不用關閉節點流。處理流關閉的時候,會調用其處理的節點流的關閉方法。
  • 知識點24:

    1、LinkedBlockingQueue:基于鏈接節點的可選限定的blocking queue 。 這個隊列排列元素FIFO(先進先出)。 隊列的頭部是隊列中最長的元素。 隊列的尾部是隊列中最短時間的元素。 新元素插入隊列的尾部,隊列檢索操作獲取隊列頭部的元素。 鏈接隊列通常具有比基于陣列的隊列更高的吞吐量,但在大多數并發應用程序中的可預測性能較低。

    blocking queue說明:不接受null元素;可能是容量有限的;實現被設計為主要用于生產者 - 消費者隊列;不支持任何類型的“關閉”或“關閉”操作,表示不再添加項目實現是線程安全的;

    2、PriorityQueue:

    2.1、基于優先級堆的無限優先級queue 。 優先級隊列的元素根據它們的有序natural ordering ,或由一個Comparator在隊列構造的時候提供,這取決于所使用的構造方法。 優先隊列不允許null元素。 依靠自然排序的優先級隊列也不允許插入不可比較的對象(這樣做可能導致ClassCastException )。

    2.2、該隊列的頭部是相對于指定順序的最小元素。 如果多個元素被綁定到最小值,那么頭就是這些元素之一 - 關系被任意破壞。 隊列檢索操作poll , remove , peek和element訪問在隊列的頭部的元件。

    2.3、優先級隊列是無限制的,但是具有管理用于在隊列上存儲元素的數組的大小的內部容量 。 它始終至少與隊列大小一樣大。 當元素被添加到優先級隊列中時,其容量會自動增長。 沒有規定增長政策的細節。

    2.4、該類及其迭代器實現Collection和Iterator接口的所有可選方法。 方法iterator()中提供的迭代器不能保證以任何特定順序遍歷優先級隊列的元素。 如果需要有序遍歷,請考慮使用Arrays.sort(pq.toArray()) 。

    2.5、請注意,此實現不同步。 如果任何線程修改隊列,多線程不應同時訪問PriorityQueue實例。 而是使用線程安全的PriorityBlockingQueue類。

    實現注意事項:此實現提供了O(log(n))的時間入隊和出隊方法( offer , poll , remove()和add ); remove(Object)和contains(Object)方法的線性時間; 和恒定時間檢索方法( peek , element和size )。

    3、ConcurrentLinkedQueue:基于鏈接節點的***并發deque(deque是雙端隊列) 。 并發插入,刪除和訪問操作可以跨多個線程安全執行。 A ConcurrentLinkedDeque是許多線程將共享對公共集合的訪問的適當選擇。像大多數其他并發集合實現一樣,此類不允許使用null元素。

    知識點25:

    ThreadLocal類用來提供線程內部的局部變量。這種變量在多線程環境下訪問(通過get或set方法訪問)時能保證各個線程里的變量相對獨立于其他線程內的變量。ThreadLocal實例通常來說都是private static類型的,用于關聯線程和線程的上下文。 可以總結為一句話:ThreadLocal的作用是提供線程內的局部變量,這種變量在線程的生命周期內起作用,減少同一個線程內多個函數或者組件之間一些公共變量的傳遞的復雜度。 舉個例子,我出門需要先坐公交再做地鐵,這里的坐公交和坐地鐵就好比是同一個線程內的兩個函數,我就是一個線程,我要完成這兩個函數都需要同一個東西:公交卡(北京公交和地鐵都使用公交卡),那么我為了不向這兩個函數都傳遞公交卡這個變量(相當于不是一直帶著公交卡上路),我可以這么做:將公交卡事先交給一個機構,當我需要刷卡的時候再向這個機構要公交卡(當然每次拿的都是同一張公交卡)。這樣就能達到只要是我(同一個線程)需要公交卡,何時何地都能向這個機構要的目的。 有人要說了:你可以將公交卡設置為全局變量啊,這樣不是也能何時何地都能取公交卡嗎?但是如果有很多個人(很多個線程)呢?大家可不能都使用同一張公交卡吧(我們假設公交卡是實名認證的),這樣不就亂套了嘛。現在明白了吧?這就是ThreadLocal設計的初衷:提供線程內部的局部變量,在本線程內隨時隨地可取,隔離其他線程。

    知識點26:

    final可以修飾類、方法、成員變量

    當final修飾類的時候,說明該類不能被繼承

    當final修飾方法的時候,說明該方法不能被重寫

    在早期,可能使用final修飾的方法,編譯器針對這些方法的所有調用都轉成內嵌調用,這樣提高效率(但到現在一般我們不會去管這事了,編譯器和JVM都越來越聰明了)

    當final修飾成員變量時,有兩種情況:

    如果修飾的是基本類型,說明這個變量的所代表數值永不能變(不能重新賦值)!

    如果修飾的是引用類型,該變量所的引用不能變,但引用所代表的對象內容是可變的!

    知識點27:

    依賴注入和控制反轉是同一概念

    依賴注入和控制反轉是對同一件事情的不同描述,從某個方面講,就是它們描述的角度不同。依賴注入是從應用程序的角度在描述,可以把依賴注入描述完整點:應用程序依賴容器創建并注入它所需要的外部資源;而控制反轉是從容器的角度在描述,描述完整點:容器控制應用程序,由容器反向的向應用程序注入應用程序所需要的外部資源。

    知識點28:

    1、**抽象類中的抽象方法(其前有abstract修飾)不能用private、static、synchronized、native訪問修飾符修飾。**原因如下:抽象方法沒有方法體,是用來被繼承的,所以不能用private修飾;static修飾的方法可以通過類名來訪問該方法(即該方法的方法體),抽象方法用static修飾沒有意義;使用synchronized關鍵字是為該方法加一個鎖。。而如果該關鍵字修飾的方法是static方法。則使用的鎖就是class變量的鎖。如果是修飾 類方法。則用this變量鎖。但是抽象類不能實例化對象,因為該方法不是在該抽象類中實現的。是在其子類實現的。所以。鎖應該歸其子類所有。所以。抽象方 法也就不能用synchronized關鍵字修飾了;native,這個東西本身就和abstract沖突,他們都是方法的聲明,只是一個吧方法實現移交給子類,另一個是移交給本地操作系統。如果同時出現,就相當于即把實現移交給子類,又把實現移交給本地操作系統,那到底誰來實現具體方法呢?

    2、**接口是一種特殊的抽象類,接口中的方法全部是抽象方法(但其前的abstract可以省略),所以抽象類中的抽象方法不能用的訪問修飾符這里也不能用。**而且protected訪問修飾符也不能使用,因為接口可以讓所有的類去 實現(非繼承) ,不只是其子類,但是要用public去修飾。接口可以去繼承一個已有的接口。

    抽象類

    特點:
    1.抽象類中可以構造方法
    2.抽象類中可以存在普通屬性,方法,靜態屬性和方法。
    3.抽象類中可以存在抽象方法。
    4.如果一個類中有一個抽象方法,那么當前類一定是抽象類;抽象類中不一定有抽象方法。
    5.抽象類中的抽象方法,需要有子類實現,如果子類不實現,則子類也需要定義為抽象的。
    6,抽象類不能被實例化,抽象類和抽象方法必須被abstract修飾

    關鍵字使用注意:
    抽象類中的抽象方法(其前有abstract修飾)不能用private、static、synchronized、native訪問修飾符修飾。

    接口

    1.在接口中只有方法的聲明,沒有方法體。
    2.在接口中只有常量,因為定義的變量,在編譯的時候都會默認加上public static final
    3.在接口中的方法,永遠都被public來修飾
    4.接口中沒有構造方法,也不能實例化接口的對象。(所以接口不能繼承類)
    5.接口可以實現多繼承
    6.接口中定義的方法都需要有實現類來實現,如果實現類不能實現接口中的所有方法則實現類定義為抽象類。
    7,接口可以繼承接口,用extends

    知識點29:

    JSP內置對象有:
    1.request對象
    客戶端的請求信息被封裝在request對象中,通過它才能了解到客戶的需求,然后做出響應。它是HttpServletRequest類的實例。
    2.response對象
    response對象包含了響應客戶請求的有關信息,但在JSP中很少直接用到它。它是HttpServletResponse類的實例。
    3.session對象
    session對象指的是客戶端與服務器的一次會話,從客戶連到服務器的一個WebApplication開始,直到客戶端與服務器斷開連接為止。它是HttpSession類的實例.
    4.out對象
    out對象是JspWriter類的實例,是向客戶端輸出內容常用的對象
    5.page對象
    page對象就是指向當前JSP頁面本身,有點象類中的this指針,它是java.lang.Object類的實例
    6.application對象
    application對象實現了用戶間數據的共享,可存放全局變量。它開始于服務器的啟動,直到服務器的關閉,在此期間,此對象將一直存在;這樣在用戶的前后連接或不同用戶之間的連接中,可以對此對象的同一屬性進行操作;在任何地方對此對象屬性的操作,都將影響到其他用戶對此的訪問。服務器的啟動和關閉決定了application對象的生命。它是ServletContext類的實例。
    7.exception對象
    exception對象是一個例外對象,當一個頁面在運行過程中發生了例外,就產生這個對象。如果一個JSP頁面要應用此對象,就必須把isErrorPage設為true,否則無法編譯。他實際上是java.lang.Throwable的對象
    8.pageContext對象
    pageContext對象提供了對JSP頁面內所有的對象及名字空間的訪問,也就是說他可以訪問到本頁所在的SESSION,也可以取本頁面所在的application的某一屬性值,他相當于頁面中所有功能的集大成者,它的本 類名也叫pageContext。
    9.config對象
    config對象是在一個Servlet初始化時,JSP引擎向它傳遞信息用的,此信息包括Servlet初始化時所要用到的參數(通過屬性名和屬性值構成)以及服務器的有關信息(通過傳遞一個ServletContext對象)

    知識點30:

    Object 類中方法及說明如下:

    registerNatives() //私有方法

    getClass() //返回此 Object 的運行類。
    hashCode() //用于獲取對象的哈希值。
    equals(Object obj) //用于確認兩個對象是否“相同”。
    clone() //創建并返回此對象的一個副本。
    toString() //返回該對象的字符串表示。
    notify() //喚醒在此對象監視器上等待的單個線程。
    notifyAll() //喚醒在此對象監視器上等待的所有線程。
    wait(long timeout) //在其他線程調用此對象的 notify() 方法或 notifyAll() 方法,或 者超過指定的時間量前,導致當前線程等待。
    wait(long timeout, int nanos) //在其他線程調用此對象的 notify() 方法或 notifyAll() 方法,或者其他某個線程中斷當前線程,或者已超過某個實際時間量前,導致當前線程等待。
    wait() //用于讓當前線程失去操作權限,當前線程進入等待序列
    finalize() //當垃圾回收器確定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法。

    知識點31:

    • 這道題目想考察的知識點是MySQL組合索引(復合索引)的最左優先原則。最左優先就是說組合索引的第一個字段必須出現在查詢組句中,這個索引才會被用到。只要組合索引最左邊第一個字段出現在Where中,那么不管后面的字段出現與否或者出現順序如何,MySQL引擎都會自動調用索引來優化查詢效率。
    • 根據最左匹配原則可以知道B-Tree建立索引的過程,比如假設有一個3列索引(col1,col2,col3),那么MySQL只會會建立三個索引(col1),(col1,col2),(col1,col2,col3)。
    • 所以題目會創建三個索引(plat_order_id)、(plat_order_id與plat_game_id的組合索引)、(plat_order_id、plat_game_id與plat_id的組合索引)。根據最左匹配原則,where語句必須要有plat_order_id才能調用索引(如果沒有plat_order_id字段那么一個索引也調用不到),如果同時出現plat_order_id與plat_game_id則會調用兩者的組合索引,如果同時出現三者則調用三者的組合索引。
    • 題目問有哪些sql能使用到索引,個人認為只要Where后出現了plat_order_id字段的SQL語句都會調用到索引,只不過是所調用的索引不同而已,所以選BCDE。如果題目說清楚是調用到三個字段的復合索引,那答案才是BD。

    知識點32:

    補充Java內存管理知識:

    1. 內存分配策略

    按照編譯原理的觀點,程序運行時的內存分配有三種策略,分別是靜態的,棧式的,和堆式的。

    靜態存儲分配是指在編譯時就能確定每個數據目標在運行時刻的存儲空間需求,因而在編譯時就可以給他們分配固定的內存空間。這種分配策略要求程序代碼中不允許有可變數據結構(比如可變數組)的存在,也不允許有嵌套或者遞歸的結構出現,因為它們都會導致編譯程序無法計算準確的存儲空間需求。

    棧式存儲分配也可稱為動態存儲分配,是由一個類似于堆棧的運行棧來實現的。和靜態存儲分配相反,在棧式存儲方案中,程序對數據區的需求在編譯時是完全未知的,只有到運行的時候才能夠知道,但是規定在運行中進入一個程序模塊時,必須知道該程序模塊所需的數據區大小才能夠為其分配內存。和我們在數據結構所熟知的棧一樣,棧式存儲分配按照先進后出的原則進行分配。

    靜態存儲分配要求在編譯時能知道所有變量的存儲要求,棧式存儲分配要求在過程的入口處必須知道所有的存儲要求,而堆式存儲分配則專門負責在編譯時或運行時模塊入口處都無法確定存儲要求的數據結構的內存分配,比如可變長度串和對象實例。堆由大片的可利用塊或空閑塊組成,堆中的內存可以按照任意順序分配和釋放。

    2. JVM中的堆和棧

    JVM是基于堆棧的虛擬機。JVM為每個新創建的線程都分配一個堆棧,也就是說,對于一個Java程序來說,它的運行就是通過對堆棧的操作來完成的。堆棧以幀為單位保存線程的狀態。JVM對堆棧只進行兩種操作:以幀為單位的壓棧和出棧操作。

    java把內存分兩種:一種是棧內存,另一種是堆內存

    棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。

    棧(stack):是一個先進后出的數據結構,通常用于保存方法(函數)中的參數,局部變量。

    堆(heap):是一個可動態申請的內存空間(其記錄空閑內存空間的鏈表由操作系統維護),是一個運行時數據區,C中的malloc語句所產生的內存空間就在堆中。

    3. 堆和棧優缺點比較

    棧的優勢是,存取速度比堆要快,僅次于直接位于CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。另外,棧數據可以共享,詳見第3點。

    堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由于要在運行時動態分配內存,存取速度較慢。

    4. Java中的數據類型有兩種

    一種是基本類型

    共有8種,即int, short, long, byte, float, double, boolean, char(注意,并沒有string的基本類型)。

    這種類型的定義是通過諸如int a = 3; long b = 255L;的形式來定義的,稱為自動變量。值得注意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這里并沒有類的存在。如int a = 3; 這里的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,由于大小可知,生存期可知(這些字面值固定定義在某個程序塊里面,程序塊退出后,字段值就消失了),出于追求速度的原因,就存在于棧中。

    另外,**棧有一個很重要的特殊性,就是存在棧中的數據可以共享。**假設我們同時定義:

    int a = 3;
    int b = 3;
    編譯器先處理int a = 3;首先它會在棧中創建一個變量為a的引用,然后查找有沒有字面值為3的地址,沒找到,就開辟一個存放3這個字面值的地址,然后將a指向3的地址。接著處理int b = 3;在創建完b的引用變量后,由于在棧中已經有3這個字面值,便將b直接指向3的地址。這樣,就出現了a與b同時均指向3的情況。

    特別注意的是,這種字面值的引用與類對象的引用不同。假定兩個類對象的引用同時指向一個對象,如果一個對象引用變量修改了這個對象的內部狀態,那么另一個對象引用變量也即刻反映出這個變化。相反,通過字面值的引用來修改其值,不會導致另一個指向此字面值的引用的值也跟著改變的情況。如上例,我們定義完a與b的值后,再令a=4;那么,b不會等于4,還是等于3。在編譯器內部,遇到a=4;時,它就會重新搜索棧中是否有4的字面值,如果沒有,重新開辟地址存放4的值;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。

    另一種是包裝類數據

    如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據全部存在于堆中,Java用new()語句來顯示地告訴編譯器,在運行時才根據需要動態創建,因此比較靈活,但缺點是要占用更多的時間。

    String是一個特殊的包裝類數據。即可以用String str = new String(“abc”);的形式來創建,也可以用String str = “abc”;的形式來創建(作為對比,在JDK 5.0之前,你從未見過Integer i = 3;的表達式,因為類與字面值是不能通用的,除了String。而在JDK 5.0中,這種表達式是可以的!因為編譯器在后臺進行Integer i = new Integer(3)的轉換)。前者是規范的類的創建過程,即在Java中,一切都是對象,而對象是類的實例,全部通過new()的形式來創建。Java中的有些類,如DateFormat類,可以通過該類的getInstance()方法來返回一個新創建的類,似乎違反了此原則。其實不然。該類運用了單例模式來返回類的實例,只不過這個實例是在該類內部通過new()來創建的,而getInstance()向外部隱藏了此細節。那為什么在String str = “abc”;中,并沒有通過new()來創建實例,是不是違反了上述原則?其實沒有。

    5.String在內存中的存放

    String是一個特殊的包裝類數據,可以用用以下兩種方式創建:

    String str = new String(“abc”);第一種創建方式是用new()來新建對象的,它會存放于堆中。每調用一次就會創建一個新的對象。

    String str = “abc”; 第二種創建方式先在棧中創建一個對String類的對象引用變量str,然后在棧中查找有沒有存放值為”abc”的地址,如果沒有,則開辟一個存放字面值為”abc”的地址,接著創建一個新的String類的對象o,并將o的字符串值指向這個地址,而且在棧中這個地址旁邊記下這個引用的對象o。如果已經有了值為”abc”的地址,則查找對象o,并返回o的地址,最后將str指向對象o的地址。

    值得注意的是,一般String類中字符串值都是直接存值的。但像String str = “abc”;這種場合下,其字符串值卻是保存了一個指向存在棧中數據的引用!

    6.數組在內存中的存放

    int x[] 或者int []x 時,在內存棧空間中創建一個數組引用,通過該數組名來引用數組。

    x = new int[5] 將在堆內存中分配5個保存int型數據的空間,堆內存的首地址放到棧內存中,每個數組元素被初始化為0。

    7.static變量在內存中的存放

    用 static的修飾的變量和方法,實際上是指定了這些變量和方法在內存中的“固定位置”-static storage。既然要有“固定位置”那么他們的 “大小”似乎就是固定的了,有了固定位置和固定大小的特征了,在棧中或堆中開辟空間那就是非常的方便了。如果靜態的變量或方法在不出其作用域的情況下,其引用句柄是不會發生改變的。

    8. java中變量在內存中的分配

    1、類變量(static修飾的變量)

    在程序加載時系統就為它在堆中開辟了內存,堆中的內存地址存放于棧以便于高速訪問。靜態變量的生命周期一直持續到整個”系統”關閉

    2、實例變量

    當你使用java關鍵字new的時候,系統在堆中開辟并不一定是連續的空間分配給變量(比如說類實例),然后根據零散的堆內存地址,通過哈希算法換算為一長串數字以表征這個變量在堆中的”物理位置”。 實例變量的生命周期–當實例變量的引用丟失后,將被GC(垃圾回收器)列入可回收“名單”中,但并不是馬上就釋放堆中內存

    3、局部變量

    局部變量,由聲明在某方法,或某代碼段里(比如for循環),執行到它的時候在棧中開辟內存,當局部變量一但脫離作用域,內存立即釋放

    知識點33:

    兩個最基本的java回收算法:復制算法和標記清理算法

    復制算法:兩個區域A和B,初始對象在A,繼續存活的對象被轉移到B。此為新生代最常用的算法

    標記清理:一塊區域,標記可達對象(可達性分析),然后回收不可達對象,會出現碎片,那么引出

    標記-整理算法:多了碎片整理,整理出更大的內存放更大的對象

    兩個概念:新生代和年老代

    新生代:初始對象,生命周期短的

    永久代:長時間存在的對象

    整個java的垃圾回收是新生代和年老代的協作,這種叫做分代回收。

    P.S:Serial New收集器是針對新生代的收集器,采用的是復制算法

    Parallel New(并行)收集器,新生代采用復制算法,老年代采用標記整理

    Parallel Scavenge(并行)收集器,針對新生代,采用復制收集算法

    Serial Old(串行)收集器,新生代采用復制,老年代采用標記整理

    Parallel Old(并行)收集器,針對老年代,標記整理

    CMS收集器,基于標記清理

    G1收集器:整體上是基于標記 整理 ,局部采用復制

    綜上:新生代基本采用復制算法,老年代采用標記整理算法。cms采用標記清理。

    知識點34:

    Servlet的生命周期

    init():僅執行一次,負責在裝載Servlet時初始化Servlet對象

    service() :核心方法,一般HttpServlet中會有get,post兩種處理方式。在調用doGet和doPost方法時會構造servletRequest和servletResponse請求和響應對象作為參數。

    destory():在停止并且卸載Servlet時執行,負責釋放資源

    初始化階段:Servlet啟動,會讀取配置文件中的信息,構造指定的Servlet對象,創建ServletConfig對象,將ServletConfig作為參數來調用init()方法。所以選ACD。B是在調用service方法時才構造的

    知識點35:

    結構型模式是描述如何將類對象結合在一起,形成一個更大的結構,結構模式描述兩種不同的東西:類與類的實例。故可以分為類結構模式和對象結構模式。

    在GoF設計模式中,結構型模式有:

    1.適配器模式 Adapter

    適配器模式是將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由于接口不兼容 而不能一起工作的那些類可以一起工作。

    兩個成熟的類需要通信,但是接口不同,由于開閉原則,我們不能去修改這兩個類的接口,所以就需要一個適配器來完成銜接過程。

    2.橋接模式 Bridge

    橋接模式將抽象部分與它的實現部分分離,是它們都可以獨立地變化。它很好的支持了開閉原則和組合鋸和復用原則。實現系統可能有多角度分類,每一種分類都有可能變化,那么就把這些多角度分離出來讓他們獨立變化,減少他們之間的耦合。

    3.組合模式 Composite

    組合模式將對象組合成樹形結構以表示部分-整體的層次結構,組合模式使得用戶對單個對象和組合對象的使用具有一致性。

    4.裝飾模式 Decorator

    裝飾模式動態地給一個對象添加一些額外的職責,就增加功能來說,它比生成子類更靈活。也可以這樣說,裝飾模式把復雜類中的核心職責和裝飾功能區分開了,這樣既簡化了復雜類,有去除了相關類中重復的裝飾邏輯。 裝飾模式沒有通過繼承原有類來擴展功能,但卻達到了一樣的目的,而且比繼承更加靈活,所以可以說裝飾模式是繼承關系的一種替代方案。

    5.外觀模式 Facade

    外觀模式為子系統中的一組接口提供了同意的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

    外觀模式中,客戶對各個具體的子系統是不了解的,所以對這些子系統進行了封裝,對外只提供了用戶所明白的單一而簡單的接口,用戶直接使用這個接口就可以完成操作,而不用去理睬具體的過程,而且子系統的變化不會影響到用戶,這樣就做到了信息隱蔽。

    6.享元模式 Flyweight

    享元模式為運用共享技術有效的支持大量細粒度的對象。因為它可以通過共享大幅度地減少單個實例的數目,避免了大量非常相似類的開銷。.

    ? 享元模式是一個類別的多個對象共享這個類別的一個對象,而不是各自再實例化各自的對象。這樣就達到了節省內存的目的。

    總結

    以上是生活随笔為你收集整理的Java常问面试题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。