精心爲你準備了 10 道 OOP 方面的 Java 面試題

按照慣例,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

❤看完兩件事

如果你覺得這篇內容對你挺有幫助,我想邀請你幫我兩個忙:

  1. 點贊,讓更多的人也能看到這篇內容(收藏不點贊,等於耍流氓😁)
  2. 關注我,讓我們成爲長期關係

謝謝你的支持!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章