面試經常問一些模棱兩可的問題,也就是一些在一些條件成立時,才能給出確定答案的問題。
比如問Java是否支持多繼承。那么回答要縝密,接口支持,類不支持。
多繼承導致網狀繼承結構。
? F????????????F
soft????????? bed
????softbed
F這層的成員變量會在softbed會出現兩份。
所以在C++中采用虛繼承來解決,達到了一種菱形結構。
?????????F
soft?????????bed
??????softbed
還有一點,就是F層的成員方法(不支持多態的方法),在soft和bed中都有。
Java所有方法都是virtual的
內存結構
---------------------------
???Data? [C++中是全局變量和static,Java中是static]
---------------------------
?? Code [代碼區是共享的]
---------------------------
?? Heap
---------------------------
?? Stack
---------------------------
Java的接口,那都是指針表,只有在運行時,才能確定每個方法的具體指向。
所以在IDE中,在一定代碼中,右鍵點擊一個接口的引用,尋找definition的時候,只能定位到接口,不能定義到具體實現類,因為在IDE中能確定編譯時的類型。
=================================================
Java修飾符號最后總結。
問class的修飾符有幾種?
縝密回答,如果是頂級類,只有兩種public 和 default。如果是內部類(成員內部類)就可以有四種。
new Outer().new Outer.Inner();
局部內部類是只能訪問final的局部變量。
匿名內部類肯定是繼承一個現有類型的類,或者實現一個現有接口。
靜態內部類也是一個頂級類,不依賴于外部類的實例,只能訪問外部類的靜態成員變量,就好像靜態方法。
C++中的嵌套類只相當于Java的靜態內部類。
=========================
final和abstract是互斥的!絕對不能出現在一起。
final的變量可以在構造器中修改,因為Java沒有想C++的初始化列表。
類型和名字在一起是核心原則,其他修飾符順序可以隨便變。
<modifiers><return-type><name>[argument_list][throws ...]
native與abstract也肯定互斥。
記住,書寫習慣是很重要的。因為可以認為代碼中“如果占居的位置一樣,那么享受的權利就一樣”
=========================
IdentityMap只用==排序。
List和Set的選擇,在Hibernate和CMP中有用到,而且區別比較大。以后總結
=========================
線程相關函數,
sleep()可以出現在非Synchronized塊中。而wait()肯定是Synchronized塊中,因為此操作會釋放鎖。
都會跑出InterruppptedException。
----------------------------------------
線程加鎖問題,困擾著軟件開發人員。
T1 --------------------〉數據 <--------------------------T2
???????????????????????????那么就在數據這邊加鎖唄。
在共享的對象類型中加減鎖,在可讀可寫成員變量加減鎖。
在訪問static變量,加鎖,訪問相同外部資源加鎖
在有讀寫兩個方法,比如生產者,消費者問題,就要在加鎖方法中添加wait和notify操作。
~~~~~~~~~~~~~~~~~~~~~~~~~~
實際上,在J2EE開發中,我們在做什么呢,實際上就是在編寫數據那部分的代碼。
Servlet,是什么,就是很多線程共享的一個數據對象,有相關的服務方法。
所以不建議在Servlet中寫成員變量,因為有數據同步問題。
所以一般,都是在方法中定義局部變量,[在這說一句,為什么局部變量沒有數據同步問題呢,那是因為對于每一個開啟的Thread,都會從進程的棧區分化出一部分做本線程的獨立棧區分配給局部變量]
SingleThreadModel已經被單獨廢除,因為此接口不能避免數據同步問題,因為即使一個Servlet類型可以創建多個實例,對于成員變量沒有線程同步問題,但是如果在Servlet中操作共享對象,比如ServletContext,就完蛋了,或者是靜態變量,和其他共享資源都要保護。
~~~~~~~~~~~~~~~~~~~~~~~~~~
IO 相關
byte[]????????????????? InputStream????????????????????????OutStream
primitive???????????????DataInputStream???????????????????????????DataOutputStream
String
字符???????????????????Reader?????????????????????????????????Writer
InputStream和OutStream因為不能確定源和目的地,所以都是抽象的。
在字節流和字符流之間必須要有個橋轉換,也就是Reader的構建需要一個InputStreamReader(InputStream,charset);
這里指的字符集是指JVM外部的編碼方式。
外部編碼方式---------------IN----------->JVM(UNICODE)-------------OUT------------->外部編碼方式
--------------------------------------------
Exception????????????????????????????RuntimeException
如果自定義異常是繼承RuntimeException,就是表明如果在此處跑出這樣的異常,其他地方是沒有什么辦法進行修復的,也就是調用方無辦法。
而已檢查異常則是,可以修復的異常。比如用戶驗證等,可以讓用戶在此輸入用戶名和密碼。
最好也將運行時異常也聲明在方法簽名中。
============================
JDBC,驅動有四類,就是對已有ODBC的橋接,對Pro*C的本地C函數的調用,通過專有數據庫協議,通過獨立的協議,但需要在單獨的一個Server進行轉換。
分頁顯示的實現,可以從兩個角度來做,一個SQL,一個是JDBC API,
import?java.sql.*;
import?java.io.*;


