Java面试题及答案整理
特別說明
感謝原文整理,本文主要是解答了面試問題,大部分面試問題來自關注我學java 文章整理,偶有改動。戳此查看面試題整理原文
更新中。。。目前只是部分答案,包括Java基礎、排序算法、數據庫、Spring部分
1. Java 篇
(1). Java基礎知識
? java中==和equals和hashCode的區別
"=="是運算符:
用來比較兩個值、兩個對象的內存地址是否相等;
“equals()”:
equals是Object類的方法,默認情況下比較兩個對象是否是同一個對象,內部實現是通過“==”來實現的。
如果想比較兩個對象的其他內容,則可以通過重寫equals方法,
例如:String類就重寫了equals方法,改成了對象的內容是否相等。
下面是String類中的equals()方法:
“hashCode()”:
hashCode也是Object類里面的方法,返回值是一個對象的哈希碼,同一個對象哈希碼一定相等,但不同對象哈希碼也有可能相等。
如果兩個對象通過equals方法比較相等,那么他的hashCode一定相等;
如果兩個對象通過equals方法比較不相等,那么他的hashCode有可能相等;
? int與integer的區別
1.Integer是int的包裝類,int則是java的一種基本的數據類型;
Int是Java八種基本數據類型之一,一般大小為4字節32位,取值范圍為2-31~231-1 。兩個Int類型變量用“==”比較的是內容的大小。
例如:int a = 100;int b = 100;a == b為True。
Integer是對Int類型的封裝,它是一個對象,可以通過new來常見Integer對象。但是對象通過“==”比較的是對象內存地址。
例如:Integer a = new Integer(100);Integer b = new Integer(100);a == b為False
2.Integer變量必須實例化之后才能使用,而int變量不需要實例化;
3.Integer實際是對象的引用,當new一個Integer時,實際上生成一個指針指向對象,而int則直接存儲數值;
由此可以引出一個問題:使用new和不使用的差別,是否相等呢?
??4.Integer的默認值是null,而int的默認值是0。
下面是Integer的valueOf方法的一小段源碼,更多的大家自行查看: public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}? 抽象類的意義
? 抽象類是它的所有子類的公共屬性的集合,是包含一個或多個抽象方法的類。抽象類可以看作是對類的進一步抽象。在面向對象領域,抽象類主要用來進行類型隱藏。使我們能在一個更高、更抽象的級別上考慮問題,從而簡化了問題的復雜性。抽象類進一步描述了多個具體類的共同特征和行為。使用抽象類可以更好地利用這些共同屬性和操作,避免代碼的重復編寫,從而減少出錯的幾率,提高程序的開發效率。
? 接口和抽象類的區別
?1.內部方法:接口內部全是抽象方法,默認都是public abstract修飾,且沒有方法體,抽象度更高,抽象類的方法可以是具體的非抽象方法,也可是抽象的,且抽象方法有方法體。
?2.內部變量:接口內部的變量都是默認被public static final修飾(一般不在接口內定義變量),也就是說接口里的變量都是不可改變的常量。而抽象類中的變量可以是正常的定義方式。
?3.繼承和實現:接口可以被類實現,且一個類可以實現多個接口,一個類只能繼承一個抽象類。重點類在實現接口時必須實現其中所有的接口中的方法。繼承抽象類時必須實現其內部的所有抽象方法(抽象方法沒有方法體)或者重寫抽象方法,那么該繼承類也將是抽象類(含有抽象方法)。
?4.接口可以實現多繼承,但是抽象類不能。
? 能否創建一個包含可變對象的不可變對象?
可以:不要共享可變對象的引用就可以了,如果需要變化時,就返回原對象的一個拷貝,最常見的例子就是對象中包含一個日期對象的引用
? 談談對java多態的理解
Java的多態體現在一下幾個方面:
?繼承:通過繼承實現多態(典型的抽象類)
?實現接口:通過實現接口實現多態
?重寫:子類繼承父類時,可以對父類的方法進行重寫,將原有的方法改變成符合自己子類需要的樣子。需要注意的是重寫方法的時候需要注意子類的方法訪問修飾符范圍不能小于父類方法。例如父類使用protected,那么子類可以使用protected或者public,而不能使用private。
?重載:重載發生在同類中,指的是兩個名字相同的方法,他們必須包含不同的參數數量或者類型,即兩個同名方法必須擁有不同的參數注入。因為只有這樣,程序執行的時候虛擬機才能自動匹配使用相應的方法。重點:返回值不能作為重載的標志,也就是說兩個方法如果僅僅只是返回類型不同,是不行的。
?虛函數:Java 中其實沒有虛函數的概念,它的普通函數就相當于 C++ 的虛函數,動態綁定是Java的默認行為。如果 Java 中不希望某個函數具有虛函數特性,可以加上 final 關鍵字變成非虛函數。
? String、StringBuffer、StringBuilder區別
String:首先觀察源代碼,String是被final修飾的類,那么就以為著:String的定義是必須要賦值的且是不可改變的。我們常常進行的String變動,都是進行創建了新的String。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {...}StringBuffer:通過源碼可以發現,他也是被final修飾的,但是它是繼承自AbstractStringBuilder類,然而AbstractStringBuilder 類由實現了Appendable接口,通過append方法可以實現字符串操作也不會產生無用的對象。不會像String一樣每次操作都產生無用對象。重點:在源碼中,StringBuffer的所有方法都被synchronize修飾,也就是說是線程安全的。
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{...}abstract class AbstractStringBuilder implements Appendable, CharSequence {...}StringBuilder:對比StringBuffer分析,可以發現,兩者都十分相近,不過StringBuilder的方法沒有被synchronize修飾,也就是說StringBuilder并非線程安全的,但是同樣的優勢就體現出來了,StringBuilder在效率上將會比StringBuffer高很多。
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{...}? 泛型中extends和super的區別
在泛型中,常用的extends 和super的用法其實是和Java中的其他用法是差不多的 <? extends T> ?包含T和T的子類 <? super T>?可以包含T和T的父類? 進程和線程的區別
進程是計算機分配資源的最小單位,線程是計算機CPU執行的最小單位。進程之間很少進行交流,但是線程之間的通信是比較常見的。對于線程而言,既有自己獨有的內存區域,也有共享進程的資源。
? final,finally,finalize的區別
final:可以修飾變量,對象,方法,類,但是變量不可再更改,對象不能在改變,方法不能在重寫(可以被繼承和重載),類不能再被繼承。修飾接口無意義,所以不能修飾接口。 finally:通常是和try以及catch語句結合一起使用的,用作異常處理,finally的語句在try結構中一般是必須執行的,通常用來釋放鎖等必要操作,以防止死鎖的情況發生。 finalize:通常是指析構方法,是用來析構對象使用的,通常使用在垃圾回收部分,不過Java的垃圾回收是自動的,所以這個方法也是有虛擬機完成調用的,不需要程序員進行人為調用。? 序列化的方式
要實現序列化,首先需要類是實現了serializable接口,就可以被序列化。 序列化是為了將類狀態保留下來,持久化到磁盤或者是遠程調用。因為一個類的聲明周期通常不會大于JVM的生命周期,所以為了使得類狀態可以在JVM停止運行之后,在下一次被使用時依然可用,所以需要使用到序列化。 值得注意的是,序列化只會保存對象的狀態,即其成員變量,其余的靜態變量等不會被保存。如果需要指定某一變量不被序列化(如密碼和賬戶名),可以使用關鍵字transient修飾該變量即可。? string 轉換成 integer的方式及原理
觀察如下源碼可以發現:先將String轉換char數組,首先判斷第一個字符是不是負號,如果是就表明為負數,否則轉換為數字,然后依次判斷后面的每個字符。 //s是輸入的字符串,radix是輸入字符串的進制,如果radix=10,表示十進制,默認是10進制,等于2就是二進制public static int parseInt(String s, int radix)throws NumberFormatException{int result = 0;//返回結果boolean negative = false;//判斷是否為負數int i = 0, len = s.length();int limit = -Integer.MAX_VALUE;int multmin;int digit;if (len > 0) {char firstChar = s.charAt(0);if (firstChar < '0') { // Possible leading "+" or "-"if (firstChar == '-') {negative = true;limit = Integer.MIN_VALUE;} else if (firstChar != '+')throw NumberFormatException.forInputString(s);if (len == 1) // Cannot have lone "+" or "-"throw NumberFormatException.forInputString(s);i++;}multmin = limit / radix;while (i < len) {// Accumulating negatively avoids surprises near MAX_VALUEdigit = Character.digit(s.charAt(i++),radix);if (digit < 0) {throw NumberFormatException.forInputString(s);}if (result < multmin) {throw NumberFormatException.forInputString(s);}result *= radix;if (result < limit + digit) {throw NumberFormatException.forInputString(s);}result -= digit;}} else {throw NumberFormatException.forInputString(s);}return negative ? result : -result;}? 靜態屬性和靜態方法是否可以被繼承?是否可以被重寫?以及原因?
靜態屬性可以被繼承。 靜態方法也可以被繼承,不可以被重寫但是可以隱蔽(也就是子類在重寫方法后,父類方法將不可見,也就是不能被使用。無法形成多態),但是可以被重載。? 成員內部類、靜態內部類、局部內部類和匿名內部類的理解,以及項目中的應用
成員內部類:成員內部類是依附外部類而存在的,也就是說,如果要創建成員內部類的對象,前提是必須存在一個外部類的對象當成員內部類擁有和外部類同名的成員變量或者方法時,會發生隱藏現象,即默認情況下訪問的是成員內部類的成員。如果要訪問外部類的同名成員,需要以下面的形式進行訪問。外部類中如果要訪問成員內部類的成員,必須先創建一個成員內部類的對象,再通過指向這個對象的引用來訪問。內部類可以擁有private訪問權限、protected訪問權限、public訪問權限及包訪問權限
Inner inner = new Inner();//在testx類里面使用 testx.Inner inner = new testx().new Inner();;//在外部使用 外部類.this.成員變量 外部類.this.成員方法 靜態內部類靜態內部類也是定義在另一個類里面的類,只不過在類的前面多了一個關鍵字static。靜態內部類是不需要依賴于外部類的,這點和類的靜態成員屬性有點類似,并且它不能使用外部類的非static成員變量或者方法,這點很好理解,因為在沒有外部類的對象的情況下,可以創建靜態內部類的對象,如果允許訪問外部類的非static成員就會產生矛盾,因為外部類的非static成員必須依附于具體的對象。
Inner inner = new Inner();//在testx類里面使用 testx.Inner inner = new testx().Inner();;//在外部使用 局部內部類:是寫在方法體內的類,這種類的作用域僅限于方法內,相當于是局部變量局部內部類就像是方法里面的一個局部變量一樣,是不能有public、protected、private以及static修飾符的
匿名內部類是以超類或者接口的名字進行使用的,最常見的例如新建線程,或者事件監聽匿名內部類是唯一一種沒有構造器的類。正因為其沒有構造器,所以匿名內部類的使用范圍非常有限,大部分匿名內部類用于接口回調。匿名內部類在編譯的時候由系統自動起名為Outter$1.class。
new Thread(new Runnable() {@Overridepublic void run() {//代碼執行體}})? 講一下常見編碼方式?
常見的字節碼編碼方式有GBK,UTF-8,ASCII,GB2312,Unicode等
ASCII編碼:采用的編碼方式是用一個字節的低七位進行編碼,是最早的一種編碼方式之一,里面包含一些可以顯示的符號(數字,字母,某些標點)和不可顯示的符號(一些特殊符號),不包括中文,能表示的字符十分有限,后來繼而產生了擴展的ASCII碼。
GB2312編碼:采用雙字節編碼,第一個字節稱為“高位字節”(也稱“區字節)”,第二個字節稱為“低位字節”(也稱“位字節”)。兼容ASCII。
GBK編碼:兼容GBK編碼,英文字母采用單字節編碼,中文部分采用雙字節編碼。同時完全兼容ASCII。
Unicode編碼:Unicode通常用兩個字節表示一個字符,原有的英文編碼從單字節變成雙字節,只需要把高字節全部填為0就可以。
UTF-8編碼:8位元編碼,針對Unicode的一種可變長度字符編碼。它可以用來表示Unicode標準中的任何字符,而且其編碼中的第一個字節仍與ASCII相容,使得原來處理ASCII字符的軟件無須或只進行少部份修改后,便可繼續使用。因此,它逐漸成為電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼。理論編碼長度可以達到6個字節,但是實際上
UTF-8編碼:大部分字符都使用兩個字節表示,但是不兼容ASCII。
UTF-32編碼:每個字符都是用4個字節的定長碼,就使用空間來講,效率較低。
? 如何格式化日期?
? Java的異常體系
? 什么是異常鏈
? throw和throws的區別
? 反射的原理,反射創建類實例的三種方式是什么。
? java當中的四種引用
強軟弱虛
? 深拷貝和淺拷貝的區別是什么?
淺拷貝將對象復制一份,但是不會拷貝對象中的引用
而深拷貝就不同,是直接將對象和所有的引用都拷貝一份
? 什么是編譯器常量?使用它有什么風險?
公共靜態不可變(public static final )變量也就是我們所說的編譯器常量,這里的 public 可選的。實際上這些變量在編譯時會被替換掉,因為編譯器知道這些變量的值,并且知道這些變量在運行時不能改變。
這種方式存在的一個問題是你使用了一個內部的或第三方庫中的公有編譯時常量,但是這個值后面被其他人改變了,但是你的客戶端仍然在使用老的值,甚至你已經部署了一個新的jar。為了避免這種情況,當你在更新依賴 JAR 文件時,確保重新編譯你的程序。
? 你對String對象的intern()熟悉么?
intern()方法的設計之初就是為了解決String占用空間的問題,所以的這個方法實際上是在new一個String的時候,在常量池上新建一個字符串常量。但是值得注意的是,new String(“a”)+new String(“b”),常量池會形成一個“ab”的常量。當你再使用“ab”字符串時,就不會重新new,而是直接在常量池提取。從而減少內存的開銷。這里有篇很詳細的博文,大家自行驗證:戳這里去看別人家的文章
String s3 = new String("1") + new String("1");s3.intern();String s4 = new String("11");String s5 = "11";System.out.println(s3 == s4);//falseSystem.out.println(s3 == s5);//true? a=a+b與a+=b有什么區別嗎?
在兩個變量的數據類型一樣時:a+=b 和a=a+b 是沒有區別的。
但是當兩個變量的數據類型不同時,就需要考慮一下數據類型自動轉換的問題了。
也就是涉及到精度了
? 靜態代理和動態代理的區別,什么場景使用?
靜態:
動態:
? Java中實現多態的機制是什么?
? 如何將一個Java對象序列化到文件里?
? 說說你對Java反射的理解
? 說說你對Java注解的理解
? 說說你對依賴注入的理解
? 說一下泛型原理,并舉例說明
? String為什么要設計成不可變的?
? Object類的equal和hashCode方法重寫,為什么?
(2).多線程
? 開啟線程的三種方式?
- 繼承Thread類(重寫run方法)
- 實現Runnable接口(重寫run方法)
- 實現Callable接口(重寫call方法)(有返回值)(可以使用future類進行獲取返回值)
? 說說進程,線程,協程之間的區別
-
進程,是計算機系統資源分配和調度的一個最小單位。一般進程之間通信的方式主要有:管道、流管道、有名管道。后兩者是全雙工通信,前面的管道則是半雙工通信。除此之外,還有信號量、信號、消息列隊、共享內容、套接字等一些列通信方式。
-
線程可以分為兩類,用戶級線程和內核級線程。用戶級線程都是有應用程序完成,內核意識不到存在,應用啟動后,系統會分配一個進程號給進程,以及對應的內存空間等資源。用戶級線程的好處是比較高效,不需要進入內核空間,但是并發性能不高。內核級線程則是所有的工作都是內核完成,應用程序沒有進行線程管理,只能調用內核線程的接口。內核級可以更好的分配到不同的CPU,并發性更好。在現代操作系統中,往往使用組合方式實現多線程,即線程創建完全在用戶空間中完成,并且一個應用程序中的多個用戶級線程被映射到一些內核級線程上,相當于是一種折中方案。
-
協程,是一種比線程更加輕量級的存在,協程不是被操作系統內核所管理,而完全是由程序所控制(也就是在用戶態執行)。這樣帶來的好處就是性能得到了很大的提升,不會像線程切換那樣消耗資源。
-
子程序,或者稱為函數,在所有語言中都是層級調用,比如A調用B,B在執行過程中又調用了C,C執行完畢返回,B執行完畢返回,最后是A執行完畢。所以子程序調用是通過棧實現的,一個線程就是執行一個子程序。子程序調用總是一個入口,一次返回,調用順序是明確的。而協程的調用和子程序不同。
? 線程之間是如何通信的?
主要的通信方式是內存共享
另外就是一些方法,如wait、notify、notifyall等
? 什么是Daemon線程?它有什么意義?
- daemon線程又叫守護線程,他不同于其他線程,JVM的生命周期不會以他為參考,通常JVM的生命會和非守護線程的生命周期一起結束,也就是說JVM在執行完最后一個非守護線程后就停止,并不會因為還有守護線程而繼續。例如垃圾回收線程,JVM一旦啟動,垃圾回收線程就運行,直到JVM停止。所以守護線程提供的一般是公共服務。可以通過setDaemon(true)將一個線程設置為守護線程。
? 為什么要有線程,而不是僅僅用進程?
- 進程通常只能同時做一件事,那么對于多個任務并發執行將成為不可能。然而進程里面容納多個線程以后,每個線程可以執行一個任務,實現了多個任務的同時執行。另外就是線程的設計可以增加CPU的利用率。
? 什么是可重入鎖(ReentrantLock)?
- 可重入鎖也叫遞歸鎖,指外層函數在獲取鎖以后,內層函數依然可以獲取鎖進行執行。在Java中synchronize和ReentrantLock都是可重入鎖。
? 什么是線程組,為什么在Java中不推薦使用?
線程組ThreadGroup對象中的stop,resume,suspend會導致安全問題,主要是死鎖問題,已經被官方廢棄,多以價值已經大不如以前。 線程組ThreadGroup不是線程安全的,在使用過程中不能及時獲取安全的信息。 線程不安全? 樂觀鎖和悲觀鎖的理解及如何實現,有哪些實現方式?
樂觀鎖CAS
悲觀鎖
? Java中用到的線程調度算法是什么?
Java使用的是搶占式調度:因為搶占式調度不會因為某一個線程的執行受阻而終止整個程序,而是會執行其他線程。
? 同步方法和同步塊,哪個是更好的選擇?
同步塊是更好的選擇,因為它不會鎖住整個對象(當然你也可以讓它鎖住整個對
象)。同步方法會鎖住整個對象,哪怕這個類中有多個不相關聯的同步塊,這通
常會導致他們停止執行并需要等待獲得這個對象上的鎖。
同步塊更要符合開放調用的原則,只在需要鎖住的代碼塊鎖住相應的對象,這樣
從側面來說也可以避免死鎖。
? run()和start()方法區別
- run和start方法的最本質區別是:run是執行方法體,不過不是啟動新的線程去執行的,是在當前線程執行的而且是當前線程獲得CPU執行時間片段后立即執行的,start就不一樣了,是啟動了一條新的線程運行了run方法,不過start的方法是提交了一個新線程,并且使得新線程處于就緒狀態,并非立即執行,獲得時間片段后才會執行run方法體。
? 如何控制某個方法允許并發訪問線程的個數?
?AQS 重入鎖 讀寫鎖 countdownlatch 柵欄(cyclicBarrier) 信號量(semaphore)
- semaphore:信號量,通過acquire獲取一個許可,release釋放一個許可
- countdownlatch:線程計數器:利用countdown實現標記,使用await方法等待countdown的實執行。
- 線程池
- CyclicBarrier:最重要的就是await方法,意思是讓一組線程在等待某個狀態后才開始同時執行。
? 在Java中wait和sleep方法的不同;
wait方法是基于對象監視器的方法,是Object的方法,會使得線程進入阻塞狀態,重要的是會放棄已獲得的資源鎖。等待其他線程調用了對象的notify或者notifyall方法后才會再次進入就緒狀態等待執行。
sleep方法是基于線程的方法,是Thread方法。使用sleep方法后,線程不會放棄已獲得的資源,而且在一定睡眠時間結束后,會自動回復到執行狀態。
? Thread類中的yield方法有什么作用?
? 什么是不可變對象,它對寫并發應用有什么幫助?
不可變對象(Immutable Objects)即對象一旦被創建它的狀態(對象的數據,也即
對象屬性值)就不能改變,反之即為可變對象(Mutable Objects)。
不可變對象的類即為不可變類(Immutable Class)。Java 平臺類庫中包含許多不可
變類,如 String、基本類型的包裝類、BigInteger 和 BigDecimal 等。
不可變對象天生是線程安全的。它們的常量(域)是在構造函數中創建的。既然
它們的狀態無法修改,這些常量永遠不會變。
不可變對象永遠是線程安全的。
只有滿足如下狀態,一個對象才是不可變的;
它的狀態不能在創建后再被修改;
所有域都是 final 類型;并且,
它被正確創建(創建期間沒有發生 this 引用的逸出)。
? 談談wait/notify關鍵字的理解
? 為什么wait, notify 和 notifyAll這些方法不在thread類里面?
這三個方法是基于對象監視器的,所有的對象都是Object的子類
? 什么導致線程阻塞?
wait方法sleep方法
獲取對象鎖但是被其他線程占有了,進入阻塞狀態
IO請求
? 講一下java中的同步的方法
? 談談對Synchronized關鍵字,類鎖,方法鎖,重入鎖的理解
? static synchronized 方法的多線程訪問和作用
? 同一個類里面兩個synchronized方法,兩個線程同時訪問的問題
簡言之:不行。synchronize修飾方法時,加鎖是對于對象的,所以會直接鎖定一個對象,那么其他線程只能進行等待。
多個線程訪問同一個類的synchronized方法時, 都是串行執行的 ! 就算有多個cpu也不例外 ! synchronized方法使用了類java的內置鎖, 即鎖住的是方法所屬對象本身. 同一個鎖某個時刻只能被一個執行線程所獲取, 因此其他線程都得等待鎖的釋放. 因此就算你有多余的cpu可以執行, 但是你沒有鎖, 所以你還是不能進入synchronized方法執行, CPU因此而空閑. 如果某個線程長期持有一個競爭激烈的鎖, 那么將導致其他線程都因等待所的釋放而被掛起, 從而導致CPU無法得到利用, 系統吞吐量低下. 因此要盡量避免某個線程對鎖的長期占有 !
? 你如何確保main()方法所在的線程是Java程序最后結束的線程?
棧先進后出:main棧幀先進
? 談談volatile關鍵字的作用
? 談談ThreadLocal關鍵字的作用
? 談談NIO的理解
? 什么是Callable和Future?
? ThreadLocal、synchronized 和volatile 關鍵字的區別
? synchronized與Lock的區別
? ReentrantLock 、synchronized和volatile比較
? 在Java中CycliBarriar和CountdownLatch有什么區別?
? CopyOnWriteArrayList可以用于什么應用場景?
? ReentrantLock的內部實現
? lock原理
? Java中Semaphore是什么?
? Java中invokeAndWait 和 invokeLater有什么區別?
? 多線程中的忙循環是什么?
? 怎么檢測一個線程是否擁有鎖?
? 死鎖的四個必要條件?
? 對象鎖和類鎖是否會互相影響?
? 什么是線程池,如何使用?
? Java線程池中submit() 和 execute()方法有什么區別?
? Java中interrupted 和 isInterruptedd方法的區別?
? 用Java實現阻塞隊列
? BlockingQueue介紹:
? 多線程有什么要注意的問題?
? 如何保證多線程讀寫文件的安全?
? 多線程斷點續傳原理
? 斷點續傳的實現
? 實現生產者消費者模式
? Java中的ReadWriteLock是什么?
? 用Java寫一個會導致死鎖的程序,你將怎么解決?
? SimpleDateFormat是線程安全的嗎?
? Java中的同步集合與并發集合有什么區別?
? Java中ConcurrentHashMap的并發度是什么?
? 什么是Java Timer類?如何創建一個有特定時間間隔的任務?
(3).集合
Collection 和Collections 的區別?
修改對象A的equals方法的簽名,那么使用HashMap存放這個對象實例的時候,會調用哪個equals方法?
List,Set,Map的區別
List和Map的實現方式以及存儲方式
HashMap的實現原理
HashMap如何put數據(從HashMap源碼角度講解)?
HashMap的擴容操作是怎么實現的?
HashMap在JDK1.7和JDK1.8中有哪些不同?
ConcurrentHashMap的實現原理
HashTable實現原理
ArrayMap和HashMap的對比
HashMap和HashTable的區別
HashMap與HashSet的區別
集合Set實現Hash怎么防止碰撞
數組和鏈表的區別
Array和ArrayList有何區別?什么時候更適合用Array
.EnumSet是什么?
Comparable和Comparator接口有何區別?
Java集合的快速失敗機制 “fail-fast”?
fail-fast 與 fail-safe 之間的區別?
BlockingQueue是什么?
Iterator類有什么作用
poll()方法和remove()方法區別?
JAVA8的ConcurrentHashMap為什么放棄了分段鎖,有什么問題嗎,如果你來設計,你如何設計。
(4).JVM
什么情況下會觸發類的初始化?
談談你對解析與分派的認識。
你知道哪些或者你們線上使?什么GC策略?它有什么優勢,適?于什么場景?
Java類加載器包括?種?它們之間的??關系是怎么樣的?雙親委派機制是什么意思?有什么好處?
如何?定義?個類加載器?你使?過哪些或者你在什么場景下需要?個?定義的類加載器嗎?
堆內存設置的參數是什么?
Perm Space中保存什么數據?會引起OutOfMemory嗎?
棧空間引發OOM的原因是什么?存儲的內容是什么?
一個線程占用多少空間?占據哪里的空間?可以無限new線程嗎?
java里每新起一個線程,jvm會向操作系統請求新起一個本地線程,此時操作系統會用空閑的內存空間來分配這個線程。所以java里線程并不會占用 jvm的內存空間,而是會占用操作系統空閑的內存空間 jdk1.4默認的單個線程是占用256k的內存 jdk1.5以后默認的單個線程是占用1M的內存 可以通過-Xss參數設定,一般默認就好 所以既然會消耗內存,當然不可以無限new啦做GC時,?個對象在內存各個Space中被移動的順序是什么?
你有沒有遇到過OutOfMemory問題?你是怎么來處理這個問題的?處理 過程中有哪些收獲?
可以先嘗試擴大內存,利用Xms等調整分配的內存,如果還是不行就考慮程序有錯,可以dump文件出來分析。 生成dump文件的命令: jmap -dump:format=b,file=20170307.dump 16048 file后面的是自定義的文件名,最后的數字是進程的pid 分析可以使用Java自帶的 jvisualvm工具進行分析,也可是第三方的例如jprofiler。StackOverflow異常有沒有遇到過??般你猜測會在什么情況下被觸發?如何指定?個線程的堆棧????般你們寫多少?
觸發Stackoverflow的條件是遞歸條件過深,沒有出口。-Xms 指定jvm堆的初始大小,默認為物理內存的1/64,最小為1M;可以指定單位,比如k、m,若不指定,則默認為字節。 -Xmx 指定jvm堆的最大值,默認為物理內存的1/4或者1G,最小為2M;單位與-Xms一致。 -Xmn 指定jvm堆中年輕代的大小 -Xss 設置單個線程棧的大小,一般默認為1M。內存模型以及分區,需要詳細到每個區放什么。
分派:靜態分派與動態分派。
虛擬機在運行時有哪些優化策略
請解釋StackOverflowError和OutOfMemeryError的區別?
.在JVM中,如何判斷一個對象是否死亡?
計數器方法 根的可達性判斷2.計算機網絡
從網絡加載一個10M的圖片,說下注意事項
OSI網絡體系結構與TCP/IP協議模型
TCP的3次握手和四次揮手
為什么TCP鏈接需要三次握手,兩次不可以么,為什么?
TCP協議如何來保證傳輸的可靠性
TCP與UDP的區別
TCP與UDP的有哪些應用
HTTP1.0與2.0的區別
HTTP報文結構
HTTP的長連接和短連接?
HTTP與HTTPS的區別以及如何實現安全性
如何驗證證書的合法性
Get與POST的區別
GET:請求指定的頁面信息,并返回實體主體。 POST:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。TCP的擁塞處理
TCP是如何進行流量控制
TCP和UDP分別對應的常見應用層協議
IP地址的分類
ABC類
有了唯一的Mac地址為啥還需要IP地址?
交換機、集線器與路由器有什么區別?
寶典戳戳戳
網橋的作用
寶典戳戳戳
ARP是地址解析協議,簡單語言解釋一下工作原理。
主機A的IP地址為192.168.1.1,MAC地址為0A-11-22-33-44-01; 主機B的IP地址為192.168.1.2,MAC地址為0A-11-22-33-44-02; 當主機A要與主機B通信時,地址解析協議可以將主機B的IP地址(192.168.1.2)解析成主機B的MAC地址,以下為工作流程: 第1步:根據主機A上的路由表內容,IP確定用于訪問主機B的轉發IP地址是192.168.1.2。然后A主機在自己的本地ARP緩存中檢查主機B的匹配MAC地址。 第2步:如果主機A在ARP緩存中沒有找到映射,它將詢問192.168.1.2的硬件地址,從而將ARP請求幀廣播到本地網絡上的所有主機。源主機A的IP地址和MAC地址都包括在ARP請求中。本地網絡上的每臺主機都接收到ARP請求并且檢查是否與自己的IP地址匹配。如果主機發現請求的IP地址與自己的IP地址不匹配,它將丟棄ARP請求。 第3步:主機B確定ARP請求中的IP地址與自己的IP地址匹配,則將主機A的IP地址和MAC地址映射添加到本地ARP緩存中。 第4步:主機B將包含其MAC地址的ARP回復消息直接發送回主機A。 第5步:當主機A收到從主機B發來的ARP回復消息時,會用主機B的IP和MAC地址映射更新ARP緩存。本機緩存是有生存期的,生存期結束后,將再次重復上面的過程。主機B的MAC地址一旦確定,主機A就能向主機B發送IP通信了。網絡接口卡(網卡)的功能?
1、數據的封裝與解封 發送時將上一層傳遞來的數據加上首部和尾部,成為以太網的幀。接收時將以太網的幀剝去首部和尾部,然后送交上一層 2、鏈路管理 主要是通過CSMA/CD(Carrier Sense Multiple Access with Collision Detection ,帶沖突檢測的載波監聽多路訪問)協議來實現 3、數據編碼與譯碼 即曼徹斯特編碼與譯碼。其中曼徹斯特碼,又稱數字雙向碼、分相碼或相位編碼(PE),是一種常用的的二元碼線路編碼方式之一,被物理層使用來編碼一個同步位流的時鐘和數據。在通信技術中,用來表示所要發送比特 流中的數據與定時信號所結合起來的代碼。 常用在以太網通信,列車總線控制,工業總線等領域。IO中同步與異步,阻塞與非阻塞區別
URI和URL的區別
GET請求中URL編碼的意義
常見狀態碼及原因短語
說說Session、Cookie 與 Application
如何避免瀏覽器緩存
什么是分塊傳送。
談談SQL 注入
DDos 攻擊
DDos攻擊有那些預防方法?
什么是XSS 攻擊
從輸入網址到獲得頁面的過程
3.數據結構與算法
(1)數據結構
鏈表(增刪查操作)
單向鏈表
雙向鏈表
隊列(增刪查操作)
普通隊列
優先隊友
樹
二叉樹(前序、中序、后序)
平衡樹(盡量會實現代碼)
堆
紅黑樹(了解性質、應用場景)
B樹(了解性質、應用場景)
圖
六脈神劍
深度優先搜索
廣度優先搜索
最短路徑
最小生成樹
Prim算法
Kruskal算法
拓撲
字符串
Knuth-Morris-Pratt算法
Boyer-Moore算法
(2)幾種算法思想
遞歸
通過重復將問題分解為同類的子問題而解決問題的方法遞推
貪心
枚舉
動態規劃
回溯法
銀行家算法
分治
將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。(3)必學十大排序算法
Java中的十種排序方式(代碼都是升序)
基于比較的排序:冒泡、選擇、插入、并歸、快速、希爾、堆排序
排序所發穩定性:如果兩個值相等,排序后順序發生了變化,則不穩定,反之穩定。
常見遞推式與復雜度:
1.冒泡排序
執行順序:從頭開始,如果第一個數比第二個數小,則不動,如果比第二個數比較小,就交換這兩個數據。一次往后移動,這樣循環一次就可以將最大的數移動到最后位置。下一次循環就忽略上一次排序的最大數,在剩下的元素里再進行循環。連續多次就可以實現。(因為這樣的排序,比較大或者比較小的數會連續的想后移動,一次排序一個,形似冒泡。)
冒泡排序的時間復雜度是十分不確定的,對于已有順序的復雜度很小,但是對于大量隨機數據,是可能會更高的,因為一旦if語句判定成功,就要進行數據交換。
2.選擇排序
多次循環,每輪跳出最大值,將最大值(升序情況,降序相反)放到最后一個未排序的位置,與其交換值。
相比于冒泡排序,時間復雜度可能更高o(n^2),但是,交換的次數更少,如果是處理隨機數據,選擇排序可能比冒泡排序更好。因為他并不會像冒泡一樣,if判定為真就執行交換,而是遍歷一次才交換一次數據。
注意:數組選擇排序不能保證絕對的穩定性。如果多組相等值,可能會導致混亂,例如:
1,2,3,5,10,10,2,3,2.
雖然可以把第二個10放在最后,但是最后一個2被放在第二個2前面了。
以上僅是數組的選擇排序,但是鏈表的選擇排序是穩定的
3.堆排序(如果你不知道堆,就不用看了,看了也不懂)
堆排序可以認為是對選擇排序的優化。從數組中挑一個最大的。不過優化了選擇最大的時間復雜度進行了優化。
步驟:原地建堆
大頂堆:最大值就會在堆頂,將堆第一個數據與最后一個數據進行交換,再把最后一個元素放到堆頂。對堆頂進行siftDown操作。一直重復,直到堆只有一個元素。siftDown的時間復雜度是o(n*logn)。空間復雜度o(1)。
堆排序不是穩定的排序。
4.插入排序(撲克牌玩過沒?)
在執行過程中,插入排序將序列分為兩部分,頭部是已經排好序的,尾部待排序。是穩定的排序。
插入排序的交換次數比較多,數量比較小的情況下比較適合。
**時間復雜度:**插入排序的時間復雜度跟逆序對正相關的。
【優化交換次數】:將待插入的數據放在旁邊,將前面有序的比待插入的數大的都往后挪一位,然后將待插入元素放到正確位置就可以。
public int[] InsertSort(int[] in){//類似于撲克牌 ,前面部分相當于在手里的牌,//i指向的牌相當于拿起來的牌,然后遍歷手里的牌,// 找個合適的位置放進去for (int i = 1; i < in.length; i++) {int j = i;int insert = in[j];//重點是移動前面大的while(j>0&&insert<in[j-1]){in[j] = in[j-1];j--;}in[j] = insert;}return in;}【優化查找】還可以使用二分查找的方法進行查找插入。能將該方法進一步進行優化。二分查找的方法代碼如下:
public int[] InsertSort2(int[] in){for (int i = 1; i < in.length; i++) {int j = i;int insert = in[j];int index = search(in,insert,j);//查找插入位置while(j>index){//重點是移動前面大的in[j] = in[j-1];j--;}in[j] = insert;}return in;}//二分查找進行優化,返回第一個大于x的元素索引,插入位置public int search(int [] in,int x){if(in == null||in.length==0) return -1;int left = 0;int right = in.length;while(left!=rigth){int mid = (left+right)>>1;if(x<in[mid]){right = mid;} else{left = mid+1;}}return left;}5.歸并排序(Merge Sort)
不斷地將當前序列分割成兩個子序列,直到兩個子序列不能再分。再將子序列不斷的合并成一個有序序列,直到最后只剩下一個有序序列。
如果不考慮空間問題,則可以直接將數組拆分為兩個數組進行組合就可以了。如下圖。
合并的時候需要先拷貝整個數組的左半邊數組,為了節省空間,就可以在輸入數組上直接進行比較填入。例如下圖,第一個元素,左邊較小,就先填入左邊的數據。依次后推。
具體的實現代碼如下:(使用遞歸的,不太好理解!!!)
休眠排序(請不要使用此方法,純屬娛樂)
用線程的休眠機制進行排序。。。(適用于數字型的排序),給出一個數組,然后遍歷數組,循環建立線程,對相應建立的線程進行sleep睡眠相應的時間進行輸出。實現排序。
//休眠排序(娛樂)public void SleepSort(int[] in){for (int i : in) {new SortThread(i).start();}} class SortThread extends Thread{private int value;public SortThread(int value){this.value =value;}public void run(){try{Thread.sleep(value);System.out.println(value);}catch (InterruptedException e){e.printStackTrace();}} }6.快速排序(Quick Sort)(不穩定)
執行流程:
1.首先選擇一個軸點元素;
2.按照軸點元素將所有 的元素分割為兩個子序列;
?將大于軸點元素放在右邊;
?小于軸點的放左邊;
?等于的元素隨便放置都可以。
3.對子序列進行繼續切分操作,直到不能再切分。
如下圖,帶顏色的是軸點元素。
具體代碼實現如下:
7.希爾排序
把序列看做一個矩陣。分為m列,逐列進行排序,m從某個整數逐漸減為1,當m為1的時候,整個序列將完全有序。
因此希爾排序也被稱為遞減增量排序。矩陣的列數取決于步長序列。
希爾本人給出的步長序列是n/2k,比如n為16,步長序列為1,2,4,8。希爾不認的步長序列最差復雜度是o(n2)。目前科學家研究的最佳步長序列算法見下文:
疑惑嗎?如果上來直接分為1列不就直接排好了?
其實不是,前面的幾次排列,每次逆序對的數量在不斷減少的。到這里請返回去看插入排序,在每一次的步長排序中,逆序對都減少,那么底層就很適合用插入排序來實現。所以也有人認為希爾排序實際是插入排序的一種優化。
________________________________________________________________________
以上都是基于比較的排序,時間復雜度最低都是o(n*logn)。下面的方法都是基于比較的排序方式,屬于典型的利用空間換時間,某些時候,平均時間復雜度可以更小。
8.計數排序(Count Sort針對一定范圍的整數排序)
核心思想是統計整數在序列中出現的次數,進而推導出有序的索引。時間復雜度是o(N);
數組的長度取決于序列中最大的數的大小。統計完成后直接從小到大的依次輸出就可以得到排序的結果。
這個實現很簡單,就不加注釋了,如下!
9.基數排序(Radix Sort)
適用于整數排序(尤其是非負整數)。
執行流程:依次對個位數、十位數、百位數、千位數、、、等進行排序。(從低到高)
針對每個位上的數進行一次計數排序。可以理解為把計數排序的索引更換成數字的每個位。這樣都是在0-9之間的數。
10.桶排序(Bucket Sort)
執行流程:創建一定數量的桶(數組,鏈表),按照一定的規則將序列中的元素均勻分配到桶里面,分別對桶每個桶進行排序。將所有非空的桶合并成有序數列。桶排序沒有具體的規范式,需要自己進行規劃。代碼大家自己操作吧!!!(實際上是我寫了,沒跑對!)
4.數據庫
請簡潔描述Mysql中InnoDB支持的四種事務隔離級別名稱,以及逐級之間的區別?
Read Uncommitted(讀取未提交內容) >> 在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用于實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之為臟讀(Dirty Read)。
Read Committed(讀取提交內容) >> 這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別也支持所謂的不可重復讀(Nonrepeatable Read),因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。
Repeatable Read(可重讀) >> 這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在并發讀取數據時,會看到同樣的數據行。不過理論上,這會導致另一個棘手的問題:幻讀(Phantom Read)。簡單的說,幻讀指當用戶讀取某一范圍的數據行時,另一個事務又在該范圍內插入了新行,當用戶再讀取該范圍的數據行時,會發現有新的“幻影” 行。InnoDB和Falcon存儲引擎通過多版本并發控制(MVCC,Multiversion Concurrency Control 間隙鎖)機制解決了該問題。注:其實多版本只是解決不可重復讀問題,而加上間隙鎖(也就是它這里所謂的并發控制)才解決了幻讀問題。
Serializable(可串行化) >> 這是最高的隔離級別,它通過強制事務排序,使之不可能相互沖突,從而解決幻讀問題。簡言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。
在Mysql中ENUM的用法是什么?
枚舉類型:用來描述數據庫中限定的類型,例如:
枚舉類型的使用需要注意的事項:
盡量不要存放數值型,因為枚舉的使用也是用數值型的下標來獲取的。
枚舉中是否可以存取null由聲明的狀態決定,如果聲明時注明NOT null ,則不允許存取null值。
向枚舉中存入未列舉的詞時,會提示數據截斷警告,但是依然會操作成功。
CHAR和VARCHAR和NVARCHAR 的區別?
char是固定長度的,也就是說在聲明char類型是所規范的長度就是固定,當輸入的長度大于定義的長度時,就會導致數據被截斷,小于時,數據庫會自動在后面添加空值補齊。
但是varchar不一樣,是不支持Unicode的字符串,他的長度并不固定,所以輸入的過長不會被截斷(8000以內),輸入的過短也不會補齊。更加靈活。
nvarchar包含 n 個字符的可變長度 Unicode 字符數據,因為對Unicode的支持,字節的存儲大小是所輸入字符個數的兩倍。所輸入的數據字符長度可以為零,可以輸入中文。
事務是如何通過日志來實現的,說得越深入越好
(1)有多少種日志
redo和undo
(2)日志的存放形式
redo:在頁修改的時候,先寫到 redo log buffer 里面, 然后寫到 redo log 的文件系統緩存里面(fwrite),然后再同步到磁盤文件( fsync)。
Undo:在 MySQL5.5 之前, undo 只能存放在 ibdata文件里面, 5.6 之后,可以通過設置 innodb_undo_tablespaces 參數把 undo log 存放在 ibdata之外。
(3)事務是如何通過日志來實現基本流程如下:
因為事務在修改頁時,要先記 undo,在記 undo 之前要記 undo 的 redo, 然后修改數據頁,再記數據頁修改的 redo。 Redo(里面包括 undo 的修改) 一定要比數據頁先持久化到磁盤。 當事務需要回滾時,因為有 undo,可以把數據頁回滾到前鏡像的 狀態,崩潰恢復時,如果 redo log 中事務沒有對應的 commit 記錄,那么需要用 undo把該事務的修改回滾到事務開始之前。 如果有 commit 記錄,就用 redo 前滾到該事務完成時并提交掉。
drop,delete與truncate的區別
作用范圍和結果不同
(1)DELETE語句執行刪除的過程是每次從表中刪除一行,并且同時將該行的刪除操作作為事務記錄在日志中保存以便進行進行回滾操作。
TRUNCATE TABLE 則一次性地從表中刪除所有的數據并不把單獨的刪除操作記錄記入日志保存,刪除行是不能恢復的。并且在刪除的過程中不會激活與表有關的刪除觸發器。執行速度快。
(2)表和索引所占空間。
當表被TRUNCATE 后,這個表和索引所占用的空間會恢復到初始大小,
DELETE操作不會減少表或索引所占用的空間。且常常是配合where一起使用的。
drop語句將表所占用的空間全釋放掉。
(3)一般而言,drop > truncate > delete
局部性原理與磁盤預讀
磁盤預讀:因為磁盤的速度與主存的速度差距很大,為了提高讀取的效率,磁盤往往都不是按需讀取,而是進行了預讀,以減少磁盤的IO次數,提高效率,往往會預讀一定的數據放入主存。
局部性原理:當一個數據被用到時,其附近的數據也通常會馬上被使用。程序運行期間所需要的數據通常比較集中。由于磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間) ,因此對于具有局部性的程序來說,磁盤預讀可以提高I/0效率。
預讀的長度一般為頁(page)的整倍數。頁是計算機管理存儲器的邏輯塊,硬件及操作系統往往將主存和磁盤存儲區分割為連續的大小相等的塊,每個存儲塊稱為一頁(在許多操作系統中,頁得大小通常為4k) ,主存和磁盤以頁為單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置并向后連續讀取一頁或幾頁載入內存中,然后異常返回,程序繼續運行。
數據庫范式
第一范式 1NF
定義: 屬于第一范式關系的所有屬性都不可再分,即數據項不可分。
理解: 第一范式強調數據表的原子性,是其他范式的基礎。
簡言之:列不可再分。同一列表示一個屬性。
第二范式 2NF
定義: 若某關系R屬于第一范式,且每一個非主屬性完全函數依賴于任何一個候選碼,則關系R屬于第二范式。
此處我們需要理解非主屬性、候選碼和完全函數依賴的概念。
也就是說不依賴于別的屬性,主需要依賴于一個候選碼就可以確定一個元組,例如學號。學號確定那么其他的屬性都是唯一對應的關系。那么一個表可以有多個候選碼,比如學號、姓名等。主碼可以隨機選一個或者多個候選碼。
理解: 第二范式是指每個表必須有一個(有且僅有一個)數據項作為關鍵字或主鍵(primary key),其他數據項與關鍵字或者主鍵一一對應,即其他數據項完全依賴于關鍵字或主鍵。由此可知單主屬性的關系均屬于第二范式。
簡言之:一個表只可以描述一個事情。
第三范式 3NF
定義: 非主屬性既不傳遞依賴于碼,也不部分依賴于碼。
理解: 第三范式要求在滿足第二范式的基礎上,任何非主屬性不依賴于其他非主屬性,即在第二范式的基礎上,消除了傳遞依賴。
簡言之:一個表包含訂單編號,顧客編號,顧客姓名,那么就形成了顧客姓名依賴顧客編號,顧客編號依賴訂單編號的傳遞依賴。
訂單編號--->顧客編號---->顧客姓名
BC范式 BCFN
定義: 關系模式R<U,F>中,若每一個決定因素都包含碼,則R<U,F>屬于BCFN。
理解: 根據定義我們可以得到結論,一個滿足BC范式的關系模式有:
所有非主屬性對每一個碼都是完全函數依賴;
所有主屬性對每一個不包含它的碼也是完全函數依賴;
沒有任何屬性完全函數依賴于非碼的任何一組屬性。
第四范式 4NF
定義: 限制關系模式的屬性之間不允許有非平凡且非函數依賴的多值依賴。
理解: 顯然一個關系模式是4NF,則必為BCNF。也就是說,當一個表中的非主屬性互相獨立時(3NF),這些非主屬性不應該有多值,若有多值就違反了4NF。
第五范式 5NF
第五范式有以下要求:
(1)必須滿足第四范式;
(2)表必須可以分解為較小的表,除非那些表在邏輯上擁有與原始表相同的主鍵。
存儲過程與觸發器的區別
存儲過程:是擁有特定功能的與SQL語句集,存儲在數據庫中,一次編譯過后,再次使用就不需要再次編譯,用戶通過指定存儲過程的名字給出參數(如果該存儲過程帶有 參數)來執行它。存儲過程是數據庫的一個重要對象。
觸發器:一段時間自動執行的程序,是一種特殊的存儲過程,觸發器和普通的存儲過程的區別是:觸發器是對某一個表進行操作時觸發。例如update、insert、delete等等。進行這些操作的時候系統會自動執行該表對應的觸發器。
鎖的優化策略
什么情況下設置了索引但無法使用
哪些情況下適合建索引
哪些情況下不適合建索引
解釋MySQL外連接、內連接與自連接的區別
內連接:兩個表都滿足的項才會被連接成新虛擬表
外連接分為左連接、右連接,分別以左邊和右邊表的條件滿足為準,另一個表沒有對應項的會填充null值
自連接就是一個表和自己連接,可以理解為一種特殊的內連接,這樣會形成兩個并列的表
完整性約束包括哪些?
數據完整性(Data Integrity)是指數據的精確(Accuracy)和可靠性(Reliability)。
分為以下四類:
1、實體完整性:規定表的每一行在表中是惟一的實體。
2、域完整性:是指表中的列必須滿足某種特定的數據類型約束,其中約束又包括 取值范圍、精度等規定。
3、參照完整性:是指兩個表的主關鍵字和外關鍵字的數據應一致,保證了表之間的數據的一致性,防止了數據丟失或無意義的數據在數據庫中擴散。
4、用戶定義的完整性:不同的關系數據庫系統根據其應用環境的不同,往往還需 要一些特殊的約束條件。用戶定義的完整性即是針對某個特定關系數據庫的約束 條件,它反映某一具體應用必須滿足的語義要求。
Mysql 的存儲引擎,myisam和innodb的區別。
| myisam | 1、不支持數據庫事務 2、不支持行級鎖,寫操作鎖定整個表 ,效率低 3、不支持外鍵 | 1、執行讀取速度很快2、占用內存空間少3、存儲空間占用少 |
| innodb | 上面的都支持 | 和上面相對 |
如何進行SQL優化
1、建立索引
2、避免在where進行null判斷
3、將in換成exist(in不能走索引)
4、使用like語句盡量以具體參數開頭,不要以%(%不走索引)
5、減少使用SELECT*,把*換成具體內容更快
。。。
更多戳這里,偷窺別人家的秘籍
樂觀鎖和悲觀鎖是什么,INNODB的標準行級鎖有哪2種,解釋其含義。
InnoDB實現了以下兩種類型的行鎖:
共享鎖(S):允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。
排他鎖(X):允許獲得排他鎖的事務更新數據,阻止其他事務取得相同數據集的共享讀鎖和排他寫鎖。
另外,為了允許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB還有兩種內部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖。
意向共享鎖(IS):事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖。
意向排他鎖(IX):事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖。
| 鎖兼容 | X | IX | S | IS |
| X | 沖突 | 沖突 | 沖突 | 沖突 |
| IX | 沖突 | 兼容 | 沖突 | 兼容 |
| S | 沖突 | 沖突 | 兼容 | 兼容 |
| IS | 沖突 | 兼容 | 兼容 | 兼容 |
MVCC的含義,如何實現的
MVCC是通過在每行記錄后面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的創建時間,一個保存行的過期時間(或刪除時間)。當然存儲的并不是實際的時間值,而是系統版本號(system version number)。每開始一個新的事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會作為事務的版本號,用來和查詢到的每行記錄的版本號進行比較。
詳情請看別人家的文章:戳這里,修煉其他門派秘籍
MYSQL的主從延遲怎么解決
這點太復雜。。。大家找別人家秘籍。
spring
(1)spring概述
使用Spring框架的好處是什么?
1.方便解耦,簡化開發
通過Spring提供的IoC容器,我們可以將對象之間的依賴關系交由Spring進行控制,避免硬編碼所造成的過度程序耦合。有了Spring,用戶不必再為單實例模式類、屬性文件解析等這些很底層的需求編寫代碼,可以更專注于上層的應用。
2.AOP編程的支持
通過Spring提供的AOP功能,方便進行面向切面的編程,許多不容易用傳統OOP實現的功能可以通過AOP輕松應付。
3.聲明事物的支持
在Spring中,我們可以從單調煩悶的事務管理代碼中解脫出來,通過聲明式方式靈活地進行事務的管理,提高開發效率和質量。
4.方便程序的測試
可以用非容器依賴的編程方式進行幾乎所有的測試工作,在Spring里,測試不再是昂貴的操作,而是隨手可做的事情。例如:Spring對Junit4支持,可以通過注解方便的測試Spring程序。
5.方便集成各種優秀框架
Spring不排斥各種優秀的開源框架,相反,Spring可以降低各種框架的使用難度,Spring提供了對各種優秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
6.降低Java EE API的使用難度
Spring對很多難用的Java EE API(如JDBC,JavaMail,遠程調用等)提供了一個薄薄的封裝層,通過Spring的簡易封裝,這些Java EE API的使用難度大為降低。
Spring由哪些模塊組成?
1.Spring Core:Spring框架的核心容器,他提供了Spring框架的基本功能。這個模塊中最主要的一個組件為BeanFactory,它使用工廠模式來創建所需的對象。同時BeanFactory使用IOC思想,通過讀取XML文件的方式來實例化對象,可以說BeanFactory提供了組件生命周期的管理,組件的創建,裝配以及銷毀等功能;
2.Spring AOP:采用了面向切面編程的思想,使Spring框架管理的對象支持AOP,同時這個模塊也提供了事務管理,可以不依賴具體的EJB組件,就可以將事務管理集成到應用程序中;
3.Spring ORM:提供了對現有的ORM框架的支持,例如Hibernate等;
4.Spring DAO:提供了對DAO(Data Access Object,數據訪問對象)模式和JDBC的支持。DAO可以實現將業務邏輯與數據庫訪問的代碼分離,從而降低代碼的耦合度。通過對JDBC的抽象,簡化了開發工作,同時簡化了對異常的處理(可以很好的處理不同數據庫廠商拋出的異常);
5.Spring Web:提供了Servlet監聽器的Context和Web應用的上下文。同時還集成了一些現有的Web框架,例如Struts;
6.Spring Context:擴展核心容器,提供了Spring上下文環境,給開發人員提供了很多非常有用的服務,例如國際化,Email和JNDI訪問等;
7.Spring Web MVC:提供了一個構建Web應用程序的MVC的實現
解釋AOP模塊
解釋WEB 模塊
核心容器(應用上下文) 模塊。
什么是Spring IOC 容器?
IOC容器負責實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。應用程序無需直接在代碼中new相關的對象,應用程序由IOC容器進行組裝。
IOC的優點是什么?
第一,資源集中管理,實現資源的可配置和易管理。
第二,降低了使用資源雙方的依賴程度,即耦合度。
ApplicationContext通常的實現是什么?
1>FileSystemXmlApplicationContext:此容器從一個XML文件中加載bean的定義,XML Bean配置文件的全路徑名必須提供給它的構造函數
2>ClassPathXmlApplicationContext:此容器也從一個XML文件中加載bean的定義,這里需要正確設置classpath因為這個容器將在classpath里找bean配置
3>WebXmlApplicationContext:此容器加載一個XML文件,此文件定義了一個WEB應用的所有bean
(2)spring依賴注入
什么是Spring的依賴注入?
有哪些不同類型的IOC(依賴注入)方式?
什么是Spring beans?
一個 Spring Bean 定義 包含什么?
解釋Spring支持的幾種bean的作用域。
Spring框架中的單例bean是線程安全的嗎?
解釋Spring框架中bean的生命周期
哪些是重要的bean生命周期方法? 你能重載它們嗎?
什么是bean裝配?
什么是bean的自動裝配?
解釋不同方式的自動裝配 。
自動裝配有哪些局限性 ?
(3) spring 注解
怎樣開啟注解裝配?
首先需要導入aop包,和約束context,然后需要在xml文件中加入注解支持。
<context:annotation -config/>
談談@Required、 @Autowired、 @Qualifier注解。
@Resource
(4) spring 數據訪問
在Spring框架中如何更有效地使用JDBC?
使用Spring通過什么方式訪問Hibernate?
Spring框架的事務管理有哪些優點?
(5) Spring面向切面編程(AOP)
解釋AOP
Aspect 切面
在Spring AOP 中,關注點和橫切關注的區別是什么?
通知
有幾種不同類型的自動代理?
什么是織入。什么是織入應用的不同點?
(6) springMVC
什么是Spring的MVC框架?
DispatcherServlet
WebApplicationContext
什么是Spring MVC框架的控制器?
@Controller 注解
@RequestMapping 注解
JavaWeb
(1)servlet與Tomcat
Servlet生命周期
forward和redirect的區別
tomcat容器是如何創建servlet類實例?用到了什么原理?
什么是cookie?Session和cookie有什么區別?
Servlet安全性問題
Tomcat 有哪幾種Connector 運行模式(優化)?
(2)JSP
jsp靜態包含和動態包含的區別
jsp有哪些內置對象?作用分別是什么?
jsp和servlet的區別、共同點、各自應用的范圍?
寫出5種JSTL常用標簽
JSP是如何被執行的?執行效率比SERVLET低嗎?
說出Servlet和CGI的區別?
簡述JSP的設計模式。
總結
以上是生活随笔為你收集整理的Java面试题及答案整理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 看拉扎维《模拟CMOS集成电路设计》的一
- 下一篇: 解决看网课鼠标不能移开,视频不能加速