Java中容易被你忽略的細節(一)

1.wKiom1hlFW6jzC6uAAAerC_XgFQ034.jpg-wh_50在一個程序當中代碼段訪問了同一個對象從單獨的併發的線程當中,那麼這個代碼段叫”臨界區” 

怎麼解決呢:使用同步的機制對臨界區進行保護 


同步的兩種方式:同步塊和同步方法 

對於同步來說都是使用synchronized方法

每一個對象都有一個監視器,或者叫做鎖。

java用監視器機制實現了進程之間的異步執行


2.Struts框架基於MVC模式

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組件生成動態網頁,返回給客戶; 

爲什麼要用: 

JSP、Servlet、JavaBean技術的出現給我們構建強大的企業應用系統提供了可能。但用這些技術構建的系統非常的繁亂,所以在此之上,我們需要一個規則、一個把這些技術組織起來的規則,這就是框架,Struts便應運而生。 

基於Struts開發的應用由3類組件構成:控制器組件、模型組件、視圖組件


3.HttpServletRequest類主要處理:

1.讀取和寫入HTTP頭

2.取得和設置cookies

3.讀取路徑信息

4.標識HTTP會話


4.==  比較的是兩個對象的地址是否相同

equals 比較的是兩個對象的內容是否相同

==比較的是對象的地址,也就是是否是同一個對象;

equal比較的是對象的值。


凡是new出來的就是對象

凡是new出來的就是不同的對象,無論它們長的多麼相似

凡是new出來的都有自己的內存空間


5.構造方法不需要同步化。

定義在接口中的方法默認是public的。

容器保存的是對象的引用。 

構造方法每次都是構造出新的對象,不存在多個線程同時讀寫同一對象中的屬性的問題,所以不需要同步 。

如果父類中的某個方法使用了 synchronized關鍵字,而子類中也覆蓋了這個方法,默認情況下子類中的這個方法並不是同步的,必須顯示的在子類的這個方法中加上 synchronized關鍵字纔可。當然,也可以在子類中調用父類中相應的方法,這樣雖然子類中的方法並不是同步的,但子類調用了父類中的同步方法,也就相當子類方法也同步了。


6.一般關係數據模型和對象數據模型之間有以下對應關係:表對應類,記錄對應對象,表的字段對應類的屬性.


7.自動類型轉換遵循下面的規則:

1.若參與運算的數據類型不同,則先轉換成同一類型,然後進行運算。

2.轉換按數據長度增加的方向進行,以保證精度不降低。例如int型和long型運算時,先把int量轉成long型後再進行運算。

3.所有的浮點運算都是以雙精度進行的,即使僅含float單精度量運算的表達式,也要先轉換成double型,再作運算。

4.char型和short型參與運算時,必須先轉換成int型。

5.在賦值運算中,賦值號兩邊的數據類型不同時,需要把右邊表達式的類型將轉換爲左邊變量的類型。如果右邊表達式的數據類型長度比左邊長時,將丟失一部分數據,這樣會降低精度。

下圖表示了類型自動轉換的規則:

short/char--->int--->unsigned--->long---> double <---float


8.trowable 的子類 error 和 Exception

Exception 包括 非檢查性異常 RuntimeException, 及其子類,即運行時的異常,運行時的異常是代碼的BUG,

和檢查性異常,即非運行時異常,程序在編譯的時候會發現的異常 如: IOException之類,在處理類似文件流的時候,java強制規定必須處理可能遇到的文件流異常。

runtimeException是運行時的異常,在運行期間拋出異常的超類,程序可以選擇是否try-catch處理。

其他的檢查性異常(非運行時的異常,如IOException),是必須try-catch的,否則程序在編譯的時候就會發現錯誤。


9.Java共有六個包裝類,分別是Boolean、Character、Integer、Long、Float和Double,從字面上我們就能夠看出他們分別對應於 boolean、char、int、long、float和double。而String和Date本身就是類,因此沒有包裝類。.


