一、王者榮耀服務器實現
二、接口和類的區別?
1、類只能繼承一個類,但可以實現多個接口。
2、對於繼承性,類繼承了父類的方法,子類可以選擇是否覆蓋父類的方法。
3、接口的方法只有聲明,沒有實現;而類中的方法必須有方法體。
三、接口可以實例化嗎?爲什麼?那lambda表達式不就是傳入一個接口的實例嗎?
接口不可以實例化,因爲接口可以看成是特殊的抽象類,比抽象類的程度更高,其所有方法都是public abstract類型的,因此不能實例化。
Lambda表達式的原理是:
1、編譯器根據Lambda表達式生成一個私有的靜態函數,這個私有函數就是執行Lambda表達式裏的內容
2、生成一個內部類並調用上述所生成的私有靜態函數
3、將Lambda表達式替換爲該內部類的一個實例傳入方法體中
所以本質上來講Lambda表達式並非傳入一個接口的實例,而是傳入一個內部類的實例。
這裏引用一下別人的代碼:
public class LambdaTest {
public static void printString(String s, Print<String> print) {
print.print(s);
}
public static void main(String[] args) {
printString("test", (x) -> System.out.println(x));
}
}
@FunctionalInterface
interface Print<T> {
public void print(T x);
}
反編譯代碼:
public class LambdaTest {
public static void PrintString(String s, Print<String> print) {
print.print(s);
}
public static void main(String[] args) {
PrintString("test", new LambdaTest$$Lambda$1());
}
private static void lambda$main$0(String x) {
System.out.println(x);
}
static final class LambdaTest$$Lambda$1 implements Print {
public void print(Object obj) {
LambdaTest.lambda$main$0((String) obj);
}
private LambdaTest$$Lambda$1() {
}
}
}
@FunctionalInterface
interface Print<T> {
public void print(T x);
}
四、可以在static方法內部調用非靜態方法嗎
static內部不能直接調用該類的非靜態方法,但是如果通過傳入一個對象的引用到靜態方法,然後通過該引用就可以調用非靜態方法和非靜態成員了。
五、可以在子類重寫父類的static方法嗎
邏輯上可以,編譯可以通過,但在父類引用指向子類對象的時候,通過父類引用調用的仍然是父類的類方法,而不是子類的。
public class StaticFather {
public static void print() {
System.out.println("I am father");
}
}
public class StaticSon extends StaticFather {
public static void print() {
System.out.println("I am son");
}
}
public class Main {
public static void main(String[] args) {
StaticFather A = new StaticFather();
StaticFather B = new StaticSon();
StaticSon C = new StaticSon();
A.print();
B.print();
C.print();
}
}
Result:
I am father
I am father //通過父類引用調用靜態方法時,仍然是父類的靜態方法,而非子類的
I am son
六、Hashmap底層實現及工作過程
底層採用數組+鏈地址表法實現,jdk1.8後當鏈地址表的長度超過8時會用一棵紅黑樹來代替。
put方法工作過程:
1、調用hashcode()函數得到其哈希值
2、根據散列函數(n-1)&hashcode來計算數組下標
3、如果定位到的數組位置沒有元素就直接插入;如果有元素就檢查該元素是否重複,重複就覆蓋,否則判斷該數組位置是存放紅黑樹還是鏈表,紅黑樹就調用相應的方法插入,鏈表就在鏈表尾部插入
七、LinkedHashmap如何保證有序
LinkedHashMap繼承了HashMap,並定義了一個繼承自HashMap.Node的Entry靜態內部類,這個類記錄了節點的上一個節點和下一個節點,因此在插入數據的時候,就會綁定在上一個最後插入的節點後面來保證有序。
八、線程狀態有哪些
新建(new)
就緒(Runnable)
阻塞(Blocked)
死亡(Dead)
九、sleep()和wait()有什麼區別?調用後線程的狀態一致嗎?
sleep()是Thread類的方法,可使線程暫定指定的時間,進入阻塞狀態,指定時間過後會變爲就緒態;sleep()可以在任何地方調用,且必須捕獲異常,如果不捕獲異常,當產生InterruptedException異常時該線程就會進入死亡狀態。
而wait()是Object類的方法,可是線程進入阻塞狀態,同時進入一個和該對象相關的等待池中,同時釋放掉持有的對象鎖;wait()方法只能在synchronized同步塊中調用,不需要捕獲異常。
兩者都會進入阻塞狀態。
九、java線程池怎麼實現
線程池是指管理一組同構工作線程的資源池,線程池的實現與工作隊列密切相關,在工作隊列中保存了所有等待執行的任務,工作者線程的任務就是從工作隊列中獲取一個任務、執行任務,然後返回線程池中並等待下一個任務的分配。
當工作隊列被填滿後,開始執行飽和策略:
1、中止(Abort)策略:拋出未檢查的RejectedExecutionException,調用者可以捕獲這個異常,並根據需求編寫處理代碼。
2、調用者運行(Caller-Runs)策略:將某些任務回退到調用者,降低新任務的流量。
3、拋棄(Discard)策略:直接拋棄該任務。
4、拋棄最舊(Discard-Oldest)策略:拋棄下一個被執行的任務,然後嘗試重新提交新的任務(如果是優先級隊列則會拋棄優先級最高的)。
十、算法
1、打亂一個數組
public class UpsetArray {
public static void upset(int []array, int n) {
Random random = new Random();
int temp;
int randomNum;
for (int i = 0; i < n; i++) {
randomNum = random.nextInt(n - i) + i;
temp = array[randomNum];
array[randomNum] = array[i];
array[i] = temp;
}
}
public static void test() {
int array[] = { 0, 5, 3, 2, 1, 7, 4};
System.out.println(Arrays.toString(array));
upset(array, array.length);
System.out.println(Arrays.toString(array));
}
}
Result:
[0, 5, 3, 2, 1, 7, 4]
[3, 5, 0, 2, 1, 4, 7]
2、歸併排序(見排序算法實現博文)
引用:https://blog.csdn.net/jiankunking/article/details/79825928