最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java面試題沖刺第五天--基礎(chǔ)篇2

 更新時(shí)間:2021年07月13日 15:07:58   作者:_陳哈哈  
這篇文章主要為大家分享了最有價(jià)值的三道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下

面試題1:說一下抽象類和接口有哪些區(qū)別?

正經(jīng)回答:

抽象類和接口的主要區(qū)別:

從設(shè)計(jì)層面來說,抽象類是對類的抽象,是一種模板設(shè)計(jì);接口是行為的抽象,是一種行為的規(guī)范。

  • 一個(gè)類可以有多個(gè)接口 只能有繼承一個(gè)父類
  • 抽象類可以有構(gòu)造方法,接口中不能有構(gòu)造方法。
  • 抽象類中可以有普通成員變量,接口中沒有普通成員
  • 變量接口里邊全部方法都必須是abstract的;抽象類的可以有實(shí)現(xiàn)了的方法
  • 抽象類中的抽象方法的訪問類型可以是public,protected;但接口中的抽象方法只能是public類型的,并且默認(rèn)即為public abstract類型
  • 抽象類中可以包含靜態(tài)方法,接口中不能包含靜態(tài)方法
  • 抽象類和接口中都可以包含靜態(tài)成員變量,抽象類中的靜態(tài)成員變量的訪問類型可以任意;但接口中定義的變量只能是public static final類型,并且默認(rèn)即為public static final類型。

Java8中接口中引入默認(rèn)方法和靜態(tài)方法,以此來減少抽象類和接口之間的差異

接口和抽象類各有優(yōu)缺點(diǎn),在接口和抽象類的選擇上,必須遵守這樣一個(gè)原則:

行為模型應(yīng)該總是通過接口而不是抽象類定義,所以通常是優(yōu)先選用接口,盡量少用抽象類。

選擇抽象類的時(shí)候通常是如下情況:需要定義子類的行為,又要為子類提供通用的功能。

深入追問:

追問1:說一說你對抽象類的理解吧,他到底是干啥用的

我們常說面向?qū)ο蟮暮诵乃枷胧牵合瘸橄?,后具體。抽象類是含有抽象方法的類,不能被實(shí)例化,抽象類常用作當(dāng)做模板類使用。

接口更多的是在系統(tǒng)架構(gòu)設(shè)計(jì)方法發(fā)揮作用,主要用于定義模塊之間的通信契約。

而抽象類在代碼實(shí)現(xiàn)方面發(fā)揮作用,可以實(shí)現(xiàn)代碼的重用,例如,模板方法設(shè)計(jì)模式是抽象類的一個(gè)典型應(yīng)用,假設(shè)某個(gè)項(xiàng)目的所有Servlet類都要用相同的方式進(jìn)行權(quán)限判斷、記錄訪問日志和處理異常,那么就可以定義一個(gè)抽象的基類,讓所有的Servlet都繼承這個(gè)抽象基類,在抽象基類的service方法中完成權(quán)限判斷、記錄訪問日志和處理異常的代碼,在各個(gè)子類中只是完成各自的業(yè)務(wù)邏輯代碼。父類方法中間的某段代碼不確定,再留給子類干,就用模板方法設(shè)計(jì)模式。

追問2:用抽象類實(shí)現(xiàn)一個(gè)接口,和普通類實(shí)現(xiàn)接口會有什么不同么?

一般來說我們使用普通類來實(shí)現(xiàn)接口,這個(gè)普通類就必須實(shí)現(xiàn)接口中所有的方法,這樣的結(jié)果就是普通類中就需要實(shí)現(xiàn)多余的方法,造成代碼冗余。但是如果我們使用的是抽象類來實(shí)現(xiàn)接口,那么就可以只實(shí)現(xiàn)接口中的部分方法,并且當(dāng)其他類繼承這個(gè)抽象類時(shí),仍然可以實(shí)現(xiàn)接口中有但抽象類并未實(shí)現(xiàn)的方法。