10stringbuffer與stringbuilder的區別:

1.  在執行速度方面的比較:StringBuilder >  StringBuffer   

2.  StringBuffer與StringBuilder,他們是字符串變量,是可改變的對象,每當我們用它們對字符串做操作時,實際上是在一個對象上操作的,不像String一樣創建一些對象進行操作,所以速度就快了。

3.  StringBuilder:線程非安全的

  StringBuffer:線程安全的

    當我們在字符串緩衝去被多個線程使用是,JVM不能保證StringBuilder的操作是安全的,雖然他的速度最快,但是可以保證StringBuffer是可以正確操作的。當然大多數情況下就是我們是在單線程下進行的操作,所以大多數情況下是建議用StringBuilder而不用StringBuffer的,就是速度的原因。


對於三者使用的總結:

1.如果要操作少量的數據用 = String

2.單線程操作字符串緩衝區下操作大量數據 = StringBuilder

3.多線程操作字符串緩衝區下操作大量數據 = StringBuffer


11.類中聲明的變量有默認初始值;方法中聲明的變量沒有默認初始值,必須在定義時初始化,否則在訪問該變量時會出錯。

boolean類型默認值是false


12.不管是靜態方法還是非靜態方法,都需要調用後執行,其執行的次序和在類裏聲明的次序無關,區別是靜態方法是“class.method"方式執行,非靜態方法是"object.method"方式執行,即後者需要創建一個對象。

靜態成員變量(也稱類變量)先於非靜態成員變量初始化,靜態成員變量在類第一次加載時初始化,所有對象共享一份靜態成員變量,非靜態成員變量則在對象創建時初始化.

Java中經常有一些靜態塊,這是用來在生成類之前進行的初始化,無論java還C++語言中的static,都是最先初始化好的。結構如下: 

static { 

靜態語句代碼塊 


非靜態語句代碼塊 

異同點 

相同點:都是在JVM加載類時且在構造方法執行之前執行,在類中都可以定義多個,一般在代碼塊中對一些static變量進行賦值。 

不同點:靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊-->非靜態代碼塊-->構造函數)。 

靜態代碼塊只在第一次new(或者只要訪問了就)執行一次,之後不在執行,而非靜態代碼塊在每new一次都會執行一次,跟構造函數一樣。非靜態代碼塊可以在普通方法中定義(個人感覺作用不大);而靜態代碼塊不行。 



1、靜態代碼塊是在類加載時自動執行的,非靜態代碼塊在創建對象自動執行的代碼,不創建對象不執行該類的非靜態代碼塊。 順序: 靜態代碼塊--》非靜態代碼塊--》類構造函數。 

2、在靜態方法裏面只能直接調用同類中其他的靜態成員(包括變量和方法),而不能直接訪問類中的非靜態成員。因爲對於非靜態的方法和變量,需要先創建類的實例對象後方可使用,而靜態方法在使用前不用創建任何對象。 

3、如果某些代碼必須要在項目啓動時候就執行,我們可以採用靜態代碼塊,這種代碼是主動執行的;需要在項目啓動的時候就初始化.


在不創建對象的情況下,其他程序來調用的時候,需要使用靜態方法,此時代碼是被動執行的。 

區別:靜態代碼塊是自動執行的; 

靜態方法是被調用的時候才執行的; 

作用:靜態代碼塊可以用來初始化一些項目最常用的變量和對象;靜態方法可以用作不創建對象也可以能需要執行的代碼。


13.abstract class和interface的區別:

1.抽象類可以有構造方法,接口中不能有構造方法。

2.抽象類中可以有普通成員變量,接口中沒有普通成員變量。

3.一個類可以實現多個接口,但只能繼承一個抽象類。

抽象類

特點:

抽象類中可以構造方法

抽象類中可以存在普通屬性,方法,靜態屬性和方法。

抽象類中可以存在抽象方法。

如果一個類中有一個抽象方法,那麼當前類一定是抽象類;抽象類中不一定有抽象方法。

