接口和抽象類的差別是什麼?
Java提供和支援建立抽象類和接口。它們的實作有共同點,不同點在于:
接口中所有的方法隐含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。
類可以實作很多個接口,但是隻能繼承一個抽象類
類如果要實作一個接口,它必須要實作接口聲明的所有方法。但是,類可以不實作抽象類聲明的所有方法,當然,在這種情況下,類也必須得聲明成是抽象的。
抽象類可以在不提供接口方法實作的情況下實作接口。
Java接口中聲明的變量預設都是final的。抽象類可以包含非final的變量。
Java接口中的成員函數預設是public的。抽象類的成員函數可以是private,protected或者是public。
接口是絕對抽象的,不可以被執行個體化。抽象類也不可以被執行個體化,但是,如果它包含main方法的話是可以被調用的。
1.abstract class 在 Java 語言中表示的是一種繼承關系,一個類隻能使用一次繼承關系。但是,一個類卻可以實作多個interface。
2.在abstract class 中可以有自己的資料成員,也可以有非abstarct的成員方法,而在interface中,隻能夠有靜态的不能被修改的資料成員(也就是必須是static final的,不過在 interface中一般不定義資料成員),所有的成員方法都是abstract的。
3.abstract class和interface所反映出的設計理念不同。其實abstract class表示的是"is-a"關系,interface表示的是"like-a"關系。
4.實作抽象類和接口的類必須實作其中的所有方法。抽象類中可以有非抽象方法。接口中則不能有實作方法。
5.接口中定義的變量預設是public static final 型,且必須給其初值,是以實作類中不能重新定義,也不能改變其值。
6.抽象類中的變量預設是 friendly 型,其值可以在子類中重新定義,也可以重新指派。
7.接口中的方法預設都是 public,abstract 類型的。
Java虛拟機是一個可以執行Java位元組碼的虛拟機程序。Java源檔案被編譯成能被Java虛拟機執行的位元組碼檔案。
Java被設計成允許應用程式可以運作在任意的平台,而不需要程式員為每一個平台單獨重寫或者是重新編譯。Java虛拟機讓這個變為可能,因為它知道底層硬體平台的指令長度和其他特性。
Java運作時環境(JRE)是将要執行Java程式的Java虛拟機。它同時也包含了執行applet需要的浏覽器插件。Java開發工具包(JDK)是完整的Java軟體開發包,包含了JRE,編譯器和其他的工具(比如:JavaDoc,Java調試器),可以讓開發者開發、編譯、執行Java應用程式。
“static”關鍵字表明一個成員變量或者是成員方法可以在沒有所屬的類的執行個體變量的情況下被通路。
Java中static方法不能被覆寫,因為方法覆寫是基于運作時動态綁定的,而static方法是編譯時靜态綁定的。static方法跟類的任何執行個體都不相關,是以概念上不适用。
關于覆寫的一些舉例:
(1) 父類和子類中同名的靜态類
class Parent{
public static void fun(){
System.out.println("Parent fun()");
}
}
class Child extends Parent{
System.out.println("Child fun()");
結論:static方法不能被覆寫,父類和子類中允許有同樣的static方法!
(2)父類和子類中同樣的private方法
private void xun(){
System.out.println("Parent xun()");
class Child extends Parent
System.out.println("Child xun()");
結論:private方法不能被覆寫,父類和子類中允許有同樣的private方法!
(3)父類中有public final方法gun(),子類中不能有同名同參的gun()方法
public final void gun(){
System.out.println("Parent gun()");
public void gun(){
System.out.println("Child gun()");
(4)這樣寫編譯是沒有錯的
private final void gun(){
static變量在Java中是屬于類的,它在所有的執行個體中的值是一樣的。當類被Java虛拟機載入的時候,會對static變量進行初始化。如果你的代碼嘗試不用執行個體來通路非static的變量,編譯器會報錯,因為這些變量還沒有被建立出來,還沒有跟任何執行個體關聯上。
Java語言支援的8中基本資料類型是:
byte
short
int
long
float
double
boolean
char
自動裝箱是Java編譯器在基本資料類型和對應的對象包裝類型之間做的一個轉化。比如:把int轉化成Integer,double轉化成double,等等。反之就是自動拆箱。
Java中的方法重載發生在同一個類裡面兩個或者是多個方法的方法名相同但是參數不同的情況。與此相對,方法覆寫是說子類重新定義了父類的方法。方法覆寫必須有相同的方法名,參數清單和傳回類型。覆寫者可能不會限制它所覆寫的方法的通路。
Java中類不支援多繼承,隻支援單繼承(即一個類隻有一個父類)。 但是java中的接口支援多繼承,,即一個子接口可以有多個父接口。(接口的作用是用來擴充對象的功能,一個子接口繼承多個父接口,說明子接口擴充了多個功能,當類實作接口時,類就擴充了相應的功能)。
對象被值傳遞,意味着傳遞了對象的一個副本。是以,就算是改變了對象副本,也不會影響源對象的值。
對象被引用傳遞,意味着傳遞的并不是實際的對象,而是對象的引用。是以,外部對引用對象所做的改變會反映到所有的對象上。
Java線程
程序是執行着的應用程式,而線程是程序内部的一個執行序列。一個程序可以有多個線程。線程又叫做輕量級程序。程序擁有一個完整的虛拟位址空間,不依賴于線程而獨立存在;反之,線程是程序的一部分,沒有自己的位址空間,與程序内的其他線程一起共享配置設定給該程序的所有資源。 程序,是并發執行的程式在執行過程中配置設定和管理資源的基本機關。
有三種方式可以用來建立線程:
繼承Thread類
實作Runnable接口
應用程式可以使用Executor架構來建立線程池
實作Runnable接口這種方式更受歡迎,因為這不需要繼承Thread類。在應用設計中已經繼承了别的對象的情況下,這需要多繼承(而Java不支援多繼承),隻能實作接口。同時,線程池也是非常高效的,很容易實作和使用。
線程在執行過程中,可以處于下面幾種狀态:
就緒(Runnable):線程準備運作,不一定立馬就能開始執行。
運作中(Running):程序正在執行線程的代碼。
等待中(Waiting):線程處于阻塞的狀态,等待外部的處理結束。
睡眠中(Sleeping):線程被強制睡眠。
I/O阻塞(Blocked on I/O):等待I/O操作完成。
同步阻塞(Blocked on Synchronization):等待擷取鎖。
死亡(Dead):線程完成了執行。
集合類接口指定了一組叫做元素的對象。集合類接口的每一種具體的實作類都可以選擇以它自己的方式對元素進行儲存和排序。有的集合類允許重複的鍵,有些不允許。
Java集合類提供了一套設計良好的支援對一組對象進行操作的接口和類。Java集合類裡面最基本的接口有:
Collection:代表一組對象,每一個對象都是它的子元素。
Set:不包含重複元素的Collection。
List:有順序的collection,并且可以包含重複元素。
Map:可以把鍵(key)映射到值(value)的對象,鍵不能重複。
克隆(cloning)或者是序列化(serialization)的語義和含義是跟具體的實作相關的。是以,應該由集合類的具體實作來決定如何被克隆或者是序列化。
Iterator接口提供了很多對集合元素進行疊代的方法。每一個集合類都包含了可以傳回疊代器執行個體的疊代方法。疊代器可以在疊代的過程中删除底層集合的元素。
下面列出了他們的差別:
Iterator可用來周遊Set和List集合,但是ListIterator隻能用來周遊List。
Iterator對集合隻能是前向周遊,ListIterator既可以前向也可以後向。
ListIterator實作了Iterator接口,并包含其他的功能,比如:增加元素,替換元素,擷取前一個和後一個元素的索引,等等。
Iterator的安全失敗是基于對底層集合做拷貝,是以,它不受源集合上修改的影響。java.util包下面的所有的集合類都是快速失敗的,而java.util.concurrent包下面的所有的類都是安全失敗的。快速失敗的疊代器會抛出ConcurrentModificationException異常,而安全失敗的疊代器永遠不會抛出這樣的異常。
Java中的HashMap是以鍵值對(key-value)的形式存儲元素的。HashMap需要一個hash函數,它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素。當調用put()方法的時候,HashMap會計算key的hash值,然後把鍵值對存儲在集合中合适的索引上。如果key已經存在了,value會被更新成新值。HashMap的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。
Java中的HashMap使用hashCode()和equals()方法來确定鍵值對的索引,當根據鍵擷取值的時候也會用到這兩個方法。如果沒有正确的實作這兩個方法,兩個不同的鍵可能會有相同的hash值,是以,可能會被集合認為是相等的。而且,這兩個方法也用來發現重複元素。是以這兩個方法的實作對HashMap的精确性和正确性是至關重要的。
HashMap和Hashtable都實作了Map接口,是以很多特性非常相似。但是,他們有以下不同點:
HashMap允許鍵和值是null,而Hashtable不允許鍵或者值是null。
Hashtable是同步的,而HashMap不是。是以,HashMap更适合于單線程環境,而Hashtable适合于多線程環境。
HashMap提供了可供應用疊代的鍵的集合,是以,HashMap是快速失敗的。另一方面,Hashtable提供了對鍵的列舉(Enumeration)。
一般認為Hashtable是一個遺留的類。
在JDK中,檢視集合有很多關于快速失敗的描述:注意,此實作不是同步的。如果多個線程同時通路一個哈希映射,而其中至少一個線程從結構上修改了該映射,則它必須 保持外部同步。(結構上的修改是指添加或删除一個或多個映射關系的任何操作;僅改變與執行個體已經包含的鍵關聯的值不是結構上的修改。)在疊代器建立之後,如果從結構上對映射進行修改,除非通過疊代器本身的 remove 方法,其他任何時間任何方式的修改,疊代器都将抛出 ConcurrentModificationException。是以,面對并發的修改,疊代器很快就會完全失敗,而不冒在将來不确定的時間發生任意不确定行為的風險。快速失敗:對于非并發集合來說,在其進行疊代時,例如iterator疊代時,iterator是另起一個線程,若有其他線程(如Collection)進行結構修改(修改了增減了集合中的内容),這個疊代會馬上感覺到,并且立即抛出 ConcurrentModificationException 異常,而不是疊代完成後才告訴你出錯了,引起快速失敗。若用iterator進行修改則不會出現這個問題,如iterator.move();也就是說涉及到了多個線程間的同步問題。
下面列出了Array和ArrayList的不同點:
Array可以包含基本類型和對象類型,ArrayList隻能包含對象類型。
Array大小是固定的,ArrayList的大小是動态變化的。
ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
對于基本類型資料,集合使用自動裝箱來減少編碼工作量。但是,當處理固定大小的基本資料類型的時候,這種方式相對比較慢。
ArrayList和LinkedList都實作了List接口,他們有以下的不同點:
ArrayList是基于索引的資料接口,它的底層是數組。它可以以O(1)時間複雜度對元素進行随機通路。與此對應,LinkedList是以元素清單的形式存儲它的資料,每一個元素都和它的前一個和後一個元素連結在一起,在這種情況下,查找某個元素的時間複雜度是O(n)。
相對于ArrayList,LinkedList的插入,添加,删除操作速度更快,因為當元素被添加到集合任意位置的時候,不需要像數組那樣重新計算大小或者是更新索引。
LinkedList比ArrayList更占記憶體,因為LinkedList為每一個節點存儲了兩個引用,一個指向前一個元素,一個指向下一個元素。
也可以參考ArrayList vs. LinkedList。
Java提供了隻包含一個compareTo()方法的Comparable接口。這個方法可以個給兩個對象排序。具體來說,它傳回負數,0,正數來表明輸入對象小于,等于,大于已經存在的對象。
Java提供了包含compare()和equals()兩個方法的Comparator接口。compare()方法用來給兩個輸入參數排序,傳回負數,0,正數表明第一個參數是小于,等于,大于第二個參數。equals()方法需要一個對象作為參數,它用來決定輸入參數是否和comparator相等。隻有當輸入參數也是一個comparator并且輸入參數和目前comparator的排序結果是相同的時候,這個方法才傳回true。
大O符号描述了當資料結構裡面的元素增加的時候,算法的規模或者是性能在最壞的場景下有多麼好。
大O符号也可用來描述其他的行為,比如:記憶體消耗。因為集合類實際上是資料結構,我們一般使用大O符号基于時間,記憶體和性能來選擇最好的實作。大O符号可以對大量資料的性能給出一個很好的說明。
HashSet是由一個hash表來實作的,是以,它的元素是無序的。add(),remove(),contains()方法的時間複雜度是O(1)。
另一方面,TreeSet是由一個樹形的結構來實作的,它裡面的元素是有序的。是以,add(),remove(),contains()方法的時間複雜度是O(logn)。
垃圾收集器(Garbage Collectors)
垃圾回收的目的是識别并且丢棄應用不再使用的對象來釋放和重用資源。
這兩個方法用來提示JVM要進行垃圾回收。但是,立即開始還是延遲進行垃圾回收是取決于JVM的。
在釋放對象占用的記憶體之前,垃圾收集器會調用對象的finalize()方法。一般建議在該方法中釋放對象持有的資源。
不會,在下一個垃圾回收周期中,這個對象将是可被回收的。
當對象對目前使用這個對象的應用程式變得不可觸及的時候,這個對象就可以被回收了。
JVM的堆是運作時資料區,所有類的執行個體和數組都是在堆上配置設定記憶體。它在JVM啟動的時候被建立。對象所占的堆記憶體是由自動記憶體管理系統也就是垃圾收集器回收。
堆記憶體是由存活和死亡的對象組成的。存活的對象是應用可以通路的,不會被垃圾回收。死亡的對象是應用不可通路尚且還沒有被垃圾收集器回收掉的對象。一直到垃圾收集器把這些對象回收掉之前,他們會一直占據堆記憶體空間。
Java中有兩種異常:受檢查的(checked)異常和不受檢查的(unchecked)異常。不受檢查的異常不需要在方法或者是構造函數上聲明,就算方法或者是構造函數的執行可能會抛出這樣的異常,并且不受檢查的異常可以傳播到方法或者是構造函數的外面。相反,受檢查的異常必須要用throws語句在方法或者是構造函數上聲明。這裡有Java異常處理的一些小建議。檢查異常:(編譯器必須處理的異常)除error,runtimeexception及其子類以外,其他的Exception類及其子類都是檢查異常。該異常特點是java編譯器檢查,即當程式中出現異常時,要麼用try-catch語句捕獲,要麼用throws子句聲明抛出,否則編譯不通過。 非檢查異常:(編譯器不要求處置的異常),包括運作時異常(runtimeexception及其子類)和錯誤(error)
Exception和Error都是Throwable的子類。Exception用于使用者程式可以捕獲的異常情況。Error定義了不期望被使用者程式捕獲的異常。
throw關鍵字用來在程式中明确的抛出異常,相反,throws語句用來表明方法不能處理的異常。每一個方法都必須要指定哪些異常不能處理,是以方法的調用者才能夠確定處理可能發生的異常,多個異常是用逗号分隔的。
45.異常處理的時候,finally代碼塊的重要性是什麼?(譯者注:作者标題的序号弄錯了)
無論是否抛出異常,finally代碼塊總是會被執行。就算是沒有catch語句同時又抛出異常的情況下,finally代碼塊仍然會被執行。最後要說的是,finally代碼塊主要用來釋放資源,比如:I/O緩沖區,資料庫連接配接。
Exception對象會在下一個垃圾回收過程中被回收掉。
無論是否抛出異常,finally代碼塊都會執行,它主要是用來釋放應用占用的資源。finalize()方法是Object類的一個protected方法,它是在對象被垃圾回收之前由Java虛拟機來調用的。
Java小應用程式(Applet)
java applet是能夠被包含在HTML頁面中并且能被啟用了java的用戶端浏覽器執行的程式。Applet主要用來建立動态互動的web應用程式。
applet可以經曆下面的狀态:
Init:每次被載入的時候都會被初始化。
Start:開始執行applet。
Stop:結束執行applet。
Destroy:解除安裝applet之前,做最後的清理工作。
applet是運作在啟用了java的浏覽器中,Java應用程式是可以在浏覽器之外運作的獨立的Java程式。但是,它們都需要有Java虛拟機。
進一步來說,Java應用程式需要一個有特定方法簽名的main函數來開始執行。Java applet不需要這樣的函數來開始執行。
最後,Java applet一般會使用很嚴格的安全政策,Java應用一般使用比較寬松的安全政策。
布局管理器用來在容器中組織元件。1,BorderLayout 2,FlowLayout 3,GridLayout 4,GridBagLayout 5,CardLayout 6,BoxLayout
GridBagLayout裡面的元素是按照網格進行布局的。不同大小的元素可能會占據網格的多于1行或一列。是以,行數和列數可以有不同的大小。
Scrollbar是一個元件,不是容器。而ScrollPane是容器。ScrollPane自己處理滾動事件。
隻有3個線程安全的方法: repaint(), revalidate(), and invalidate()。
Canvas, Frame, Panel,和Applet支援重繪。
Frame類繼承了Window類,它定義了一個可以有菜單欄的主應用視窗。
事件監聽器接口定義了對特定的事件,事件處理器必須要實作的方法。事件擴充卡給事件監聽器接口提供了預設的實作。
GUI元件可以處理它自己的事件,隻要它實作相對應的事件監聽器接口,并且把自己作為事件監聽器。
Java使用布局管理器以一種一緻的方式在所有的視窗平台上擺放元件。因為布局管理器不會群組件的絕對大小和位置相綁定,是以他們能夠适應跨視窗系統的特定平台的不同。
Java中的Swing元件使用了MVC(視圖-模型-控制器)設計模式。
JDBC是允許使用者在不同資料庫之間做選擇的一個抽象層。JDBC允許開發者用JAVA寫資料庫應用程式,而不需要關心底層特定資料庫的細節。
JDBC驅動提供了特定廠商對JDBC API接口類的實作,驅動必須要提供java.sql包下面這些類的實作:Connection, Statement, PreparedStatement,CallableStatement, ResultSet和Driver。
Class.forName("com.mysql.jdbc.Driver"); //加載mysq驅動
conn = DriverManager.getConnection(url,user,password);
stmt = conn.createStatement();
類裝載指通過解析類(或者接口)的位元組碼檔案來建構代表這個類(或是這個接口)的執行個體的過程。有些像根據藍圖制作一個産品一樣的概念。類裝載有如下的兩種方式:
//第1種方式
Class c1 = Class.forName (String className);
//第2種方式
ClassLoader cl = new ClassLoader();
Class c1 = cl.loadClass(String className, boolean resolve );
其中,Class.forName()完成了類裝載、連接配接以及初始化(激活類的靜态變量的初始化Java代碼和靜态Java代碼塊。)
在JDBC連結資料庫中的應用
在JDBC中加載驅動類時(Class.forName(“com.mysql.jdbc.Driver”),如果換成getClass().getClassLoader().loadClass(“com.mysql.jdbc.Driver”),就不行,因為它隻是向jvm裝載了Driver的類資訊,但是并沒有進行類的初始化,也就不能執行相應的操作,因為Driver是需要被初始化才能使用的。
PreparedStatements是預編譯的,是以,性能會更好。同時,不同的查詢參數值,PreparedStatement可以重用。
String sql= "insert into user (name,pwd) values(?,?)"; //sql語句不再采用拼接方式,應用占位符問号的方式寫sql語句。
ps=conn.prepareStatement(sql); ps.setString(1, user.getName()); ps.setString(2, user.getPwd()); //對占位符設定值,占位符順序從1開始,第一個參數是占位符的位置,第二個參數是占位符的值。
像打開關閉資料庫連接配接這種和資料庫的互動可能是很費時的,尤其是當用戶端數量增加的時候,會消耗大量的資源,成本是非常高的。可以在應用伺服器啟動的時候建立很多個資料庫連接配接并維護在一個池中。連接配接請求由池中的連接配接提供。在連接配接使用完畢以後,把連接配接歸還到池中,以用于滿足将來更多的請求。資料庫連接配接池負責配置設定,管理和釋放資料庫連接配接,它允許應用程式重複使用一個現有的資料庫連接配接,而不是重建立立一個。資料庫連接配接池在初始化時将建立一定數量的資料庫連接配接放到連接配接池中, 這些資料庫連接配接的數量是由最小資料庫連接配接數來設定的.無論這些資料庫連接配接是否被使用,連接配接池都将一直保證至少擁有這麼多的連接配接數量.連接配接池的最大資料庫連接配接數量限定了這個連接配接池能占有的最大連接配接數,當應用程式向連接配接池請求的連接配接數超過最大連接配接數量時,這些請求将被加入到等待隊列中。
參考:http://www.cnblogs.com/xdp-gacl/p/4002804.html
Servlet是用來處理用戶端請求并産生動态網頁内容的Java類。Servlet主要是用來處理或者是存儲HTML表單送出的資料,産生動态内容,在無狀态的HTTP協定下管理狀态資訊。
所有的Servlet都必須要實作的核心的接口是javax.servlet.Servlet。每一個Servlet都必須要直接或者是間接實作這個接口,或者是繼承javax.servlet.GenericServlet或者javax.servlet.http.HTTPServlet。最後,Servlet使用多線程可以并行的為多個請求服務。
Applet是運作在用戶端主機的浏覽器上的用戶端Java程式。而Servlet是運作在web伺服器上的服務端的元件。applet可以使用使用者界面類,而Servlet沒有使用者界面,相反,Servlet是等待用戶端的HTTP請求,然後為請求産生響應。
GenericServlet是一個通用的協定無關的Servlet,它實作了Servlet和ServletConfig接口。繼承自GenericServlet的Servlet應該要覆寫service()方法。最後,為了開發一個能用在網頁上服務于使用HTTP協定請求的Servlet,你的Servlet必須要繼承自HttpServlet。
對每一個用戶端的請求,Servlet引擎載入Servlet,調用它的init()方法,完成Servlet的初始化。然後,Servlet對象通過為每一個請求單獨調用service()方法來處理所有随後來自用戶端的請求,最後,調用Servlet(譯者注:這裡應該是Servlet而不是server)的destroy()方法把Servlet删除掉。
doGet:GET方法會把名值對追加在請求的URL後面。因為URL對字元數目有限制,進而限制了用在用戶端請求的參數值的數目。并且請求中的參數值是可見的,是以,敏感資訊不能用這種方式傳遞。
doPOST:POST方法通過把請求參數值放在請求體中來克服GET方法的限制,是以,可以發送的參數的數目是沒有限制的。最後,通過POST請求傳遞的敏感資訊對外部用戶端是不可見的。
Web應用程式是對Web或者是應用伺服器的動态擴充。有兩種類型的Web應用:面向表現的和面向服務的。面向表現的Web應用程式會産生包含了很多種标記語言和動态内容的互動的web頁面作為對請求的響應。而面向服務的Web應用實作了Web服務的端點(endpoint)。一般來說,一個Web應用可以看成是一組安裝在伺服器URL名稱空間的特定子集下面的Servlet的集合。
ServletRequest類可以找出用戶端機器的IP位址或者是主機名。getRemoteAddr()方法擷取用戶端主機的IP位址,getRemoteHost()可以擷取主機名。
HTTP響應由三個部分組成:
狀态碼(Status Code):描述了響應的狀态。可以用來檢查是否成功的完成了請求。請求失敗的情況下,狀态碼可用來找出失敗的原因。如果Servlet沒有傳回狀态碼,預設會傳回成功的狀态碼HttpServletResponse.SC_OK。
HTTP頭部(HTTP Header):它們包含了更多關于響應的資訊。比如:頭部可以指定認為響應過期的過期日期,或者是指定用來給使用者安全的傳輸實體内容的編碼格式。如何在Serlet中檢索HTTP的頭部看這裡。
主體(Body):它包含了響應的内容。它可以包含HTML代碼,圖檔,等等。主體是由傳輸在HTTP消息中緊跟在頭部後面的資料位元組組成的。
抽象是把想法從具體的執行個體中分離出來的步驟,是以,要根據他們的功能而不是實作細節來建立類。Java支援建立隻暴漏接口而不包含方法實作的抽象的類。這種抽象技術的主要目的是把類的行為和實作細節分離開。
抽象和封裝是互補的概念。一方面,抽象關注對象的行為。另一方面,封裝關注對象行為的細節。一般是通過隐藏對象内部狀态資訊做到封裝,是以,封裝可以看成是用來提供抽象的一種政策。
繼承給對象提供了從基類擷取字段和方法的能力。繼承提供了代碼的重用行,也可以在不修改類的情況下給現存的類添加新特性。
多态是程式設計語言給不同的底層資料類型做相同的接口展示的一種能力。一個多态類型上的操作可以應用到其他類型的值上面。或者這樣了解, 指允許不同類的對象對同一消息做出響應。即同一消息可以根據發送對象的不同而采用多種不同的行為方式。
<![if !supportLists]>1.<![endif]>可替換性(substitutability)。多态對已存在代碼具有可替換性。例如,多态對圓Circle類工作,對其他任何圓形幾何體,如圓環,也同樣工作。
2.可擴充性(extensibility)。多态對代碼具有可擴充性。增加新的子類不影響已存在類的多态性、繼承性,以及其他特性的運作和操作。實際上新加子類更容易獲得多态功能。例如,在實作了圓錐、半圓錐以及半球體的多态基礎上,很容易增添球體類的多态性。
3.接口性(interface-ability)。多态是超類通過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆寫它而實作的。
4.靈活性(flexibility)。它在應用中展現了靈活多樣的操作,提高了使用效率。
5.簡化性(simplicity)。多态簡化對應用軟體的代碼編寫和修改過程,尤其在處理大量對象的運算和操作時,這個特點尤為突出和重要。
封裝給對象提供了隐藏内部特性和行為的能力。對象提供一些能被其他對象通路的方法來改變它内部的資料。在Java當中,有3種修飾符:public,private和protected。每一種修飾符給其他的位于同一個包或者不同包下面對象賦予了不同的通路權限。
下面列出了使用封裝的一些好處:
通過隐藏對象的屬性來保護對象内部的狀态。
提高了代碼的可用性和可維護性,因為對象的行為可以被單獨的改變或者是擴充。
禁止對象之間的不良互動提高子產品化。
參考這個文檔擷取更多關于封裝的細節和示例。
代碼開發子產品化,更易維護和修改。
代碼複用。
增強代碼的可靠性和靈活性。
增加代碼的可了解性。
面向對象程式設計有很多重要的特性,比如:封裝,繼承,多态和抽象。
JSP隐含對象是頁面中的一些Java對象,JSP容器讓這些Java對象可以為開發者所使用。開發者不用明确的聲明就可以直接使用他們。JSP隐含對象也叫做預定義變量。下面列出了JSP頁面中的隐含對象:
application,page,request,response,session,exception,out,config,pageContext
JSP技術中,scriptlet是嵌入在JSP頁面中的一段Java代碼。scriptlet是位于标簽内部的所有的東西,在标簽與标簽之間,使用者可以添加任意有效的scriplet。
在JSP中Scriptlet一共分為三種:
· <%%>:定義局部變量,編寫語句
· <%!%>:定義全局變量,可以編寫類、方法
· <%=%>:表達式輸出,專門輸出變量或一個具體值
JSP動作以XML文法的結構來控制Servlet引擎的行為。當JSP頁面被請求的時候,JSP動作會被執行。它們可以被動态的插入到檔案中,重用JavaBean元件,轉發使用者到其他的頁面,或者是給Java插件産生HTML代碼。下面列出了可用的動作:
jsp:include-當JSP頁面被請求的時候包含一個檔案。
jsp:useBean-找出或者是初始化Javabean。
jsp:setProperty-設定JavaBean的屬性。
jsp:getProperty-擷取JavaBean的屬性。
jsp:forward-把請求轉發到新的頁面。
jsp:plugin-産生特定浏覽器的代碼。
什麼是JSP指令(Directive)?JSP中有哪些不同類型的指令?
Directive是當JSP頁面被編譯成Servlet的時候,JSP引擎要處理的指令。Directive用來設定頁面級别的指令,從外部檔案插入資料,指定自定義的标簽庫。Directive是定義在 <%@ 和 %>之間的。下面列出了不同類型的Directive:
包含指令(Include directive):用來包含檔案和合并檔案内容到目前的頁面。
頁面指令(Page directive):用來定義JSP頁面中特定的屬性,比如錯誤頁面和緩沖區。
Taglib指令: 用來聲明頁面中使用的自定義的标簽庫。
下面列出了使用JSP的優點:
JSP頁面是被動态編譯成Servlet的,是以,開發者可以很容易的更新展現代碼。
JSP頁面可以被預編譯。
JSP頁面可以很容易的和靜态模闆結合,包括:HTML或者XML,也可以很容易的和産生動态内容的代碼結合起來。
開發者可以提供讓頁面設計者以類XML格式來通路的自定義的JSP标簽庫。
開發者可以在元件層做邏輯上的改變,而不需要編輯單獨使用了應用層邏輯的頁面。
浏覽器首先要請求一個以.jsp擴充名結尾的頁面,發起JSP請求,然後,Web伺服器讀取這個請求,使用JSP編譯器把JSP頁面轉化成一個Servlet類。需要注意的是,隻有當第一次請求頁面或者是JSP檔案發生改變的時候JSP檔案才會被編譯,然後伺服器調用servlet類,處理浏覽器的請求。一旦請求執行結束,servlet會把響應發送給用戶端。
JSP頁面是一種包含了靜态資料和JSP元素兩種類型的文本的文本文檔。靜态資料可以用任何基于文本的格式來表示,比如:HTML或者XML。JSP是一種混合了靜态内容和動态産生的内容的技術。
URL編碼是負責把URL裡面的空格和其他的特殊字元替換成對應的十六進制表示,反之就是解碼。
sendRedirect()方法會建立一個新的請求,而forward()方法隻是把請求轉發到一個新的目标上。重定向(redirect)以後,之前請求作用域範圍以内的對象就失效了,因為會産生一個新的請求,而轉發(forwarding)以後,之前請求作用域範圍以内的對象還是能通路的。一般認為sendRedirect()比forward()要慢。
HTTP隧道是一種利用HTTP或者是HTTPS把多種網絡協定封裝起來進行通信的技術。是以,HTTP協定扮演了一個打通用于通信的網絡協定的管道的包裝器的角色。把其他協定的請求掩蓋成HTTP的請求就是HTTP隧道。
cookie是Web伺服器發送給浏覽器的一塊資訊。浏覽器會在本地檔案中給每一個Web伺服器存儲cookie。以後浏覽器在給特定的Web伺服器發請求的時候,同時會發送所有為該伺服器存儲的cookie。下面列出了session和cookie的差別:
無論用戶端浏覽器做怎麼樣的設定,session都應該能正常工作。用戶端可以選擇禁用cookie,但是,session仍然是能夠工作的,因為用戶端無法禁用服務端的session。
在存儲的資料量方面session和cookies也是不一樣的。session能夠存儲任意的Java對象,cookie隻能存儲String類型的對象。
控制反轉即IoC (Inversion of Control),是面向對象程式設計中的一種設計原則,可以用來減低計算機代碼之間的耦合度。它把傳統上由程式代碼直接操控的對象的調用權交給容器,通過容器來實作對象元件的裝配和管理。所謂的“控制反轉”概念就是對元件對象控制權的轉移,從程式代碼本身轉移到了外部容器。
所謂依賴注入就是指:在運作期,由外部容器動态地将依賴對象注入到元件中。當spring容器啟動後,spring容器初始化,建立并管理bean對象,以及銷毀它。是以我們隻需從容器直接擷取Bean對象就行,而不用編寫一句代碼來建立bean對象。這種現象就稱作控制反轉,即應用本身不負責依賴對象的建立及維護,依賴對象的建立及維護是由外部容器負責的。這樣控制權就由應用轉移到了外部容器,控制權的轉移就是所謂反轉。雖然平時隻需要按要求将bean配置到配置檔案中,但是了解其實作過程對了解spring的實作原理是有好處的。
使用Cookie 使用URL重寫 使用隐藏的表單域
一個使用者的所有請求操作都應該屬于同一個會話,而另一個使用者的所有請求操作則應該屬于另一個會話,二者不能混淆。而Web 應用程式是使用 HTTP 協定傳輸資料的。 HTTP 協定是 無狀态 的協定。一旦資料交換完畢,用戶端與伺服器端的連接配接就會關閉,再次交換資料需要建立新的連接配接。這就意味着伺服器無法從連接配接上跟蹤會話。要跟蹤該會話,必須引入一種機制。Cookie 和 Session 就是這樣的一種機制。
引導類加載器(bootstrap class loader):它用來加載 Java 的核心庫,是用原生代碼來實作的
擴充類加載器(extensions class loader):它用來加載 Java 的擴充庫。
系統類加載器(system class loader):它根據 Java 應用的類路徑(CLASSPATH)來加載 Java 類
tomcat為每個App建立一個Loader,裡面儲存着此WebApp的ClassLoader。需要加載WebApp下的類時,就取出ClassLoader來使用
jvm classLoader architecture :
A、Bootstrap ClassLoader/啟動類加載器
主要負責jdk_home/lib目錄下的核心 api 或 -Xbootclasspath 選項指定的jar包裝入工作.
B、Extension ClassLoader/擴充類加載器
主要負責jdk_home/lib/ext目錄下的jar包或 -Djava.ext.dirs 指定目錄下的jar包裝入工作
C、System ClassLoader/系統類加載器
主要負責java -classpath/-Djava.class.path所指的目錄下的類與jar包裝入工作.
D、 User Custom ClassLoader/使用者自定義類加載器(java.lang.ClassLoader的子類)
在程式運作期間, 通過java.lang.ClassLoader的子類動态加載class檔案, 展現java動态實時類裝入特性.
1.指針
JAVA語言讓程式設計者無法找到指針來直接通路記憶體無指針,并且增添了自動的記憶體管理功能,進而有效地防止了c/c++語言中指針操作失誤,如野指針所造成的系統崩潰。但也不是說JAVA沒有指針,虛拟機内部還是使用了指針,隻是外人不得使用而已。這有利于Java程式的安全。
2.多重繼承
c++支援多重繼承,這是c++的一個特征,它允許多父類派生一個類。盡管多重繼承功能很強,但使用複雜,而且會引起許多麻煩,編譯程式實作它也很不容易。Java不支援多重繼承,但允許一個類繼承多個接口(extends+implement),實作了c++多重繼承的功能,又避免了c++中的多重繼承實作方式帶來的諸多不便。
3.資料類型及類
Java是完全面向對象的語言,所有函數和變量部必須是類的一部分。除了基本資料類型之外,其餘的都作為類對象,包括數組。對象将資料和方法結合起來,把它們封裝在類中,這樣每個對象都可實作自己的特點和行為。而c++允許将函數和變量定義為全局的。此外,Java中取消了c/c++中的結構和聯合,消除了不必要的麻煩。
4.自動記憶體管理
Java程式中所有的對象都是用new操作符建立在記憶體堆棧上,這個操作符類似于c++的new操作符。下面的語句由一個建立了一個類Read的對象,然後調用該對象的work方法:
Read r=new Read();
r.work();
語句Read r=new Read();在堆棧結構上建立了一個Read的執行個體。Java自動進行無用記憶體回收操作,不需要程式員進行删除。而c十十中必須由程式貝釋放記憶體資源,增加了程式設計者的負扔。Java中當一個對象不被再用到時,無用記憶體回收器将給它加上标簽以示删除。JAVA裡無用記憶體回收程式是以線程方式在背景運作的,利用空閑時間工作。
5.操作符重載
Java不支援操作符重載。操作符重載被認為是c十十的突出特征,在Java中雖然類大體上可以實作這樣的功能,但操作符重載的友善性仍然丢失了不少。Java語言不支援操作符重載是為了保持Java語言盡可能簡單。
6.預處理功能
Java不支援預處理功能。c/c十十在編譯過程中都有一個預編澤階段,即衆所周知的預處理器。預處理器為開發人員提供了友善,但增加丁編譯的複雜性。JAVA虛拟機沒有預處理器,但它提供的引入語句(import)與c十十預處理器的功能類似。
7. Java不支援預設函數參數,而c十十支援
在c中,代碼組織在函數中,函數可以通路程式的全局變量。c十十增加了類,提供了類算法,該算法是與類相連的函數,c十十類方法與Java類方法十分相似,然而,由于c十十仍然支援c,是以不能阻止c十十開發人員使用函數,結果函數和方法混合使用使得程式比較混亂。
Java沒有函數,作為一個比c十十更純的面向對象的語言,Java強迫開發人員把所有例行程式包括在類中,事實上,用方法實作例行程式可激勵開發人員更好地組織編碼。
8. 字元串
c和c十十不支援字元串變量,在c和c十十程式中使用Null終止符代表字元串的結束,在Java中字元串是用類對象(strinR和stringBuffer)來實作的,這些類對象是Java語言的核心,用類對象實作字元串有以下幾個優點:
(1)在整個系統中建立字元串和通路字元串元素的方法是一緻的;
(2)J3陽字元串類是作為Java語言的一部分定義的,而不是作為外加的延伸部分;
(3)Java字元串執行運作時檢空,可幫助排除一些運作時發生的錯誤;
(4)可對字元串用“十”進行連接配接操作。
9. goto語句
“可怕”的goto語句是c和c++的“遺物”,它是該語言技術上的合法部分,引用goto語句引起了程式結構的混亂,不易了解,goto語句子要用于無條件轉移子程式和多結構分支技術。鑒于以廣理由,Java不提供goto語句,它雖然指定goto作為關鍵字,但不支援它的使用,使程式簡潔易讀。
l0.類型轉換
在c和c十十中有時出現資料類型的隐含轉換,這就涉及了自動強制類型轉換問題。例如,在c十十中可将一浮點值賦予整型變量,并去掉其尾數。Java不支援c十十中的自動強制類型轉換,如果需要,必須由程式顯式進行強制類型轉換。
11.異常
JAVA中的異常機制用于捕獲例外事件,增強系統容錯能力
try{//可能産生例外的代碼
}catch(exceptionType name){
//處理
其中exceptionType表示異常類型。而C++則沒有如此友善的機制。