目錄html
本文轉載自原博客 ,雖然說是面試題,可是裏面的知識點都值得去掌握,我會去查證答案,不會的暫留。恰好準備辭職了,這幾天補充一下java
我是蜀雲泉mysql
我作過XX項目程序員
封裝,多態,繼承三大特色web
final是表示不可變的,例如final一個變量,那麼這個變量的值不會變,就是常量。final一個方法,這個方法不能被子類重寫,final一個類,這個類不能被繼承。面試
finally這個是try catch捕捉異常的語句中最終執行的部分,須要注意的是,finally通常是在try和catch的return以前才執行的,這句話很重要,能夠去參考這篇文章finally在try和catch的return以前執行redis
finalize是在Object類中定義的,最主要的用途是回收特殊渠道申請的內存。Java程序有垃圾回收器,因此通常狀況下內存問題不用程序員操心。但有一種JNI(Java Native Interface)調用non-Java程序(C或C++),finalize()的工做就是回收這部分的內存。算法
Integer是java爲int提供的封裝類。int的默認值爲0,而Integer的默認值爲null,即Integer能夠區分出未賦值和值爲0的區別,int則沒法表達出未賦值的狀況,例如,要想表達出沒有參加考試和考試成績爲0的區別,則只能使用Integerspring
①不管如何,Integer與new Integer不會相等。內存地址不同。
②兩個都是非new出來的Integer,若是數在-128到127之間,則是true,不然爲false,由於 java在編譯Integer i = 128的時候,被翻譯成 Integer i = Integer.valueOf(128);而valueOf()函數會對-128到127之間的數進行緩存,因此Integer a=127;Integer b=127;a==b是true的,由於都是緩存中取得數據,可是範圍以外的就不同了。sql③兩個都是new出來的,都爲false。地址都不同了
④int和integer(不管new否)比,都爲true,由於會把Integer自動拆箱爲int再去比
方法重載是指同一個類中的多個方法具備相同的名字,但這些方法具備不一樣的參數列表,即參數的數量或參數類型不能徹底相同
方法重寫是存在子父類之間的,子類定義的方法與父類中的方法具備相同的方法名字,相同的參數表和相同的返回類型
注:
(1)子類中不能重寫父類中的final方法
(2)子類中必須重寫父類中的abstract方法
含有abstract修飾符的class即爲抽象類,abstract 類不能建立的實例對象。含有abstract方法的類必須定義爲abstract class,abstract class類中的方法沒必要是抽象的。abstract class類中定義抽象方法必須在具體(Concrete)子類中實現,因此,不能有抽象構造方法或抽象靜態方法。若是的子類沒有實現抽象父類中的全部抽象方法,那麼子類也必須定義爲abstract類型。
接口(interface)能夠說成是抽象類的一種特例,接口中的全部方法都必須是抽象的。接口中的方法定義默認爲public abstract類型,接口中的成員變量類型默認爲public static final。
下面比較一下二者的語法區別:
- 抽象類能夠有構造方法,接口中不能有構造方法。
- 抽象類中能夠有普通成員變量,接口中沒有普通成員變量
- 抽象類中能夠包含非抽象的普通方法,接口中的全部方法必須都是抽象的,不能有非抽象的普通方法。
- 抽象類中的抽象方法的訪問類型能夠是public,protected和(默認類型,雖然 eclipse下不報錯,但應該也不行),但接口中的抽象方法只能是public類型的,而且默認即爲public abstract類型。
- 抽象類中能夠包含靜態方法,接口中不能包含靜態方法
- 抽象類和接口中均可以包含靜態成員變量,抽象類中的靜態成員變量的訪問類型能夠任意,但接口中定義的變量只能是public static final類型,而且默認即爲public static final類型。
- 一個類能夠實現多個接口,但只能繼承一個抽象類。
①、在運行時判斷任意一個對象所屬的類
②、在運行時構造任意一個類的對象
③、在運行時判斷任意一個類所具備的成員變量和方法(經過反射設置能夠調用 private)
④、在運行時調用人一個對象的方法反射的用途
不少人都認爲反射在實際Java中開發應用中並不普遍,其實否則。
當咱們在使用 IDE(如 Eclipse\IDEA)時,當咱們輸入一個隊長或者類並向調用它的屬性和方法時,一按 (「.」)點號,編譯器就會自動列出她的屬性或方法,這裏就會用到反射。
標準答案:
GET在瀏覽器回退時是無害的,而POST會再次提交請求。
GET產生的URL地址能夠被Bookmark,而POST不能夠。
GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
GET請求只能進行url編碼,而POST支持多種編碼方式。
GET請求參數會被完整保留在瀏覽器歷史記錄裏,而POST中的參數不會被保留。
GET請求在URL中傳送的參數是有長度限制的,而POST麼有。
對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
GET比POST更不安全,由於參數直接暴露在URL上,因此不能用來傳遞敏感信息。
GET參數經過URL傳遞,POST放在Request body中。
牛逼的本質:
GET和POST是HTTP協議中的兩種發送請求的方法。
HTTP是基於TCP/IP的關於數據如何在萬維網中如何通訊的協議。
因此GET/POST都是TCP連接。
GET產生一個TCP數據包;POST產生兩個TCP數據包。
對於GET方式的請求,瀏覽器會把http header和data一併發送出去,服務器響應200(返回數據);
而對於POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)
本回答參考文章,建議讀一下,寫的很是棒Get和Post的區別
Session和Cookie是幹嗎的?首先我先說一個HTTP協議,傳輸數據,咱們知道,TCP/IP能夠傳輸數據,所謂的HTTP協議,就是TCP/IP在網絡層面傳輸的一個包裝規則。因此,HTTP協議的本質就是TCP/IP
HTTP協議有一個特色:無狀態鏈接
我訪問淘寶,登陸帳戶,跳轉了頁面,我一買東西,瀏覽器告訴我,不知道你的帳戶是啥,由於HTTP訪問是無狀態的,我登陸以後,跳轉了頁面,個人登陸信息已經沒了,買東西的時候,他根本不知道上次請求是啥,也不知道個人任何信息。這怎麼行,每次請求之間必須能夠通訊,必須數據能夠共享。有3種方法可使得每次請求之間數據共享
1.url帶參數
2.Cookie
3.Session
url帶參數咱們確定不使用,這種方式會把參數顯示在url欄裏面,好嘛,個人帳戶和密碼都顯示出來了,我還有啥隱私可言。因此,HTTP無狀態協議每次請求之間的數據互通,咱們使用Session和Cookie
區別:
1.Cookie數據存儲在客戶端,Session數據存儲在服務器端
2.由於Cookie存儲在客戶端,因此不安全,有可能有Cookie欺騙,因此登陸信息,涉及到密碼的可使用Session
3.Cookie有大小限制,每一個Cookie數據不能超過4kb,不少瀏覽器限制一個網站最多保存20個Cookie
4.Cookie分爲會話層Cookie和持久層Cookie,Session的本質就是會話層Cookie,因此一但你的瀏覽器禁用了Cookie,Cookie和Session都沒法使用
5.Cookie的key-value都是String類型的,Session的key-value是String-Object類型的
更多的詳細內容,去閱讀個人博客Java Web之Cookie、Session]
最簡單的,分爲5個步驟,賈璉欲執事
@Test public void Con() throws Exception { String sql="insert SysUser values('201408090009',123,'李信','男','王者榮耀','shuyunquan@qq.com','老師')"; //1.加載註冊Mysql驅動 Class.forName("com.mysql.cj.jdbc.Driver"); //2.連接數據庫,獲取連接對象 Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/Design?serverTimezone=UTC"); //3.建立語句對象 Statement st=con.createStatement(); //4.執行SQL語句 int row=st.executeUpdate(sql); //5.釋放資源 st.close(); con.close(); }這個是最簡單的,後面涉及到鏈接池什麼的參考個人文章Java JDBC
==判斷兩個對象的引用內存地址是否一致
equals是Object類裏面的,子類通常均可以重寫,而子類通常都重寫成了值對比
舉例:
String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2);//true String str3 = new String("abc"); String str4 = new String ("abc"); System.out.println(str3==str4);//false System.out.println(str3.equals(str4));//true上面的str1和str2都是同一內存空間下的abc,因此str1和str2==是true
下面的new了兩個對象,那就開闢了兩個內存空間,str3和str4確定不==,可是equals是值比較,他倆的值都是abc,因此是true
開局一張圖,剩下的全都會
根據神圖,咱們已經知道
1.List能夠記錄添加順序,能夠重複,Set沒有順序,不能重複
2.List能夠插入多個null元素,Set只能插入一個null
3.List和Set都實現於collection
只有繼承collection接口的纔算集合,因此List是集合,Map自己就是一個接口,因此Map根本就不是集合。Map就是兩個集合之間的映射關係,由key-value組成,也稱之爲鍵值對Entry ,因此Map也能夠理解爲由一個個Entry組成的,是否是有點 Set
的意思,因爲Map沒有繼承Collection接口和Iterable接口,因此Map是不能使用foreach迭代的 1.List是集合,Map不是集合
2.List有序,可重複。Map的key 不容許重複,value能夠重複
ArrayList底層是數組
LinkedList底層是雙向鏈表
因此他們倆的區別,也就是數組和鏈表的區別
頻繁的訪問get或set,固然數組的ArrayList好一點,由於LinkedList還須要移動指針
頻繁的增長或者刪除add/delete,固然是鏈表的LinkedList比較好一點,鏈表直接更改一下指針指向就ok,數組的ArrayList還得移動數據
Vector和ArrayList的關係:
1):底層算法都是基於數組.
2):ArrayList是集合框架裏提供的新的變長數組.Vector是ArrayList的前身.
3):Vector相對於ArrayList來講,線程更安全,可是性能較低.
不推薦使用Vector,用ArrayList就能夠了
這個和上面的差很少
1.都採用的是哈希表算法,底層都是數組+鏈表
2.HashMap中的key沒有順序,也不容許重複,key和value能夠爲null,初始值是16,線程不安全
3.HashTablekey和value都不能爲null,初始值是11,線程安全
4.HashTable是HashMap的前身,全部的方法都使用了synchronized,都是線程安全的,可是性能很低。
5.ConcurrentHashMap 線程也是安全的,經過把整個Map分爲N個Segment,能夠提供相同的線程安全,可是效率提高N倍,默認提高16倍。(讀操做不加鎖,因爲HashEntry的value變量是 volatile的,也能保證讀取到最新的值。)
Hashtable的synchronized是針對整張Hash表的,即每次鎖住整張表讓線程獨佔,ConcurrentHashMap容許多個修改操做併發進行,其關鍵在於使用了鎖分離技術
有些方法須要跨段,好比size()和containsValue(),它們可能須要鎖定整個表而而不只僅是某個段,這須要按順序鎖定全部段,操做完畢後,又按順序釋放全部段的鎖總結:
HaspMap線程不安全,因此多線程的時候要本身加鎖
HashTable和ConcurrentHashMap 都是線程安全的,可是HashTable是鎖住了整張表,ConcurrentHashMap有一個Segment可重入鎖,
鎖分段技術:首先將數據分紅一段一段的存儲,而後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據的時候,其餘段的數據也能被其餘線程訪問。
ConcurrentHashMap提供了與Hashtable和SynchronizedMap不一樣的鎖機制。Hashtable中採用的鎖機制是一次鎖住整個hash表,從而在同一時刻只能由一個線程對其進行操做;而ConcurrentHashMap中則是一次鎖住一個桶。
ConcurrentHashMap默認將hash表分爲16個桶,諸如get、put、remove等經常使用操做只鎖住當前須要用到的桶。這樣,原來只能一個線程進入,如今卻能同時有16個寫線程執行,併發性能的提高是顯而易見的。
1.HashMap使用鍵值對存儲,HashSet僅僅存儲數據
2.一個實現Map接口,一個實現Set接口
3.HaspMap使用put()方法存儲元素,HashSet使用add()添加元素
4.HashMap比較快,由於是使用惟一的鍵來獲取對象 HashSet較HashMap來講比較慢
建議去看看個人文章Java進程線程筆記
建立線程的方式有3種:
1.繼承Thread類
2.實現Runnable接口
3.匿名內部類建立線程
實現:我貼出關鍵代碼
繼承Thread類方式:
package com.StadyJava.day14Thread; import java.lang.Thread; class Music extends Thread{ public void run() { for (int i = 0; i < 50; i++) { System.out.println("聽音樂"+i); } } } public class MusicThread { public static void main(String[] args) { for (int i = 0; i < 50; i++) { System.out.println("打遊戲"+i); if (i == 10) { Music music=new Music(); music.start(); } } } }實現Runnable接口
package com.StadyJava.day14Thread; import java.lang.Runnable; class MusicRun implements Runnable{ public void run() { for (int i = 0; i < 50; i++) { System.out.println("聽音樂"+i); } } } public class MusicRunnable { public static void main(String[] args) { for (int i = 0; i < 50; i++) { System.out.println("打遊戲"+i); if (i == 10) { Runnable music=new MusicRun(); Thread thread=new Thread(music); thread.start(); } } } }匿名內部類方式,這個其實仍是上面的兩種方式,只不過匿名內部類了
package com.StadyJava.day14Thread; import java.lang.Runnable; class MusicRun implements Runnable{ public void run() { for (int i = 0; i < 50; i++) { System.out.println("聽音樂"+i); } } } public class MusicRunnable { public static void main(String[] args) { for (int i = 0; i < 50; i++) { System.out.println("打遊戲"+i); if (i == 10) { //匿名內部類的形式1,使用接口 new Thread(new Runnable() { public void run() { for (int i = 0; i < 50; i++) { System.out.println("聽音樂"+i); } } }).start(); //匿名內部類的形式2,使用繼承類 new Thread(){ public void run() { for (int i = 0; i < 50; i++) { System.out.println("聽音樂"+i); } } }.start(); } } } }繼承Thread類建立線程方式:
- Java中類是單繼承的,若是使用了繼承Thread類建立線程,那麼就 不能再有其餘父類了,這是一個限制
- 從操做上來講,繼承Thread類的方式更簡單,獲取線程名稱也簡單,直接getName就行了。操做簡單,這是優勢
- 從多線程共享資源的方面分析,繼承方式不行,直接3我的,每一個人50個蘋果,沒有實現共享,這是缺點
實現Runnable接口建立線程方式:
- Java中類是能夠實現多接口的,因此實現Runnable接口建立線程,也能夠繼續的去實現其餘接口,也能夠去繼承類,設計優雅,這是優勢
- 從操做上分析,實現接口方式有點複雜,獲取線程名稱的時候,必須使用Thread.currentThread()來獲取當前線程的引用
- 從多線程共享資源的方面上,實現接口方式能夠作到共享資源,3我的去吃50個蘋果,共享資源。這是優勢
綜合上面的區別對比,咱們的這個比賽。看來只能使用實現Runnable接口建立線程的方式來實現了。推薦之後建立線程,都使用實現Runnable接口的方式。
sleep()是線程休眠的意思,方法須要指定等待的時間,須要try catch捕捉異常,例如 Thread.sleep(1000); 線程休眠1秒,sleep方法在休眠的時候,是牢牢的抓住同步鎖不鬆手的,多用於來模擬網絡延遲
join()線程是聯合線程的意思,用處是A線程和B線程一塊兒運行,A必須拿到B的一個結果才能夠執行,這個時候就能夠B.join(),此時A線程就會等待B線程執行完畢再執行
yield()這個是禮讓線程的方法,和sleep()有點像
這個yield方法和sleep方法的區別以下:
1.均可以使得當前處於運行狀態的線程放棄執行的機會,讓給其它線程
2.sleep方法會讓給其它線程,隨機的讓。yield方法會讓給那些優先級高的線程。
3.調用sleep方法後,線程會進入計時等待狀態。調用yield方法後,線程會進入就緒狀態。
如下均可以參考這篇文章:CountDownLatch、CyclicBarrier和 Semaphore
CountDownLatch類位於java.util.concurrent包下,利用它能夠實現相似計數器的功能。好比有一個任務A,它要等待其餘4個任務執行完畢以後才能執行,此時就能夠利用CountDownLatch來實現這種功能了。
CountDownLatch類只提供了一個構造器:
public CountDownLatch(int count) { }; //參數count爲計數值而後下面這3個方法是CountDownLatch類中最重要的方法:
public void await() throws InterruptedException { }; //調用await()方法的線程會被掛起,它會等待直到count值爲0才繼續執行 public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()相似,只不過等待必定的時間後count值還沒變爲0的話就會繼續執行 public void countDown() { }; //將count值減1下面看一個例子你們就清楚CountDownLatch的用法了:
public class Test { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(2); new Thread(){ public void run() { try { System.out.println("子線程"+Thread.currentThread().getName()+"正在執行"); Thread.sleep(3000); System.out.println("子線程"+Thread.currentThread().getName()+"執行完畢"); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); new Thread(){ public void run() { try { System.out.println("子線程"+Thread.currentThread().getName()+"正在執行"); Thread.sleep(3000); System.out.println("子線程"+Thread.currentThread().getName()+"執行完畢"); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); try { System.out.println("等待2個子線程執行完畢..."); latch.await(); System.out.println("2個子線程已經執行完畢"); System.out.println("繼續執行主線程"); } catch (InterruptedException e) { e.printStackTrace(); } } }執行結果:
線程Thread-0正在執行 線程Thread-1正在執行 等待2個子線程執行完畢... 線程Thread-0執行完畢 線程Thread-1執行完畢 2個子線程已經執行完畢 繼續執行主線程
錢
錢
但願成爲技術骨幹,目前暫定Java和大數據處理方向
有沒有加班費?