如以下代碼,抽象類只是實(shí)現(xiàn)了接口A中的方法a,方法b,但是當(dāng)類C繼承抽象類B時(shí),可以直接實(shí)現(xiàn)接口A中的c方法,有一點(diǎn)需要注意的是,類C中的方法a,方法b都是調(diào)用的父類B的方法a,方法b,不是直接實(shí)現(xiàn)接口的方法a和b。

/**
 *接口
 */
 interface A{
 public void aaa();
 public void bbb();
 public void ccc();
 }
 /**
 *抽象類
 */
 abstract class B implements A{
 public void aaa(){}
 public void bbb(){}
 }
 /**
 * 實(shí)現(xiàn)類
 */
 public class C extends B{
 public void aaa(){}
 public void bbb(){}
 public void ccc(){}
 }

追問3:抽象類能使用 final 修飾嗎?

不能,定義抽象類就是讓其他類繼承的,如果定義為 final 該類就不能被繼承,這樣彼此就會產(chǎn)生矛盾,所以 final 不能修飾抽象類。

在這里插入圖片描述

面試題2:final 在 Java 中有什么作用?

正經(jīng)回答:

用于修飾類、方法和屬性;

1、修飾類

當(dāng)用final修飾類的時(shí),表明該類不能被其他類所繼承。需要注意的是:final類中所有的成員方法都會隱式的定義為final方法。

2、修飾方法

使用final方法的原因主要是把方法鎖定,以防止繼承類對其進(jìn)行更改或重寫。

若父類中final方法的訪問權(quán)限為private,將導(dǎo)致子類中不能直接繼承該方法,因此,此時(shí)可以在子類中定義相同方法名的函數(shù),此時(shí)不會與重寫final的矛盾,而是在子類中重新地定義了新方法。

class A{
    private final void getName(){
        System.out.println("getName - A");
    }
}
public class B extends A{
    public void getName(){
        System.out.println("getName - B");
    }
    public void main(String[]args){
        this.getName(); // 日志輸出:getName - B
    }
}

3、修飾變量

當(dāng)final修飾一個(gè)基本數(shù)據(jù)類型時(shí),表示該基本數(shù)據(jù)類型的值一旦在初始化后便不能發(fā)生變化;如果final修飾一個(gè)引用類型時(shí),則在對其初始化之后便不能再讓其指向其他對象了,但該引用所指向的對象的內(nèi)容是可以發(fā)生變化的。本質(zhì)上是一回事,因?yàn)橐玫闹凳且粋€(gè)地址,final要求值,即地址的值不發(fā)生變化。

final修飾一個(gè)成員變量(屬性),必須要顯示初始化。這里有兩種初始化方式,一種是在變量聲明的時(shí)候初始化;第二種方法是在聲明變量的時(shí)候不賦初值,但是要在這個(gè)變量所在的類的所有的構(gòu)造函數(shù)中對這個(gè)變量賦初值。

當(dāng)函數(shù)的參數(shù)類型聲明為final時(shí),說明該參數(shù)是只讀型的。即你可以讀取使用該參數(shù),但是無法改變該參數(shù)的值。

深入追問:

追問1:能分別說一下final、finally、finalize的區(qū)別么?

  • final可以修飾類、變量、方法,修飾類表示該類不能被繼承、修飾方法表示該方法不能被重寫、修飾變量表示該變量是一個(gè)常量不能被重新賦值。
  • finally一般作用在try-catch代碼塊中,在處理異常的時(shí)候,通常我們將一定要執(zhí)行的代碼方法finally代碼塊中,表示不管是否出現(xiàn)異常,該代碼塊都會執(zhí)行,一般用來存放一些關(guān)閉資源的代碼。當(dāng)然,還有多種情況走不了finally~
  • finalize是一個(gè)方法,屬于Object類的一個(gè)方法,而Object類是所有類的父類,該方法一般由垃圾回收器來調(diào)用,當(dāng)我們調(diào)用System.gc() 方法的時(shí)候,由垃圾回收器調(diào)用finalize(),回收垃圾,一個(gè)對象是否可回收的最后判斷。