抽象類中的抽象方法,需要有子類實現,如果子類不實現,則子類也需要定義爲抽象的。

接口

特點:

在接口中只有方法的聲明,沒有方法體。

在接口中只有常量,因爲定義的變量,在編譯的時候都會默認加上

public static final 

在接口中的方法,永遠都被public來修飾。

接口中沒有構造方法,也不能實例化接口的對象。

接口可以實現多繼承

接口中定義的方法都需要有實現類來實現,如果實現類不能實現接口中的所有方法

則實現類定義爲抽象類。


14.1.線程通過調用對象的synchronized方法可獲得對象的互斥鎖定。

2.線程調度算法是平臺獨立的。

3.通過繼承Thread類或實現Runnable接口來創建線程。

線程調度分爲協同式調度和搶佔式調度,Java使用的是搶佔式調度,也就是每個線程將由操作系統來分配執行時間,線程的切換不由線程本身來決定(協同式調度)。這就是平臺獨立的原因。


15.方法的重寫(override)兩同兩小一大原則:

方法名相同,參數類型相同

子類返回類型小於等於父類方法返回類型,

子類拋出異常小於等於父類方法拋出異常,

子類訪問權限大於等於父類方法訪問權限。


16.1、boolean類型只有兩個直接量值:true和false. 

2、除成員變量會有默認初始值外,其他變量必須在第一次使用之前初始化

boolean類型的默認值是false;

其餘的7種基本類型默認值:

byte是 (byte)0;

short是 (short)0;

int是 0;

long是 0L;

float 是0.0f;

double 是0.0d;

char是 \u0000;

String是null;


17.servlet中init,service,destroy方法描述:

init方法:是在servlet實例創建時調用的方法,用於創建或打開任何與servlet相關的資源和初始 化servlet的狀態,Servlet規範保證調用init方法前不會處理任

何請求.init()方法是servlet生命的起點。

一旦加載了某個servlet,服務器將立即調用它的init()方法.

service方法:是servlet真正處理客戶端傳過來的請求的方法,由web容器調用, 根據HTTP請求方法(GET、POST等),將請求分發到doGet、doPost等方法 

destory方法:是在servlet實例被銷燬時由web容器調用。

Servlet規範確保在destroy方法調用之前所有請求的處理均完成,

需要覆蓋destroy方法的情況:釋放任何在init方法中打開的與servlet相關的資源存

儲servlet的狀態。destroy()方法標誌servlet生命週期的結束。


18.類加載過程

類從被加載到虛擬機內存中開始,到卸載出內存爲止,它的整個生命週期包括:加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸載(Unloading)7個階段。其中準備、驗證、解析3個部分統稱爲連接(Linking)。

加載、驗證、準備、初始化和卸載這5個階段的順序是確定的,類的加載過程必須按照這種順序按部就班地開始,而解析階段則不一定:它在某些情況下可以在初始化階段之後再開始,這是爲了支持Java語言的運行時綁定(也稱爲動態綁定或晚期綁定)。

來源:http://www.importnew.com/18548.html


19.java不允許單獨的方法,過程或函數存在,需要隸屬於某一類中。

java語言中的方法屬於對象的成員,而不是類的成員。不過,其中靜態方法屬於類的成員。

Java語言中的方法必定隸屬於某一類(對象),調用方法與過程或函數相同。


20.Java 提供的事件處理模型是一種人機交互模型。它有三個基本要素:

1) 事件源(Event Source):即事件發生的場所,就是指各個組件,如按鈕等,點擊按鈕其實就是組件上發生的一個事件;

2) 事件(Event):事件封裝了組件上發生的事情,比如按鈕單擊、按鈕鬆開等等;

3) 事件監聽器(Event Listener):負責監聽事件源上發生的特定類型的事件,當事件到來時還必須負責處理相應的事件;


21.在WEB開發中實現會話跟蹤的技術有:session,cookie,地址重寫,隱藏域。