public?class?SeparatePage
{
????private?String?url;
????private?String?username;
????private?String?password;


????private?Connection?conn(String?url,String?username,String?password)
{

????????try
{
????????????Class.forName("oracle.jdbc.driver.OracleDriver");
????????????Connection?con=DriverManager.getConnection(url,username,password);
????????????return?con;
????????}

????????catch(Exception?conException)
{
????????????conException.printStackTrace();
????????????return?null;
????????}
????}
????

????private?PreparedStatement?setScrollRs(Connection?con,String?sql)
{

????????try
{
????????????if(con==null)?
????????????????return?null;
????????????PreparedStatement?pst=con.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
????????????return?pst;
????????}

????????catch(Exception?psException)
{
????????????psException.printStackTrace();
????????????return?null;
????????}
????}
????

????private?ResultSet?execute(PreparedStatement?pst)
{

????????try
{
????????????ResultSet?rs=pst.executeQuery();
????????????return?rs;
????????}

????????catch(Exception?ee)
{?
????????????System.out.println("query?error:"+ee);
????????????return?null;
????????}
????}
????

????private?int?countPage(ResultSet?rs,int?pageSize)
{

????????try
{
????????????rs.last();??
????????????int?rowCount?=?rs.getRow();
????????????int?pageCount?=?(rowCount+pageSize-1)?/?pageSize;
????????????return?pageCount;
????????}

????????catch(Exception?e1)
{
????????????System.out.println("countPage?error:"+e1);
????????????return?0;
????????}
????}
????

????private?void?beginPos(ResultSet?rs,int?pageNo,int?pageSize)
{

????????try
{
????????????rs.absolute((pageNo-1)?*?pageSize?+?1);
????????}
????????catch(Exception?sql)

????????
{
????????????sql.printStackTrace();
????????}
????}
????

????private?String?getPrompt(String?msg)
{
????????BufferedReader?bis=new?BufferedReader(new?InputStreamReader(System.in));

????????try
{
????????????String?s="";
????????????System.out.println(msg);
????????????if(s.length()<1)??s?=?bis.readLine();
????????????return?s;
????????}catch(Exception?ioException)

????????
{
????????????return?null;
????????}
????}
????

????private?void?view(ResultSet?rs,int?pageSize)
{

????????try
{
????????????ResultSetMetaData?rmeta?=?rs.getMetaData();
????????????int?numColumns?=?rmeta.getColumnCount();
????????????int?i?=?0;
????????????while(i<pageSize?&&?!rs.isAfterLast())

????????????
{
????????????????for(int?j?=?0;j<?numColumns;j++)

????????????????
{
????????????????????String?sTemp?=?rs.getString(j+1);
????????????????????System.out.print(sTemp+"?????");
????????????????}
????????????????i++;
????????????????rs.next();
????????????????System.out.println();????
????????????}

????????}catch(Exception?se)
{
????????????se.printStackTrace();
????????}
????}
????

????void?demo()

????
{
????????Connection?con=null;
????????PreparedStatement?pst=null;
????????ResultSet?rs=null;

????????try
{
????????????boolean?flag=true;
????????????con=conn(url,username,password);
????????????String?sql?=?"select?*?from?xj?order?by?id";
????????????pst=setScrollRs(con,sql);
????????????rs=execute(pst);

????????????while(flag)
{
????????????????int?pageSize=Integer.parseInt(getPrompt("請輸入頁面長度"));
????????????????int?pageCount=countPage(rs,pageSize);
????????????????if(getPrompt("是否退出(y/n)?").equals("y"))?

????????????????
{
????????????????????flag?=?false;
????????????????????break;
????????????????}
????????????????int?pageNo=Integer.parseInt(getPrompt("請輸入要查看第幾頁"));
????????????????beginPos(rs,pageNo,pageSize);
????????????????view(rs,pageSize);
????????????????if(getPrompt("是否返回(y/n)?").equals("y"))?
????????????????????continue;
????????????}
????????}

????????catch(Exception?e)
{
????????????e.printStackTrace();
????????}

????????finally
{

????????????try
{
????????????????if(con!=null)?con.close();
????????????????if(pst!=null)?pst.close();
????????????????if(rs!=null)?rs.close();
????????????}

????????????catch?(Exception?ec)
{
????????????????ec.printStackTrace();
????????????}
????????}
????}
????

????public?static?void?main(String?args[])
{

????????if(args.length!=3)
{
????????????System.out.println("use:java?JDBCConn?url?username?password");
????????????return;
????????}
????????SeparatePage?sp=new?SeparatePage();
????????sp.url=args[0];
????????sp.username=args[1];
????????sp.password=args[2];
????????sp.demo();
????}????
}

============================

方框就是Attribute。
實際上還有Session的Map,有Session和一個ID,而這個ID被作為一個hook鉤子放置于Cookie中,使得瀏覽器與Session對應上,屏蔽了Http無狀態的弊端。
===========
監聽器分為對于Session,Request,Application的生命周期的監聽器和屬性添加刪除的監聽器。
對于Session還有一個就是跟群集有關的,在FailOver的時候,要對Session 進行網絡傳輸到備用設備上,那么屬性和需要支持串行化,對于不能串行化的資源,比如數據庫連接,需要有一個時機來斷開和重新獲得,那么就有HttpSessionActivationListener。
Struts和EJB,都是API依賴,都是基于繼承多態的框架,移植性降低。
而Spring和Hibernate基于反射,弊端是依賴于配置,配置文件多,調試困難,因為都是要在運行時才能確定配置是否正確。
posted on 2006-04-22 12:34
北國狼人的BloG 閱讀(536)
評論(2) 編輯 收藏 所屬分類:
達內學習總結