08.01_面向對象(代碼塊的概述和分類)(瞭解)(面試的時候會問,開發不用或者很少用)
- A:代碼塊概述
- 在Java中,使用{}括起來的代碼被稱爲代碼塊。
- B:代碼塊分類
- 根據其位置和聲明的不同,可以分爲局部代碼塊,構造代碼塊,靜態代碼塊,同步代碼塊(多線程講解)。
- C:常見代碼塊的應用
- a:局部代碼塊
- 在方法中出現;限定變量生命週期,及早釋放,提高內存利用率
- b:構造代碼塊 (初始化塊)
- 在類中方法外出現;多個構造方法方法中相同的代碼存放到一起,每次調用構造都執行,並且在構造方法前執行
- c:靜態代碼塊
- 在類中方法外出現,並加上static修飾;用於給類進行初始化,在加載的時候就執行,並且只執行一次。
- 一般用於加載驅動
- a:局部代碼塊
08.02_面向對象(代碼塊的面試題)(掌握)
- A:看程序寫結果
-
class Student { static { System.out.println("Student 靜態代碼塊"); } { System.out.println("Student 構造代碼塊"); } public Student() { System.out.println("Student 構造方法"); } } class Demo2_Student { static { System.out.println("Demo2_Student靜態代碼塊"); } public static void main(String[] args) { System.out.println("我是main方法"); Student s1 = new Student(); Student s2 = new Student(); } }
08.03_面向對象(繼承案例演示)(掌握)
- A:繼承(extends)
- 讓類與類之間產生關係,子父類關係
- B:繼承案例演示:
- 動物類,貓類,狗類
- 定義兩個屬性(顏色,腿的個數)兩個功能(喫飯,睡覺)
- C:案例演示
- 使用繼承前
- D:案例演示
- 使用繼承後
08.04_面向對象(繼承的好處和弊端)(掌握)
- A:繼承的好處
- a:提高了代碼的複用性
- b:提高了代碼的維護性
- c:讓類與類之間產生了關係,是多態的前提
- B:繼承的弊端
-
類的耦合性增強了。
-
開發的原則:高內聚,低耦合。
-
耦合:類與類的關係
-
內聚:就是自己完成某件事情的能力
-
08.05_面向對象(Java中類的繼承特點)(掌握)
- A:Java中類的繼承特點
- a:Java只支持單繼承,不支持多繼承。(一個兒子只能有一個爹)
- 有些語言是支持多繼承,格式:extends 類1,類2,…
- b:Java支持多層繼承(繼承體系)
- a:Java只支持單繼承,不支持多繼承。(一個兒子只能有一個爹)
- B:案例演示
- Java中類的繼承特點
- 如果想用這個體系的所有功能用最底層的類創建對象
- 如果想看這個體系的共性功能,看最頂層的類
- Java中類的繼承特點
08.06_面向對象(繼承的注意事項和什麼時候使用繼承)(掌握)
-
A:繼承的注意事項
- a:子類只能繼承父類所有非私有的成員(成員方法和成員變量)
- b:子類不能繼承父類的構造方法,但是可以通過super(馬上講)關鍵字去訪問父類構造方法。
- c:不要爲了部分功能而去繼承
- 項目經理 姓名 工號 工資 獎金
- 程序員 姓名 工號 工資
-
B:什麼時候使用繼承
- 繼承其實體現的是一種關係:“is a”。
Person
Student
Teacher
水果
蘋果
香蕉
橘子
採用假設法。
如果有兩個類A,B。只有他們符合A是B的一種,或者B是A的一種,就可以考慮使用繼承。 - 繼承其實體現的是一種關係:“is a”。
08.07_面向對象(繼承中成員變量的關係)(掌握)
- A:案例演示
- a:不同名的變量
- b:同名的變量
###08.08_面向對象(this和super的區別和應用)(掌握)
- A:this和super都代表什麼
- this:代表當前對象的引用,誰來調用我,我就代表誰
- super:代表當前對象父類的引用
- B:this和super的使用區別
- a:調用成員變量
- this.成員變量 調用本類的成員變量,也可以調用父類的成員變量
- super.成員變量 調用父類的成員變量
- b:調用構造方法
- this(…) 調用本類的構造方法
- super(…) 調用父類的構造方法
- c:調用成員方法
- this.成員方法 調用本類的成員方法,也可以調用父類的方法
- super.成員方法 調用父類的成員方法
- a:調用成員變量
08.09_面向對象(繼承中構造方法的關係)(掌握)
- A:案例演示
- 子類中所有的構造方法默認都會訪問父類中空參數的構造方法
- B:爲什麼呢?
-
因爲子類會繼承父類中的數據,可能還會使用父類的數據。
-
所以,子類初始化之前,一定要先完成父類數據的初始化。
-
其實:
- 每一個構造方法的第一條語句默認都是:super() Object類最頂層的父類。
-
08.10_面向對象(繼承中構造方法的注意事項)(掌握)
- A:案例演示
- 父類沒有無參構造方法,子類怎麼辦?
- super解決
- this解決
- B:注意事項
- super(…)或者this(….)必須出現在構造方法的第一條語句上
08.11_面向對象(繼承中的面試題)(掌握)
- A:案例演示
-
看程序寫結果1 class Fu{ public int num = 10; public Fu(){ System.out.println("fu"); } } class Zi extends Fu{ public int num = 20; public Zi(){ System.out.println("zi"); } public void show(){ int num = 30; System.out.println(num); System.out.println(this.num); System.out.println(super.num); } } class Test1_Extends { public static void main(String[] args) { Zi z = new Zi(); z.show(); } } 看程序寫結果2 class Fu { static { System.out.println("靜態代碼塊Fu"); } { System.out.println("構造代碼塊Fu"); } public Fu() { System.out.println("構造方法Fu"); } } class Zi extends Fu { static { System.out.println("靜態代碼塊Zi"); } { System.out.println("構造代碼塊Zi"); } public Zi() { System.out.println("構造方法Zi"); } } Zi z = new Zi(); 請執行結果。
08.12_面向對象(繼承中成員方法關係)(掌握)
- A:案例演示
- a:不同名的方法
- b:同名的方法
08.13_面向對象(方法重寫概述及其應用)(掌握)
- A:什麼是方法重寫
- 重寫:子父類出現了一模一樣的方法(注意:返回值類型可以是子父類,這個我們學完面向對象講)
- B:方法重寫的應用:
- 當子類需要父類的功能,而功能主體子類有自己特有內容時,可以重寫父類中的方法。這樣,即沿襲了父類的功能,又定義了子類特有的內容。
- C:案例演示
- a:定義一個手機類。
08.14_面向對象(方法重寫的注意事項)(掌握)
- A:方法重寫注意事項
-
a:父類中私有方法不能被重寫
- 因爲父類私有方法子類根本就無法繼承
-
b:子類重寫父類方法時,訪問權限不能更低
- 最好就一致
-
c:父類靜態方法,子類也必須通過靜態方法進行重寫
- 其實這個算不上方法重寫,但是現象確實如此,至於爲什麼算不上方法重寫,多態中我會講解(靜態只能覆蓋靜態)
-
子類重寫父類方法的時候,最好聲明一模一樣。
-
- B:案例演示
- 方法重寫注意事項
08.15_面向對象(方法重寫的面試題)(掌握)
- A:方法重寫的面試題
-
Override和Overload的區別?Overload能改變返回值類型嗎?
-
overload可以改變返回值類型,只看參數列表
-
方法重寫:子類中出現了和父類中方法聲明一模一樣的方法。與返回值類型有關,返回值是一致(或者是子父類)的
-
方法重載:本類中出現的方法名一樣,參數列表不同的方法。與返回值類型無關。
-
子類對象調用方法的時候:
- 先找子類本身,再找父類。
-
08.16_面向對象(使用繼承前的學生和老師案例)(掌握)
- A:案例演示
- 使用繼承前的學生和老師案例
- 屬性:姓名,年齡
- 行爲:喫飯
- 老師有特有的方法:講課
- 學生有特有的方法:學習
08.17_面向對象(使用繼承後的學生和老師案例)(掌握)
- A:案例演示
- 使用繼承後的學生和老師案例
08.18_面向對象(貓狗案例分析,實現及測試)(掌握)
- A:貓狗案例分析
- B:案例演示
- 貓狗案例繼承版
- 屬性:毛的顏色,腿的個數
- 行爲:喫飯
- 貓特有行爲:抓老鼠catchMouse
- 狗特有行爲:看家lookHome
08.19_面向對象(final關鍵字修飾類,方法以及變量的特點)(掌握)
- A:final概述
- B:final修飾特點
- 修飾類,類不能被繼承
- 修飾變量,變量就變成了常量,只能被賦值一次
- 修飾方法,方法不能被重寫
- C:案例演示
- final修飾特點
08.20_面向對象(final關鍵字修飾局部變量)(掌握)
- A:案例演示
-
方法內部或者方法聲明上都演示一下(瞭解)
-
基本類型,是值不能被改變
-
引用類型,是地址值不能被改變,對象中的屬性可以改變
-
08.21_面向對象(final修飾變量的初始化時機)(掌握)
- A:final修飾變量的初始化時機
- 顯示初始化
- 在對象構造完畢前即可
相關面試題:
1:代碼塊是什麼?代碼塊的分類和各自特點?
2:靜態代碼塊,構造代碼塊,構造方法的執行流程?
3:繼承概述
4:繼承的好處
5:Java中繼承的特點
6:Java中繼承的注意事項?以及我們什麼時候使用繼承?
7:繼承中的成員訪問特點
A:成員變量
在子類方法中訪問一個變量
B:成員方法
在測試類中通過子類對象去訪問一個方法
8:繼承中構造方法的執行流程?假如父類沒有無參構造方法,子類應該怎麼辦?
9:final關鍵字可以幹什麼?有什麼特點?
10:final關鍵字的面試題?
A:修飾局部變量
B:初始化時機
相關面試題:
- 使用 final 關鍵字修飾一個變量時, 是引用不能變, 還是引用的對象不能變?
使用 final 關鍵字修飾一個變量時, 是指引用變量不能變, 引用變量所指向的對象中的內容北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090
還是可以改變的。 例如, 對於如下語句:
final StringBuffer a=new StringBuffer(“immutable”);
執行如下語句將報告編譯期錯誤:
a=new StringBuffer("");
但是, 執行如下語句則可以通過編譯:
a.append(" broken!");
有人在定義方法的參數時, 可能想採用如下形式來阻止方法內部修改傳進來的參數對象:
public void method(final StringBuffer param){
}
實際上, 這是辦不到的, 在該方法內部仍然可以增加如下代碼來修改參數對象:
param.append(“a”); - ""和 equals 方法究竟有什麼區別?
操作符專門用來比較兩個變量的值是否相等, 也就是用於比較變量所對應的內存中所存
儲的數值是否相同, 要比較兩個基本類型的數據或兩個引用變量是否相等, 只能用操作
符。
如果一個變量指向的數據是對象類型的, 那麼, 這時候涉及了兩塊內存, 對象本身佔用一塊
內存(堆內存) , 變量也佔用一塊內存, 例如 Objet obj = new Object();變量 obj 是一個內存,
new Object()是另一個內存, 此時, 變量 obj 所對應的內存中存儲的數值就是對象佔用的那塊
內存的首地址。 對於指向對象類型的變量, 如果要比較兩個變量是否指向同一個對象, 即要
看這兩個變量所對應的內存中的數值是否相等, 這時候就需要用操作符進行比較。
equals 方法是用於比較兩個獨立對象的內容是否相同, 就好比去比較兩個人的長相是否相
同, 它比較的兩個對象是獨立的。 例如, 對於下面的代碼:
String a=new String(“foo”);
String b=new String(“foo”);
兩條 new 語句創建了兩個對象, 然後用 a,b 這兩個變量分別指向了其中一個對象, 這是兩個
不同的對象, 它們的首地址是不同的, 即 a 和 b 中存儲的數值是不相同的, 所以, 表達式
ab 將返回 false, 而這兩個對象中的內容是相同的, 所以, 表達式 a.equals(b)將返回 true。
在實際開發中, 我們經常要比較傳遞進行來的字符串內容是否等, 例如, String input
= …;input.equals(“quit”), 許多人稍不注意就使用進行比較了, 這是錯誤的, 隨便從網上
找幾個項目實戰的教學視頻看看, 裏面就有大量這樣的錯誤。 記住, 字符串的比較基本上都
是使用 equals 方法。
如果一個類沒有自己定義 equals 方法, 那麼它將繼承 Object 類的 equals 方法, Object 類的
equals 方法的實現代碼如下:
boolean equals(Object o){
return thiso;
} 這
說明, 如果一個類沒有自己定義 equals 方法, 它默認的 equals 方法(從 Object 類繼承的)
就是使用操作符, 也是在比較兩個變量指向的對象是否是同一對象, 這時候使用 equals
和使用==會得到同樣的結果, 如果比較的是兩個獨立的對象則總返回 false。 如果你編寫的
類希望能夠比較該類創建的兩個實例對象的內容是否相同, 那麼你必須覆蓋 equals 方法, 由
你自己寫代碼來決定在什麼情況即可認爲兩個對象的內容是相同的。 - 靜態變量和實例變量的區別?
語法定義上的區別: 靜態變量前要加 static 關鍵字, 而實例變量前則不加。北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090
程序運行時的區別: 實例變量屬於某個對象的屬性, 必須創建了實例對象, 其中的實例變量
纔會被分配空間, 才能使用這個實例變量。 靜態變量不屬於某個實例對象, 而是屬於類, 所
以也稱爲類變量, 只要程序加載了類的字節碼, 不用創建任何實例對象, 靜態變量就會被分
配空間, 靜態變量就可以被使用了。 總之, 實例變量必須創建對象後纔可以通過這個對象來
使用, 靜態變量則可以直接使用類名來引用。
例如, 對於下面的程序, 無論創建多少個實例對象, 永遠都只分配了一個 staticVar 變量, 並
且每創建一個實例對象, 這個 staticVar 就會加 1; 但是, 每創建一個實例對象, 就會分配一
個 instanceVar, 即可能分配多個 instanceVar, 並且每個 instanceVar 的值都只自加了 1 次。
public class VariantTest{
public static int staticVar = 0;
public int instanceVar = 0;
public VariantTest(){
staticVar++;
instanceVar++;
System.out.println(“staticVar=” + staticVar + ”,instanceVar=” + instanceVar);
}
} 備
注:這個解答除了說清楚兩者的區別外,最後還用一個具體的應用例子來說明兩者的差異,
體現了自己有很好的解說問題和設計案例的能力, 思維敏捷, 超過一般程序員, 有寫作能力! - 是否可從一個 static 方法內發出對非 static 方法的調用?
不可以。 因爲非 static 方法是要與對象關聯在一起的, 必須創建一個對象後, 纔可以在該對
象上進行方法調用, 而 static 方法調用時不需要創建對象, 可以直接調用。 也就是說, 當一
個 static 方法被調用時, 可能還沒有創建任何實例對象, 如果從一個 static 方法中發出對非
static 方法的調用, 那個非 static 方法是關聯到哪個對象上的呢? 這個邏輯無法成立, 所以,
一個 static 方法內部發出對非 static 方法的調用。 - Integer 與 int 的區別
int 是 java 提供的 8 種原始數據類型之一。Java 爲每個原始類型提供了封裝類, Integer 是 java
爲 int 提供的封裝類。 int 的默認值爲 0, 而 Integer 的默認值爲 null, 即 Integer 可以區分出
未賦值和值爲 0 的區別, int 則無法表達出未賦值的情況, 例如, 要想表達出沒有參加考試
和考試成績爲 0 的區別, 則只能使用 Integer。 在 JSP 開發中, Integer 的默認爲 null, 所以用
el 表達式在文本框中顯示時, 值爲空白字符串, 而 int 默認的默認值爲 0, 所以用 el 表達式
在文本框中顯示時, 結果爲 0, 所以, int 不適合作爲 web 層的表單數據的類型。
在 Hibernate 中, 如果將 OID 定義爲 Integer 類型, 那麼 Hibernate 就可以根據其值是否爲 null
而判斷一個對象是否是臨時的, 如果將 OID 定義爲了 int 類型, 還需要在 hbm 映射文件中
設置其 unsaved-value 屬性爲 0。
另外, Integer 提供了多個與整數相關的操作方法, 例如, 將一個字符串轉換成整數, Integer
中還定義了表示整數的最大值和最小值的常量。 - Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math 類中提供了三個與取整有關的方法: ceil、 floor、 round, 這些方法的作用與它們的英
文名稱的含義相對應,例如,ceil 的英文意義是天花板,該方法就表示向上取整,Math.ceil(11.3)
的結果爲 12,Math.ceil(-11.3)的結果是-11; floor 的英文意義是地板, 該方法就表示向下取整,
Math.ceil(11.6)的結果爲 11,Math.ceil(-11.6)的結果是-12; 最難掌握的是 round 方法, 它表示北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090
“四捨五入” , 算法爲 Math.floor(x+0.5), 即將原來的數字加上 0.5 後再向下取整, 所以,
Math.round(11.5)的結果爲 12, Math.round(-11.5)的結果爲-11。 - 下面的代碼有什麼不妥之處?
- if(username.equals(“zxx”){}
2.int x = 1;
return x==1?true:false; - 請說出作用域 public, private, protected, 以及不寫時的區別
說明: 如果在修飾的元素上面沒有寫任何訪問修飾符, 則表示 friendly。
作用域 當前類 同一 package 子孫類 其他 package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
備註: 只要記住了有 4 種訪問權限, 4 個訪問範圍, 然後將全選和範圍在水平和垂直方向上
分別按排從小到大或從大到小的順序排列, 就很容易畫出上面的圖了。 - Overload 和 Override 的區別。 Overloaded 的方法是否可以改變返回值的類型?
Overload 是重載的意思, Override 是覆蓋的意思, 也就是重寫。
重載 Overload 表示同一個類中可以有多個名稱相同的方法, 但這些方法的參數列表各不相
同(即參數個數或類型不同) 。
重寫 Override 表示子類中的方法可以與父類中的某個方法的名稱和參數完全相同,通過子類
創建的實例對象調用這個方法時, 將調用子類中的定義方法, 這相當於把父類中定義的那個
完全相同的方法給覆蓋了, 這也是面向對象編程的多態性的一種表現。 子類覆蓋父類的方法
時, 只能比父類拋出更少的異常, 或者是拋出父類拋出的異常的子異常, 因爲子類可以解決
父類的一些問題, 不能比父類有更多的問題。 子類方法的訪問權限只能比父類的更大, 不能
更小。 如果父類的方法是 private 類型, 那麼, 子類則不存在覆蓋的限制, 相當於子類中增
加了一個全新的方法。
至於 Overloaded 的方法是否可以改變返回值的類型這個問題, 要看你倒底想問什麼呢? 這
個題目很模糊。 如果幾個 Overloaded 的方法的參數列表不一樣, 它們的返回者類型當然也
可以不一樣。 但我估計你想問的問題是: 如果兩個方法的參數列表完全一樣, 是否可以讓它
們的返回值不同來實現重載 Overload。 這是不行的, 我們可以用反證法來說明這個問題, 因
爲我們有時候調用一個方法時也可以不定義返回結果變量, 即不要關心其返回結果, 例如,
我們調用 map.remove(key)方法時, 雖然 remove 方法有返回值, 但是我們通常都不會定義接
收返回結果的變量, 這時候假設該類中有兩個名稱和參數列表完全相同的方法, 僅僅是返回
類型不同, java 就無法確定編程者倒底是想調用哪個方法了, 因爲它無法通過返回結果類型
來判斷。
override 可以翻譯爲覆蓋, 從字面就可以知道, 它是覆蓋了一個方法並且對其重寫, 以求達
到不同的作用。 對我們來說最熟悉的覆蓋就是對接口方法的實現, 在接口中一般只是對方法
進行了聲明, 而我們在實現時, 就需要實現接口聲明的所有方法。除了這個典型的用法以外,
我們在繼承中也可能會在子類覆蓋父類中的方法。 在覆蓋要注意以下的幾點:
1、 覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配, 才能達到覆蓋的效果;
2、 覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
3、 覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致, 或者是其子類;北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090
4、 被覆蓋的方法不能爲 private, 否則在其子類中只是新定義了一個方法, 並沒有對其進行
覆蓋。
overload 對我們來說可能比較熟悉, 可以翻譯爲重載, 它是指我們可以定義一些名稱相同的
方法, 通過定義不同的輸入參數來區分這些方法, 然後再調用時, VM 就會根據不同的參數
樣式, 來選擇合適的方法執行。 在使用重載要注意以下的幾點:
1、 在使用重載時只能通過不同的參數樣式。 例如, 不同的參數類型, 不同的參數個數, 不
同的參數順序(當然, 同一方法內的幾個參數類型必須不一樣, 例如可以是 fun(int,float),
但是不能爲 fun(int,int)) ;
2、 不能通過訪問權限、 返回類型、 拋出的異常進行重載;
3、 方法的異常類型和數目不會對重載造成影響;
4、 對於繼承來說, 如果某一方法在父類中是訪問權限是 priavte, 那麼就不能在子類對其進
行重載, 如果定義的話, 也只是定義了一個新方法, 而不會達到重載的效果。