1.Cookies

      Cookies是使用最廣泛的會話跟蹤機制,Cookies是有服務器創建,並把Cookies信息保存在用戶機器上的硬盤上,下次用戶再次訪問該站點服 務器的時候,保存在用戶機器上硬盤的Cookies信息就被送回給服務器。一般Cookies一般不多於4KB,且用戶的敏感信息如信用卡賬號密碼不應該 保存在Cookies中。

2.URL重寫

       URL重用戶在每個URL結尾附加標識回話的數據,與標識符關聯的服務器保存有關與會話的數據,如我們訪問某個新聞的時候,在地址欄我們一般會看到這樣的 信息:http://www.XXX.com/news?id=??,通常的話id後面的問號表示該條新聞在後臺數據庫中的新聞表的id。URL重寫能夠 在客戶端停用cookies或者不支持cookies的時候仍然能夠發揮作用。

3.隱藏表單域

      通常,在表單中我們使用隱藏表單域的時候會有這麼一句代碼:<input type=”hidden” name=”XXX”  value=”XXX”/>。通過給type屬性賦值爲hidden值來實現隱藏,這樣用戶在瀏覽的時候看不到這行代碼的數據,但是當用戶通過查看 源代碼還是可以看到的。

4.Session機制

       這個機制要慎用,特別是對於訪問量很大的站點,因爲這種機制是吧Session信息保存在服務器端。如果訪問量特別大的話,對於服務器的承受力的要求有多高是可想而知的。


Cookie(結合session使用)

可以使用 cookie 存儲購物會話的 ID;在後續連接中,取出當前的會話 ID,並使用這個 ID 從服務器上的查找表(lookup table)中提取出會話的相關信息。 以這種方式使用 cookie 是一種絕佳的解決方案,也是在處理會話時最常使用的方式。但是,sevlet 中最好有一種高級的 API 來處理所有這些任務,以及下面這些冗長乏味的任務:從衆多的其他cookie中(畢竟可能會存在許多cookie)提取出存儲會話標識符的 cookie;確定空閒會話什麼時候過期,並回收它們;將散列表與每個請求關聯起來;生成惟一的會話標識符。

URL 重寫

採用這種方式時,客戶程序在每個URL的尾部添加一些額外數據。這些數據標識當前的會話,服務器將這個標識符與它存儲的用戶相關數據關聯起來。 URL重寫是比較不錯的會話跟蹤解決方案,即使瀏覽器不支持 cookie 或在用戶禁用 cookie 的情況下,這種方案也能夠工作。URL 重寫具有 cookie 所具有的同樣缺點,也就是說,服務器端程序要做許多簡單但是冗長乏味的處理任務。即使有高層的 API 可以處理大部分的細節,仍須十分小心每個引用你的站點的 URL ,以及那些返回給用戶的 URL。即使通過間接手段,比如服務器重定向中的 Location 字段,都要添加額外的信息。這種限制意味着,在你的站點上不能有任何靜態 HTML 頁面(至少靜態頁面中不能有任何鏈接到站點動態頁面的鏈接)。因此,每個頁面都必須使用 servlet 或 JSP 動態生成。即使所有的頁面都動態生成,如果用戶離開了會話並通過書籤或鏈接再次回來,會話的信息也會丟失,因爲存儲下來的鏈接含有錯誤的標識信息。

隱藏的表單域

HTML 表單中可以含有如下的條目:<input type="hidden" name="session" value="a1234">

這個條目的意思是:在提交表單時,要將指定的名稱和值自動包括在 GET 或 POST 數據中。這個隱藏域可以用來存儲有關會話的信息,但它的主要缺點是:僅當每個頁面都是由表單提交而動態生成時,才能使用這種方法。單擊常規的超文本鏈接並不產生表單提交,因此隱藏的表單域不能支持通常的會話跟蹤,只能用於一系列特定的操作中,比如在線商店的結賬過程。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章