一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾以後,那麼就具有了兩層語義:
(1) 保證了不一樣線程對這個變量進行操做時的可見性,即一個線程修改了某個變量的值,這新值對其餘線程來講是當即可見的。
(2) 禁止進行指令重排序。
volatile只提供了保證訪問該變量時,每次都是從內存中讀取最新值,並不會使用寄存器緩存該值—每次都會從內存中讀取。
而對該變量的修改,volatile並不提供原子性的保證。
因爲及時更新,極可能致使另外一線程訪問最新變量值,沒法跳出循環的狀況, 多線程下計數器必須使用鎖保護。html
(1) 調用super()必須寫在子類構造方法的第一行,不然編譯不經過。每一個子類構造方法的第一條語句,都是隱含地調用super(),若是父類沒有這種形式的構造函數,那麼在編譯的時候就會報錯。
(2) super()和this()相似, 區別是: super從子類中調用父類的構造方法,this()在同一類內調用其它方法。
(3) super()和this()均需放在構造方法內第一行。
(4) 儘管能夠用this調用一個構造器,但卻不能調用兩個。
(5) this和super不能同時出如今一個構造函數裏面,由於this必然會調用其它的構造函數,其它的構造函數必然也會有super語句的存在,因此在同一個構造函數裏面有相同的語句,就失去了語句的意義,編譯器也不會經過。
(6) this()和super()都指的是對象,因此,均不能夠在static環境中使用。包括:static變量, static方法,static語句塊。
(7) 從本質上講,this是一個指向本對象的指針, 然而super是一個Java關鍵字。程序員
1) 爲何使用內部類?
使用內部類最吸引人的緣由是:每一個內部類都能獨立地繼承一個(接口的)實現,因此不管外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。
使用內部類最大的優勢就在於它可以很是好的解決多重繼承的問題,使用內部類還可以爲咱們帶來以下特性:
(1) 內部類能夠用多個實例,每一個實例都有本身的狀態信息,而且與其餘外圍對象的信息相互獨。
(2) 在單個外圍類中,可讓多個內部類以不一樣的方式實現同一個接口,或者繼承同一個類。
(3) 建立內部類對象的時刻並不依賴於外圍類對象的建立。
(4) 內部類並無使人迷惑的「is-a」關係,他就是一個獨立的實體。
(5) 內部類提供了更好的封裝,除了該外圍類,其餘類都不能訪問。
2) 內部類分類:
(一) 成員內部類:
(1) Inner 類定義在 Outer 類的內部,至關於 Outer 類的一個成員變量的位置,Inner 類可使用任意訪問控制符,如 public 、 protected 、 private 等。
(2) Inner 類中定義的 show() 方法能夠直接訪問 Outer 類中的數據,而不受訪問控制符的影響,如直接訪問 Outer 類中的私有屬性age。
(3) 定義了成員內部類後,必須使用外部類對象來建立內部類對象,而不能直接去 new 一個內部類對象,即:內部類 對象名 = 外部類對象.new 內部類( );
(4) 編譯上面的程序後,會發現產生了兩個.class 文件: Outer.class,Outer$Inner.class{}。
(5) 成員內部類中不能存在任何static 的變量和方法, 能夠定義常量:
● 由於非靜態內部類是要依賴於外部類的實例,而靜態變量和方法是不依賴於對象的,僅與類相關, 簡而言之:在加載靜態域時,根本沒有外部類,所在在非靜態內部類中不能定義靜態域或方法,編譯不經過; 非靜態內部類的做用域是實例級別。
● 常量是在編譯器就肯定的, 放到所謂的常量池了。
★ 外部類是不能直接使用內部類的成員和方法的,可先建立內部類的對象,而後經過內部類的對象來訪問其成員變量和方法;
★ 若是外部類和內部類具備相同的成員變量或方法,內部類默認訪問本身的成員變量或方法,若是要訪問外部類的成員變量,可使用 this 關鍵字,如:Outer.this.name。
(二) 靜態內部類: 是 static 修飾的內部類。
(1) 靜態內部類不能直接訪問外部類的非靜態成員,但能夠經過 new 外部類().成員 的方式訪問
(2) 若是外部類的靜態成員與內部類的成員名稱相同,可經過「類名.靜態成員」訪問外部類的靜態成員;若是外部類的靜態成員與內部類的成員名稱不相同,則可經過「成員名」直接調用外部類的靜態成員。
(3) 建立靜態內部類的對象時,不須要外部類的對象,能夠直接建立 內部類 對象名 = new 內部類()。
(三) 方法內部類:訪問僅限於方法內或者該做用域內。
(1) 局部內部類就像是方法裏面的一個局部變量同樣,是不能有 public、protected、private 以及 static 修飾符的。
(2) 只能訪問方法中定義的 final 類型的局部變量, 由於: 當方法被調用運行完畢以後,局部變量就已消亡了。但內部類對象可能還存在, 直到沒有被引用時纔會消亡。此時就會出現一種狀況,就是內部類要訪問一個不存在的局部變量; 使用final修飾符不只會保持對象的引用不會改變,並且編譯器還會持續維護這個對象在回調方法中的生命週期. 局部內部類並非直接調用方法傳進來的參數,而是內部類將傳進來的參數經過本身的構造器備份到了本身的內部,本身內部的方法調用的實際是本身的屬性而不是外部類方法的參數; 防止被篡改數據,而致使內部類獲得的值不一致。在內部類中的屬性和外部方法的參數二者從外表上看是同一個東西,但實際上卻不是,因此他們二者是能夠任意變化的,也就是說在內部類中我對屬性的改變並不會影響到外部的形參,而然這從程序員的角度來看這是不可行的,畢竟站在程序的角度來看這兩個根本就是同一個,若是內部類該變了,而外部方法的形參卻沒有改變,這是難以理解和不可接受的,因此爲了保持參數的一致性,就規定使用 final來避免形參的不改變。
(四) 匿名內部類:
(1) 匿名內部類是直接使用 new 來生成一個對象的引用;
(2) 對於匿名內部類的使用它是存在一個缺陷的,就是它僅能被使用一次,建立匿名內部類時它會當即建立一個該類的實例,該類的定義會當即消失,因此匿名內部類是不可以被重複使用;
(3) 使用匿名內部類時,咱們必須是繼承一個類或者實現一個接口,可是二者不可兼得,同時也只能繼承一個類或者實現一個接口;
(4) 匿名內部類中是不能定義構造函數的,匿名內部類中不能存在任何的靜態成員變量和靜態方法;
(5) 匿名內部類中不能存在任何的靜態成員變量和靜態方法,匿名內部類不能是抽象的,它必需要實現繼承的類或者實現的接口的全部抽象方法;
(6) 匿名內部類初始化:使用構造代碼塊!利用構造代碼塊可以達到爲匿名內部類建立一個構造器的效果。web
PROPAGATION_REQUIRED--支持當前事務,若是當前沒有事務,就新建一個事務。這是最多見的選擇。
PROPAGATION_SUPPORTS--支持當前事務,若是當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY--支持當前事務,若是當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW--新建事務,若是當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED--以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER--以非事務方式執行,若是當前存在事務,則拋出異常。面試
Servlet的生命週期分爲5個階段:加載、建立、初始化、處理客戶請求、卸載。
(1) 加載:容器經過類加載器使用servlet類對應的文件加載servlet。
(2) 建立:經過調用servlet構造函數建立一個servlet對象。
(3) 初始化:調用init方法初始化。
(4) 處理客戶請求:每當有一個客戶請求,容器會建立一個線程來處理客戶請求。
(5) 卸載:調用destroy方法讓servlet本身釋放其佔用的資源。緩存
Java反射機制概念:Java反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。
Java反射機制主要提供瞭如下功能:
(1) 在運行時判斷任意一個對象所屬的類;
(2) 在運行時構造任意一個類的對象;
(3) 在運行時判斷任意一個類所具備的成員變量和方法;
(4) 在運行時調用任意一個對象的方法;
(5) 生成動態代理。多線程
Struts的工做流程: 在web應用啓動時就會加載初始化ActionServlet, ActionServlet從struts-config.xml文件中讀取配置信息, 把它們存放到各類配置對象, 當ActionServlet接收到一個客戶請求時, 將執行以下流程.
(1) 檢索和用戶請求匹配的ActionMapping實例, 若是不存在, 就返回請求路徑無效信息;
(2) 若是ActionForm實例不存在, 就建立一個ActionForm對象, 把客戶提交的表單數據保存到ActionForm對象中;
(3) 根據配置信息決定是否須要表單驗證. 若是須要驗證, 就調用ActionForm的validate()方法;
(4) 若是ActionForm的validate()方法返回或返回一個不包含ActionMessage的ActuibErrors對象, 就表示表單驗證成功;
(5) ActionServlet根據ActionMapping所包含的映射信息決定將請求轉發給哪一個Action, 若是相應的Action實例不存在, 就先建立這個實例, 而後調用Action的execute()方法;
(6) Action的execute()方法返回一個ActionForward對象, ActionServlet在把客戶請求轉發給ActionForward對象指向的JSP組件;
(7) ActionForward對象指向JSP組件生成動態網頁, 返回給客戶;
爲何要用Struts?
JSP、Servlet、JavaBean技術的出現給咱們構建強大的企業應用系統提供了可能。但用這些技術構建的系統很是的繁亂,因此在此之上,咱們須要一個規則、一個把這些技術組織起來的規則,這就是框架,Struts便應運而生。 基於Struts開發的應用由3類組件構成:控制器組件、模型組件、視圖組件(MVC)。app
1) JAVA的JVM的內存:框架
堆區:
(1) 存儲的所有是對象, 每一個對象都包含一個與之對應的class的信息。(class的目的是獲得操做指令) .
(2) jvm只有一個堆區(heap)被全部線程共享,堆中不存放基本類型和對象引用,只存放對象自己.
棧區:
(1) 每一個線程包含一個棧區,棧中只保存基礎數據類型的對象和自定義對象的引用(不是對象),對象都存放在堆區中.
(2) 每一個棧中的數據(原始類型和對象引用)都是私有的, 其餘棧不能訪問.
(3) 棧分爲3個部分:基本類型變量區、執行環境上下文、操做指令區(存放操做指令).jvm
2) 棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不一樣,Java自動管理棧和堆, 程序員不能直接地設置棧或堆。
3) 棧的優點是, 存取速度比堆要快, 僅次於直接位於CPU中的寄存器。但缺點是, 存在棧中的數據大小與生存期必須是肯定的, 缺少靈活性。另外, 棧數據能夠共享。堆的優點是能夠動態地分配內存大小,生存期也沒必要事先告訴編譯器,Java的垃圾收集器會自動收走這些再也不使用的數據。但缺點是,因爲要在運行時動態分配內存,存取速度較慢。函數
4) 在C語言裏堆(heap)和棧(stack)裏的區別:
heap:是由malloc之類函數分配的空間所在地。地址是由低向高增加的。
stack:是自動分配變量,以及函數調用的時候所使用的一些空間。地址是由高向低減小。
(1) 管理方式不一樣:棧(stack)由編譯器管理;堆(heap)由程序員管理。 (2) 空間大小不一樣:win32中,堆(heap)可達4G;VC中棧默認1M(能夠修改)。 (3) 碎片問題:堆(heap)易產生;棧(stack)不會。 (4) 生長方向不一樣:堆(heap)生長方向是向上的,也就是向着內存增長的方向;棧(stack)相反。 (5) 分配方式不一樣:堆(heap)是動態的,沒有靜態的堆;棧(stack)有兩種:動態和靜態。 (6) 分配效率不一樣:棧(stack),系統提供底層支持,有專門的寄存器存放棧地址,效率高;堆(heap),由庫函數提供支持,效率底。