面試題3:你對Java序列化了解么?

正經(jīng)回答:

序列化過程:

是指把一個(gè)Java對象變成二進(jìn)制內(nèi)容,實(shí)質(zhì)上就是一個(gè)byte[]數(shù)組。

因?yàn)樾蛄谢罂梢园裝yte[]保存到文件中,或者把byte[]通過網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)程(IO),這樣,就相當(dāng)于把Java對象存儲到文件或者通過網(wǎng)絡(luò)傳輸出去了。

反序列化過程:

把一個(gè)二進(jìn)制內(nèi)容(也就是byte[]數(shù)組)變回Java對象。有了反序列化,保存到文件中的byte[]數(shù)組又可以“變回”Java對象,或者從網(wǎng)絡(luò)上讀取byte[]并把它“變回”Java對象。

以下是一些使用序列化的示例:

以面向?qū)ο蟮姆绞綄?shù)據(jù)存儲到磁盤上的文件,例如,Redis存儲Student對象的列表。

將程序的狀態(tài)保存在磁盤上,例如,保存游戲狀態(tài)。

通過網(wǎng)絡(luò)以表單對象形式發(fā)送數(shù)據(jù),例如,在聊天應(yīng)用程序中以對象形式發(fā)送消息。

一個(gè)Java對象要能序列化,必須實(shí)現(xiàn)一個(gè)特殊的java.io.Serializable接口,它的定義如下:

public interface Serializable {
}

Serializable接口沒有定義任何方法,它是一個(gè)空接口。我們把這樣的空接口稱為“標(biāo)記接口”(Marker Interface),實(shí)現(xiàn)了標(biāo)記接口的類僅僅是給自身貼了個(gè)“標(biāo)記”,并沒有增加任何方法。

深入追問:

追問1:Java序列化是如何工作的?

當(dāng)且僅當(dāng)對象的類實(shí)現(xiàn)java.io.Serializable接口時(shí),該對象才有資格進(jìn)行序列化。可序列化 是一個(gè)標(biāo)記接口(不包含任何方法),該接口告訴Java虛擬機(jī)(JVM)該類的對象已準(zhǔn)備好寫入持久性存儲或通過網(wǎng)絡(luò)進(jìn)行讀取。

默認(rèn)情況下,JVM負(fù)責(zé)編寫和讀取可序列化對象的過程。序列化/反序列化功能通過對象流類的以下兩種方法公開:

ObjectOutputStream。writeObject(Object):將可序列化的對象寫入輸出流。如果要序列化的某些對象未實(shí)現(xiàn)Serializable接口,則此方法將引發(fā)NotSerializableException。

ObjectInputStream。readObject():從輸入流讀取,構(gòu)造并返回一個(gè)對象。如果找不到序列化對象的類,則此方法將引發(fā)ClassNotFoundException。

如果序列化使用的類有問題,則這兩種方法都將引發(fā)InvalidClassException,如果發(fā)生I / O錯(cuò)誤,則將引發(fā)IOException。無論NotSerializableExceptionInvalidClassException是子類IOException異常。

讓我們來看一個(gè)簡單的例子。以下代碼將String對象序列化為名為“ data.ser”的文件。字符串對象是可序列化的,因?yàn)镾tring類實(shí)現(xiàn)了Serializable 接口:

String filePath = "data.ser";
String message = "Java Serialization is Cool";
try (
    FileOutputStream fos = new FileOutputStream(filePath);
    ObjectOutputStream outputStream = new ObjectOutputStream(fos);
) {
    outputStream.writeObject(message);
} catch (IOException ex) {
    System.err.println(ex);
}

以下代碼反序列化文件“ data.ser”中的String對象:

String filePath = "data.ser";
try (
    FileInputStream fis = new FileInputStream(filePath);
    ObjectInputStream inputStream = new ObjectInputStream(fis);
) {
    String message = (String) inputStream.readObject();
    System.out.println("Message: " + message);
} catch (ClassNotFoundException ex) {
    System.err.println("Class not found: " + ex);
} catch (IOException ex) {
    System.err.println("IO error: " + ex);
}

請注意,readObject()返回一個(gè)Object類型的對象,因此您需要將其強(qiáng)制轉(zhuǎn)換為可序列化的類,在這種情況下為String類。

讓我們看一個(gè)涉及使用自定義類的更復(fù)雜的示例。

給定以下學(xué)生班:

import java.io.*;
import java.util.*;
/**
 * Student.java
 * @author chenhh
 */
public class Student extends Person implements Serializable {
    public static final long serialVersionUID = 1234L;
    private long studentId;
    private String name;
    private transient int age;
    public Student(long studentId, String name, int age) {
        super();
        this.studentId = studentId;
        this.name = name;
        this.age = age;
        System.out.println("Constructor");
    }
    public String toString() {
        return String.format("%d - %s - %d", studentId, name, age);
    }
}

如上面代碼,你會發(fā)現(xiàn)兩點(diǎn):

long serialVersionUID類型的常量。

成員變量age被標(biāo)記為transient。 下面兩個(gè)問題讓我們搞明白它們。

追問2:什么是serialVersionUID常數(shù)

serialVersionUID是一個(gè)常數(shù),用于唯一標(biāo)識可序列化類的版本。從輸入流構(gòu)造對象時(shí),JVM在反序列化過程中檢查此常數(shù)。如果正在讀取的對象的serialVersionUID與類中指定的序列號不同,則JVM拋出InvalidClassException。這是為了確保正在構(gòu)造的對象與具有相同serialVersionUID的類兼容。

請注意,serialVersionUID是可選的。這意味著如果您不顯式聲明Java編譯器,它將生成一個(gè)。

那么,為什么要顯式聲明serialVersionUID呢?

原因是:自動(dòng)生成的serialVersionUID是基于類的元素(成員變量,方法,構(gòu)造函數(shù)等)計(jì)算的。如果這些元素之一發(fā)生更改,serialVersionUID也將更改。想象一下這種情況:

  • 您編寫了一個(gè)程序,將Student類的某些對象存儲到文件中。Student類沒有顯式聲明的serialVersionUID。
  • 有時(shí),您更新了Student類(例如,添加了一個(gè)新的私有方法),現(xiàn)在自動(dòng)生成的serialVersionUID也被更改了。
  • 您的程序無法反序列化先前編寫的Student對象,因?yàn)槟抢锏膕erialVersionUID不同。JVM拋出InvalidClassException。

這就是為什么建議為可序列化類顯式添加serialVersionUID的原因。

追問3、那你知道什么是瞬時(shí)變量么?

在上面的Student類中,您看到成員變量age被標(biāo)記為transient,對嗎?JVM 在序列化過程中跳過瞬態(tài)變量。這意味著在序列化對象時(shí)不會存儲age變量的值。

因此,如果成員變量不需要序列化,則可以將其標(biāo)記為瞬態(tài)。

以下代碼將Student對象序列化為名為“ students.ser”的文件:

String filePath = "students.ser";
Student student = new Student(123, "John", 22);
try (
    FileOutputStream fos = new FileOutputStream(filePath);
    ObjectOutputStream outputStream = new ObjectOutputStream(fos);
) {
    outputStream.writeObject(student);
} catch (IOException ex) {
    System.err.println(ex);
}

請注意,在序列化對象之前,變量age的值為22。

下面的代碼從文件中反序列化Student對象:

String filePath = "students.ser";
try (
    FileInputStream fis = new FileInputStream(filePath);
    ObjectInputStream inputStream = new ObjectInputStream(fis);
) {
    Student student = (Student) inputStream.readObject();
    System.out.println(student);
} catch (ClassNotFoundException ex) {
    System.err.println("Class not found: " + ex);
} catch (IOException ex) {
    System.err.println("IO error: " + ex);
}

