按照慣例,2 月份是一波面試找工作的高峯期,我就是 2014 年的 2 月份回的三線城市。 不過,當時傻乎乎的沒有刷面試題,幸好三線城市要求的面試題不是很過分,能答得上來。
如果你年後也有跳槽的打算,我還是建議你提前做好準備。今天,我爲你精心準備了 13 道 OOP 方面的 Java 面試題,如果你覺得有收穫的話,別忘了點贊分享啊。
第一題,Java 是什麼?
Java 是一門計算機編程語言,高級、健壯、面向對象,並且非常安全。它由 Sun 公司在 1995 年開發,主力開發叫 James Gosling,被稱爲 Java 之父。
其實 Oracle 官網有一段關於 Java 的定義,是這樣的:
Java 是由 Sun Microsystems 在 1995 年首先發布的編程語言和計算平臺。有許多應用程序和 Web 站點只有在安裝 Java 後才能正常工作,而且這樣的應用程序和 Web 站點日益增多。Java 快速、安全、可靠。從筆記本電腦到數據中心,從遊戲控制檯到科學超級計算機,從手機到互聯網,Java 無處不在!
第二題,什麼是 OOP ?
面向對象編程——Object Oriented Programming,簡稱 OOP,是一種程序設計思想。OOP 把對象作爲程序的基本單元,一個對象包含了成員變量和操作成員變量的方法。
面向過程的程序設計把計算機程序視爲一系列的命令集合,即一組方法的順序執行。爲了簡化程序設計,面向過程把方法繼續切分爲子方法,即把大塊方法通過切割成小塊方法來降低系統的複雜度。
而面向對象的程序設計把計算機程序視爲一組對象的集合,而每個對象都可以接收其他對象發過來的消息,並處理這些消息,計算機程序的執行就是一系列消息在各個對象之間傳遞。
OOP 有三大特徵:
- 封裝
- 多態
- 繼承
面向對象編程的語言不只有 Java,還有 C#、C++、Python 等等。如果面試官有閒情逸致的話,還可以給他講一個小學課本上的《女媧造人》。
女媧要造人,首先要想的是所造的人長什麼樣,女媧爲了方便就按照自己的樣子捏了一個模板,後面她只需要按照這個模板來捏就行。在 OOP 中,這個模板就稱爲類。
女媧按照模板(類)捏了一個人,這個人就是具體的對象;人有很多器官,比如眼睛、耳朵、鼻子、大腦、手和腳,同樣還有年齡、身高,女媧爲了區別每個人就會給每個對象不同的基本特徵。另外,捏出的人要會走路,會喫飯,會幹活等行爲方式。
在 OOP 中,對象的基本特徵稱爲成員變量,行爲方式稱爲方法,所以類是由成員變量和方法構成的;成員變量最好隱藏起來,當需要人做什麼的時候,就通過方法來完成。暴露方法的行爲稱爲封裝。
女媧想着一個人太無聊,就給它捏個伴,暫且就叫它男人和女人吧,男人和女人都是根據這個模板來的,有着一樣的基本特徵和行爲,只是某些特徵(成員變量)和行爲(方法)在實現上有差異,那麼這種根據模板而捏造不同實現細節的類的行爲稱爲多態,就是一個模板有男人和女人兩種形態。
女媧爲了省事就讓人類自己繁衍後代,就有了父子的關係,子類具有父類的基本特徵和行爲,子類也可以改變這些特徵和行爲,這種父子關係實現稱爲繼承。
第三題,Java 有哪些特性?
- 面向對象。
參照第二題。
- 平臺無關性。
Java 是“一次編寫,到處運行(Write Once,Run any Where)”的語言,因此採用 Java 語言編寫的程序具有很好的可移植性,而保證這一點的正是 Java 的虛擬機機制。在引入虛擬機之後,Java 語言在不同的平臺上運行不需要重新編譯。
Java 語言使用 Java 虛擬機機制屏蔽了具體平臺的相關信息,使得 Java 語言編譯的程序只需要生成虛擬機上的目標代碼,就可以在多種平臺上不加修改地運行。
- 簡單性。
Java 捨棄了很多 C++ 中難以理解的特性,比如操作符的重載和多繼承等,而且 Java 語言加入了垃圾回收機制,解決了程序員需要管理內存的問題,使編程變得更加簡單。
- 支持多線程。
Java 支持多個線程同時執行,並提供多線程之間的同步機制。
- 健壯性。
Java 的強類型機制、異常處理、垃圾回收機制等都是 Java 健壯性的重要保證。
- 高性能。
隨着 JIT(Just in Time,即時編譯)的發展,Java 的運行速度也越來越快。
第四題,Java 是 100% 面向對象嗎?
不是的。Java 有 8 中基本數據類型,包括 boolean、char、byte、short、int、long、float 和 double,它們都不是對象。
第五題,什麼是抽象?
抽象是指爲了某種目的,對一個概念或一種現象包含的信息進行過濾,移除不相關的信息,只保留與某種最終目的相關的信息。例如,一個皮質的足球,我們可以過濾掉它的質料,得到更一般性的概念,也就是球。從另外一個角度看,抽象就是簡化事物,抓住事物本質的過程。
在 Java 中,可以通過兩種形式來體現抽象:抽象類和接口。
定義抽象類的時候需要用到關鍵字 abstract,放在 class 關鍵字前。
public abstract class AbstractPlayer {
abstract void play();
}
通過 extends 關鍵字可以繼承抽象類。
public class BasketballPlayer extends AbstractPlayer {
@Override
void play() {
System.out.println("我是張伯倫,籃球場上得過 100 分");
}
}
接口是通過 interface 關鍵字定義的,它可以包含一些常量和方法。
public interface Electronic {
// 常量
String LED = "LED";
// 抽象方法
int getElectricityUse();
// 靜態方法
static boolean isEnergyEfficient(String electtronicType) {
return electtronicType.equals(LED);
}
// 默認方法
default void printDescription() {
System.out.println("電子");
}
}
通過 implements 關鍵字可以實現一個接口。
public class Computer implements Electronic {
public static void main(String[] args) {
new Computer();
}
@Override
public int getElectricityUse() {
return 0;
}
}
第六題,什麼是封裝?
封裝將類的某些信息隱藏在類的內部,不允許外部程序直接訪問,只能通過該類提供的方法來實現對隱藏信息的操作和訪問。
例如,一臺計算機內部極其複雜,有主板、CPU、硬盤和內存, 而一般用戶不需要了解它的內部細節,不需要知道主板的型號、CPU 主頻、硬盤和內存的大小,於是計算機制造商用機箱把計算機封裝起來,對外提供了一些接口,如鼠標、鍵盤和顯示器等,這樣做了以後,用戶使用計算機就非常方便了。
封裝最主要的功能在於我們能修改自己的實現代碼,而不用修改那些調用我們代碼的程序片段。
實現封裝的具體步驟如下:
- 修改成員變量的可見性來限制對屬性的訪問,一般設爲 private。
- 爲每個成員變量創建一對賦值(setter)方法和取值(getter)方法,一般設爲 public,用於屬性的讀寫。
- 在賦值和取值方法中,加入成員變量控制語句(對成員變量值的合法性進行判斷)。
public class Student {
private int id;
private String name;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public static void main(String args[]) {
Student student = new Student();
student.setId(1034);
student.setName("沉默王二");
System.out.println("學生 id " + student.getId());
System.out.println("學生姓名 " + student.getName());
}
}
第七題,抽象和封裝有什麼區別?
抽象只關注對象的相關數據,並隱藏所有可能無關行爲的細節。它隱藏了背景細節,但強調了要點,以減少複雜性並提高效率。抽象關注的是思想而非事件。
封裝將成員變量和方法綁定到單個類中,同時限制了對某些成員變量的訪問。封裝意味着隱藏成員變量以保護成員變量免受外部訪問,從而使應用程序某一部分的更改不會影響其他部分。
抽象和封裝在“定義”上的差異 —— 抽象通過隱藏不相關的細節來強調對象的所有基本方面,以提高效率並消除複雜性。封裝是一種數據隱藏機制,它將數據包裝在一個膠囊中以限制來自外界的訪問。
抽象和封裝在“功能”上的差異 —— 抽象僅強調使複雜程序更簡單的基本功能,而封裝則是將成員變量和操作成員變量的方法綁定到單個類中。
抽象和封裝在“實現”上的區別 —— 抽象由抽象類和接口實現,而封裝則通過訪問權限修飾符來實現。
第八題,什麼是繼承?
繼承是面向對象編程中非常強大的一種機制,在 Java 中使用 extends 關鍵字來表示繼承關係。當創建一個類時,總是在繼承,如果沒有明確指出要繼承的類,總是隱式地從根類 Object 進行繼承。
class Person {
public Person() {
}
}
class Man extends Person {
public Man() {
}
}
Person 類隱式地繼承了 Object 類,因此 Person 類也自動地擁有了 hashCode()
、equals()
、toString()
等方法。
Man 類繼承了 Person 類,這樣一來,Person 類就稱爲父類,Man類就稱爲子類。如果兩個類存在繼承關係,子類會自動繼承父類的方法和成員變量,在子類中可以調用父類的方法和成員變量。
Java 只允許單繼承,也就是說一個類最多隻能顯式地繼承一個父類。但一個類卻可以被多個類繼承,也就是說一個類可以擁有多個子類。
第九題,什麼是多態?
多態是同一個行爲具有多個不同表現形式的能力,可以使程序具有良好的擴展性,並可以對所有類的對象進行通用處理。
在繼承關係中,子類如果定義了一個與父類方法簽名完全相同的方法,被稱爲方法重寫(Override)。
public class Shape {
public void getArea() {
System.out.println("形狀");
}
}
public class Rectangle extends Shape {
@Override
public void getArea() {
System.out.println("矩形");
}
public static void main(String args[]) {
Shape shape = new Rectangle();
shape.getArea();
}
}
方法重寫和方法重載(Overload)不同,如果一個類有多個名字相同但參數個數不同的方法,我們通常稱這些方法爲方法重載。
public class Calculator {
public int subtract(int a, int b) {
return a - b;
}
public double subtract(double a, double b) {
return a - b;
}
public static void main(String args[]) {
Calculator calculator = new Calculator();
System.out.println("150 和 12 相差 " + calculator.subtract(150, 12));
System.out.println("15.5 和 15.4 相差 " + calculator.subtract(15.50, 15.40));
}
}
通過下面這幅圖可以瞭解到,子類 Circle、Triangle、Square 繼承了父類 Shape,並且重寫了 draw()
方法用於繪製不同的形狀。
方法重寫用於提供父類已經聲明的方法的特殊實現,是實現多態的基礎條件。
第十題,怎麼區分關聯、聚合、組合?
能體現關聯(Association)關係的例子有客戶和訂單之間的關係、公司和員工之間的關係、用戶與電腦之間的關係。關聯關係所涉及的兩個類是處在同一層次上的。
class Computer {
public void develop() {
}
}
class Person {
private Computer computer;
public Person(Computer computer) {
this.computer = computer;
}
public void work() {
computer.develop();
}
}
聚合(Aggregation)是整體和個體之間的關係。聚合關係所涉及的兩個類是處在不平等層次上的,一個代表整體,另一個代表部分,體現的是 has-a 的關係,比如班級和學生,班級如果不存在了學生還可以存在。
再比如說任何地址之間的關係。
public class Person {
private Address address;
}
class Address {
private String city;
private String state;
private String country;
}
組合(Composition)關係是比聚合關係更強的關係,體現的是 is-a 的關係,比如說房子與房間,房子如果不存在了房間就沒有存在的必要了。
再比如說車與輪胎、車門、車窗之間的關係。
public class Car {
private Tire[] tires;
private Door[] doors;
private Window[] windows;
}
class Tire {
}
class Door {
}
class Steering {
}
class Window {
}
好了,關於面向對象編程方面的面試題就先了解到這吧,如果能夠對你在年後的面試中助一臂之力那就太好了,如果不能,溫故一下封裝、繼承、多態方面的知識也是很有必要的。
PS:好朋友 Guide 哥的面試突擊第四版可以下載了,GitHub 標星 95.3k,真的非常牛逼。第四版增加/修改的內容如下圖所示。
如果你不知道獲取方式的話,我提供給你一個:
鏈接:https://pan.baidu.com/s/19voBuI_zR4_E9qrk0iAUYA 密碼:413c
❤看完兩件事:
如果你覺得這篇內容對你挺有幫助,我想邀請你幫我兩個忙:
- 點贊,讓更多的人也能看到這篇內容(收藏不點贊,等於耍流氓😁)
- 關注我,讓我們成爲長期關係
謝謝你的支持!