MVC 全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典范,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。
MVC只是將分管不同功能的邏輯代碼進行了隔離,增強了可維護和可擴展性,增強代碼復用性,因此可以減少代碼重復 。但是不保證減少代碼量,多層次的調用模式還有可能增加代碼量
forward 和 redirect 區別
1.從地址欄顯示來說
forward是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然后把這些內容再發給瀏覽器.瀏覽器根本不知道服務器發送的內容從哪里來的,所以它的地址欄還是原來的地址.
redirect是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址.所以地址欄顯示的是新的URL.
2.從數據共享來說
forward:轉發頁面和轉發到的頁面可以共享request里面的數據.
redirect:不能共享數據.
3.從運用地方來說
forward:一般用於用戶登陸的時候,根據角色轉發到相應的模塊.
redirect:一般用於用戶注銷登陸時返回主頁面和跳轉到其它的網站等.
4.從效率來說
forward:高.
redirect:低.
JDK,JRE,JVM區別與聯系?
答: JDK : Java Development ToolKit(Java開發工具包)。JDK是整個JAVA的核心,包括了Java運行環境(Java Runtime Envirnment),一堆Java工具(javac/java/jdb等)和Java基礎的類庫(即Java API 包括rt.jar)。 最主流的JDK是Sun公司發布的JDK,除了Sun之外,還有很多公司和組織都開發了屬於自己的JDK,例如國外IBM公司開發了屬於自己的JDK,國內淘寶也開發了屬於自己的JDK,各個組織開發自己的JDK都是為了在某些方面得到一些提高,以適應自己的需求,比如IBM的JDK據說運行效率就比SUN的JDK高的多。但不管怎么說,我們還是需要先把基礎的Sun JDK掌握好。 JDK有以下三種版本: J2SE,standard edition,標准版,是我們通常用的一個版本J2EE,enterpsise edtion,企業版,使用這種JDK開發J2EE應用程序J2ME,micro edtion,主要用於移動設備、嵌入式設備上的java應用程序 我們常常用JDK來代指Java API,Java API是Java的應用程序接口,其實就是前輩們寫好的一些java Class,包括一些重要的語言結構以及基本圖形,網絡和文件I/O等等 ,我們在自己的程序中,調用前輩們寫好的這些Class,來作為我們自己開發的一個基礎。當然,現在已經有越來越多的性能更好或者功能更強大的第三方類庫供我們使用。
JRE:Java Runtime Enviromental(java運行時環境)。也就是我們說的JAVA平台,所有的Java程序都要在JRE下才能運行。包括JVM和JAVA核心類庫和支持文件。與JDK相比,它不包含開發工具——編譯器、調試器和其它工具。
JVM:Java Virtual Mechinal(JAVA虛擬機)。JVM是JRE的一部分,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。JVM有自己完善的硬件架構,如處理器、堆棧、寄存器等,還具有相應的指令系統。JVM 的主要工作是解釋自己的指令集(即字節碼)並映射到本地的 CPU 的指令集或 OS 的系統調用。Java語言是跨平台運行的,其實就是不同的操作系統,使用不同的JVM映射規則,讓其與操作系統無關,完成了跨平台性。JVM 對上層的 Java 源文件是不關心的,它關注的只是由源文件生成的類文件( class file)。類文件的組成包括 JVM 指令集,符號表以及一些補助信息。
JVM內存總體一共分為了 4個部分(stack segment、heap segment、code segment、data segment) 當我們在程序中聲明一個局部變量的時候,此變量就存放在了 stack segment(棧)當中; 當new 一個對象的時候,此對象放在了heap segment(堆)當中; static 的變量或者字符串常量 則存在在 data segment(數據區)中; 類中方法是存在在 code segment(代碼區)中。
對於JVM內存配置參數:-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3 ,其最小內存值和Survivor區總大小分別是(10240m,2048m)
Eden:Survivor = 3,總大小-Xmn為5120。3x+2x=5120。 則x=1024,2個為2048
-Xmx:最大堆大小
-Xms:初始堆大小
-Xmn: 年輕代大小
-XXSurvivorRatio:年輕代中Eden區與Survivor區的大小比值
根據Generation-Collection算法(目前大部分JVM采用的算法),一般根據對象的生存周期將堆內存分為若干不同的區域,一般情況將新生代分為Eden 和 兩塊Survivor。
新生代大部分要回收,采用Copying算法,快!
老年代 大部分不需要回收,采用Mark-Compact算法
Spring依賴注入(DI)的三種方式,分別為:
1. 接口注入
2. Setter 方法注入
3. 構造方法注入
JAVA基礎
( 1 )對於外部類 而言,它也可以使用訪問控制符修飾,但外部類只能有兩種訪問控制級別: public 和默認。因為外部類沒有處於任何類的內部,也就沒有其所在類的內部、所在類的子類兩個范圍,因此 private 和 protected 訪問控制符對外部類沒有意義。
( 2 )內部類的上一級程序單元是外部類,它具有 4 個作用域:同一個類( private )、同一個包( protected )和任何位置( public )。
( 3 ) 因為局部成員的作用域是所在方法,其他程序單元永遠不可能訪問另一個方法中的局部變量,所以所有的局部成員都不能使用訪問控制修飾符修飾。
private
default
protected
public
同一個類中
√
√
√
√
同一個包中
√
√
√
子類中
√
√
全局范圍內
√
final關鍵字。修飾類、方法、屬性!不能修飾抽象類,因為抽象類一般都是需要被繼承的,final修飾后就不能繼承了。
1.final修飾變量,則等同於常量。不能被再次賦值!
2.final修飾方法中的參數,稱為最終參數。
3.final修飾類,則類不能被繼承
4.final修飾方法,則方法不能被重寫(注意不是重載)
Java標識符
由數字、字母、下划線(_)、美元符號($)或人民幣(¥) 組成,首位不能是數字 。並且Java關鍵字不能作為標識符 。
泛型
在開發中使用泛型取代非泛型的數據類型(比如用ArrayList<String>取代ArrayList),程序的運行時性能不變
泛型僅僅是java的一顆語法糖,它不會影響java虛擬機生成的匯編代碼,在編譯階段,虛擬機就會把泛型的類型擦除,還原成沒有泛型的代碼,頂多編譯速度稍微慢一些,執行速度是完全沒有什么區別的。
sleep()和wait()的區別
1,這兩個方法來自不同的類分別是Thread和Object
2,最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得敏感詞線程可以使用同步控制塊或者方法。
3,wait,notify和notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用
synchronized(x){
x.notify()
//或者wait()
}
4,sleep 必須捕獲異常,而wait,notify和notifyAll不需要捕獲異常
類中有缺省構造器constructor,不一定要定義構造器
方法可以和類同名,和構造器區別在於方法必須要有返回值類型。
一個類可以定義多個參數列表不同的構造器,實現構造器重載。
編碼: 一個編號(數字)到字符的一種映射關系,就僅僅是一種一對一的映射而已,可以理解成一個很大的對應表格
java默認的字符集是Unicode(占兩個字節byte,一個字節=8比特位bit,所以每個Unicode占用16比特位)
編碼格式: 用來序列化或存儲編碼中提到的那個“編號(數字)”的一種“格式”,包括gbk和utf-8
gbk: 是指中國的中文字符,其它它包含了簡體中文與繁體中文字符
UTF-8: 它是一種全國家通過的一種編碼
什么是字符串常量池
JVM為了減少字符串對象的重復創建,其維護了一個特殊的內存,這段內存被成為字符串常量池或者字符串字面量池
工作原理
當代碼中出現字面量形式創建字符串對象時,JVM首先會對這個字面量進行檢查,如果字符串常量池中存在相同內容的字符串對象的引用,則將這個引用返回,否則新的字符串對象被創建,然后將這個引用放入字符串常量池,並返回該引用。
實現前提
字符串常量池實現的前提條件就是Java中String對象是不可變的,這樣可以安全保證多個變量共享同一個對象。如果Java中的String對象可變的話,一個引用操作改變了對象的值,那么其他的變量也會受到影響,顯然這樣是不合理的。
關於堆和棧
Java中所有由類實例化的對象和數組都存放在堆內存中,無論是成員變量,局部變量,還是類變量,它們指向的對象都存儲在堆內存中。而棧內存用來存儲局部變量和方法調用。
關於寄存器
Java中運行時數據區有一個程序寄存器(又稱程序計數器),該寄存器為線程私有。Java中的程序計數器用來記錄當前線程中正在執行的指令。如果當前正在執行的方法是本地方法,那么此刻程序計數器的值為 undefined
String str = new String(“abc”),則"abc"存儲在常量池中的,而new的String對象存儲在堆中,引用對象str存儲在棧中
數組命名時名稱與[]可以隨意排列,但聲明的二維數組中第一個中括號中必須要有值,它代表的是在該二維數組中有多少個一維數組。
一個Java源文件中只能包含一個與文件名同名的public類,但可以包含多個同名的非public內部類。
運算符優先級
單目 >運算>移位>比較>按位>邏輯>
三目 >
賦值 ,其中只有單目、三目、賦值是從右到左的
Java字節碼是Java源文件編譯產生的中間文件
java虛擬機是可運行java字節碼的假想計算機 java的跨平台性也是相對與其他編程語言而言的
先介紹一下c語言的編譯過程。先是C語言源程序 也就是c的文件經過C編譯程序編譯后,生成windows可執行文件exe文件,然后在windows中執行。
再介紹java的編譯過程。先是java源程序擴展名為java的文件,由java編譯程序將java字節碼文件,就是class文件然后在java虛擬機中執行。機器碼是由CPU來執行的。Java編譯后是字節碼, 電腦只能運行機器碼。
Java在運行的時候把字節碼變成機器碼。C/C++在編譯的時候直接編譯成機器碼。
Java異常都繼承自類Throwable,Throwable子類有Error和Exception,其中Exception又分為運行時異常和編譯時異常。
編譯時異常是未雨綢繆性質的異常,是防范,需要顯示處理。應該捕獲或者拋出
運行時異常是程序員問題造成,可以通過java虛擬機來自行處理
public interface IService {
String
NAME=
"default"
;
}
與上面等價表示是 public static final String NAME=”default”;
為什么是public:因為接口必然是要被實現的,如果不是public,這個屬性就沒有意義了;
為什么是static:因為如果不是static,那么由於每個類可以繼承多個接口,那就會出現重名的情況;
為什么是final:這是為了體現java的開閉原則,因為接口是一種模板,既然是模板,那就對修改關閉,對擴展開放。
java用來運行一個.class文件
javadoc用來生成api文檔
jar用來生成jar包
javac用來把.java文件編譯為.class文件
多線程
線程
run()方法用來執行線程體中具體的內容
start()方法用來啟動線程對象,使其進入就緒狀態
sleep()方法用來使線程進入睡眠狀態
suspend()方法用來使線程掛起,要通過resume()方法使其重新啟動
jvm中 是使用監視器鎖來實現不同線程的異步執行, 在語法的表現就是synchronized 。
程序輸出
public class Demo{
public static void main(String args[]){
int num = 10;
System.out.println(test(num));
}
public static int test(int b){
try
{
b += 10;
return b;
}
catch(RuntimeException e)
{
}
catch(Exception e2)
{
}
finally
{
b += 10;
return b;
}
}
}
輸出結果是(30 )
public class Example{
String str=new String("tarena");
char[]ch={'a','b','c'};
public static void main(String args[]){
Example ex=new Example();
ex.change(ex.str,ex.ch);
System.out.print(ex.str+" and ");
System.out.print(ex.ch);
}
public void change(String str,char ch[]){
//引用類型變量,傳遞的是地址,屬於引用傳遞。
str="test ok";
ch[0]='g';
}
}
輸出tarena and gbc
public static void main(String args[])throws InterruptedException{
Thread t =new Thread(new Runnable() {
public void run() {
try {
Thread.sleep( 2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.print( "2");
}
});
t.start();
t.join();
System.out.print( "1");
}
輸出21
因為子線程的休眠時間太長,因此主線程很有可能在子線程之前結束也就是輸出結果是12,但是子線程用了join函數,因此主線程必須等待子線程執行完畢才結束因此輸出結果只能是21
thread.Join把指定的線程加入到當前線程,可以將兩個交替執行的線程合並為順序執行的線程。比如在線程B中調用了線程A的Join()方法,直到線程A執行完畢后,才會繼續執行線程B。
t.join(); //使調用線程 t 在此之前執行完畢。
t.join(1000); //等待 t 線程,等待時間是1000毫秒
public class TestClass {
private static void testMethod(){
System.out.println( "testMethod");
}
public static void main(String[] args) {
((TestClass) null ).testMethod();
}
}
運行正常,輸出testMethod
1)此處是類對方法的調用,不是對象對方法的調用。
2)方法是static靜態方法,直接使用"類.方法"即可,因為靜態方法使用不依賴對象是否被創建。
null可以被強制類型轉換成任意類型(不是任意類型對象),於是可以通過它來執行靜態方法。
3)非靜態的方法用"對象.方法"的方式,必須依賴對象被創建后才能使用,若將testMethod()方法前的static去掉,則會報 空指針異常 。此處也驗證了2)的觀點
當然,不管是否靜態方法,都是已經存在的,只是訪問方式不同。