此代碼將輸出以下輸出:

1個(gè) 123 - John - 0

總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Java框架入門之簡單介紹SpringBoot框架

    Java框架入門之簡單介紹SpringBoot框架

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著SpringBoot框架展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • SpringBoot?Web開發(fā)之請求響應(yīng)、分層解耦問題記錄

    SpringBoot?Web開發(fā)之請求響應(yīng)、分層解耦問題記錄

    在?Spring?Boot?的?Web?請求響應(yīng)處理中,Servlet?起著關(guān)鍵的作用,Servlet?是?Java?Web?開發(fā)中的基本組件,主要負(fù)責(zé)處理客戶端的請求并生成響應(yīng),這篇文章主要介紹了SpringBoot?Web開發(fā)之請求響應(yīng),分層解耦,需要的朋友可以參考下
    2024-08-08
  • SpringBoot導(dǎo)出Excel表格到指定路徑的代碼詳解

    SpringBoot導(dǎo)出Excel表格到指定路徑的代碼詳解

    Spring Boot導(dǎo)出Excel通常涉及到使用第三方庫如Apache POI或者XlsxWriter等,它們能幫助你在Spring應(yīng)用中生成并下載Excel文件,那么SpringBoot如何導(dǎo)出Excel表格到指定路徑,本文將給大家詳細(xì)的介紹一下
    2024-07-07
  • SpringBoot中打印SQL語句的幾種方法實(shí)現(xiàn)

    SpringBoot中打印SQL語句的幾種方法實(shí)現(xiàn)

    本文主要介紹了SpringBoot中打印SQL語句的幾種方法實(shí)現(xiàn),,通過打印SQL語句可以幫助開發(fā)人員快速了解數(shù)據(jù)庫的操作情況,進(jìn)而進(jìn)行性能分析和調(diào)試,感興趣的可以了解一下
    2023-11-11
  • Java集合框架迭代器Iterator實(shí)現(xiàn)原理解析

    Java集合框架迭代器Iterator實(shí)現(xiàn)原理解析

    這篇文章主要介紹了Java集合框架迭代器Iterator實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • NoHttpResponseException異常解決優(yōu)化HttpClient配置以避免連接問題

    NoHttpResponseException異常解決優(yōu)化HttpClient配置以避免連接問題

    這篇文章主要為大家介紹了NoHttpResponseException異常解決,優(yōu)化HttpClient配置以避免連接問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • SpringBoot密碼加密的實(shí)現(xiàn)示例

    SpringBoot密碼加密的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot密碼加密的實(shí)現(xiàn)示例,包括引入依賴、配置加密工具、生成加密密鑰、加密密碼、配置解密,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • mybatis動(dòng)態(tài)sql之Map參數(shù)的講解

    mybatis動(dòng)態(tài)sql之Map參數(shù)的講解

    今天小編就為大家分享一篇關(guān)于mybatis動(dòng)態(tài)sql之Map參數(shù)的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的實(shí)現(xiàn)

    SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的實(shí)現(xiàn)

    本文主要介紹了SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 使用Postman傳遞arraylist數(shù)據(jù)給springboot方式

    使用Postman傳遞arraylist數(shù)據(jù)給springboot方式

    這篇文章主要介紹了使用Postman傳遞arraylist數(shù)據(jù)給springboot方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評論

合江县| 萨嘎县| 龙陵县| 汶上县| 恩平市| 漯河市| 连江县| 长治县| 潞西市| 淮滨县| 化德县| 盐源县| 漳州市| 武清区| 普定县| 溧水县| 拉萨市| 昌邑市| 治多县| 南丰县| 锡林郭勒盟| 大田县| 曲麻莱县| 郧西县| 呼伦贝尔市| 淮南市| 城固县| 金门县| 大英县| 高雄县| 杨浦区| 利川市| 德昌县| 美姑县| 巍山| 宁乡县| 久治县| 闽侯县| 黄冈市| 茶陵县| 衡山县|