[Java大厂必备面试题] 点滴促就辉煌, 每日三题【Day5】:基础篇2

本文主要是介绍[Java大厂必备面试题] 点滴促就辉煌, 每日三题【Day5】:基础篇2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   新的搬砖一天,我想问一下各位老哥都是一样 天天迷茫的么,

我不能迷茫,我是大家的光啊,迪迦! ..............

就让我成为黑暗的那一缕光明!                        

 快乐的源泉,欢迎小伙伴来加入!


  • 目录

    面试题1:说一下抽象类和接口有哪些区别?

    正经回答:

    深入追问:

    追问1:说一说你对抽象类的理解吧,他到底是干啥用的:

    追问2:用抽象类实现一个接口,和普通类实现接口会有什么不同么?

    追问3:抽象类能使用 final 修饰吗?

    面试题2:final 在 Java 中有什么作用?

    正经回答:

    深入追问:

    追问1:能分别说一下final、finally、finalize的区别么?

    面试题3:你对Java序列化了解么?

    正经回答:

    深入追问:

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

    追问2:什么是serialVersionUID常数

    追问3、那你知道什么是瞬时变量么?

    每日小结



=============================================================================================

  本栏目Java开发岗高频面试题主要出自以下各技术栈:Java基础知识、集合容器、并发编程、JVM、Spring全家桶、MyBatis等ORMapping框架、MySQL数据库、Redis缓存、RabbitMQ消息队列、Linux操作技巧等。

=============================================================================================

面试题1:说一下抽象类和接口有哪些区别?

正经回答:

抽象类和接口的主要区别:

  •   从设计层面来说,抽象类是对类的抽象,是一种模板设计;接口是行为的抽象,是一种行为的规范。
  • 一个类可以有多个接口 只能有继承一个父类
  • 抽象类可以有构造方法,接口中不能有构造方法。
  • 抽象类中可以有普通成员变量,接口中没有普通成员变量
  • 接口里边全部方法都必须是abstract的;抽象类的可以有实现了的方法
  • 抽象类中的抽象方法的访问类型可以是public,protected;但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型
  • 抽象类中可以包含静态方法,接口中不能包含静态方法
  • 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意;但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。 

Java8中接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。

接口和抽象类各有优缺点,在接口和抽象类的选择上,必须遵守这样一个原则:

  • 行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
  • 选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能。

深入追问:

追问1:说一说你对抽象类的理解吧,他到底是干啥用的:

我们常说面向对象的核心思想是:先抽象,后具体。抽象类是含有抽象方法的类,不能被实例化,抽象类常用作当做模板类使用。

  接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。

  而抽象类在代码实现方面发挥作用,可以实现代码的重用,例如,模板方法设计模式是抽象类的一个典型应用,假设某个项目的所有Servlet类都要用相同的方式进行权限判断、记录访问日志和处理异常,那么就可以定义一个抽象的基类,让所有的Servlet都继承这个抽象基类,在抽象基类的service方法中完成权限判断、记录访问日志和处理异常的代码,在各个子类中只是完成各自的业务逻辑代码。父类方法中间的某段代码不确定,再留给子类干,就用模板方法设计模式。
 

追问2:用抽象类实现一个接口,和普通类实现接口会有什么不同么?

 一般来说我们使用普通类来实现接口,这个普通类就必须实现接口中所有的方法,这样的结果就是普通类中就需要实现多余的方法,造成代码冗余。但是如果我们使用的是抽象类来实现接口,那么就可以只实现接口中的部分方法,并且当其他类继承这个抽象类时,仍然可以实现接口中有但抽象类并未实现的方法。

  如以下代码,抽象类只是实现了接口A中的方法a,方法b,但是当类C继承抽象类B时,可以直接实现接口A中的c方法,有一点需要注意的是,类C中的方法a,方法b都是调用的父类B的方法a,方法b,不是直接实现接口的方法a和b。
 

/**
 *接口
 */
 interface A{
 public void aaa();
 public void bbb();
 public void ccc();
 }
 /**
 *抽象类
 */
 abstract class B implements A{
 public void aaa(){}
 public void bbb(){}
 }
 /**
 * 实现类
 */
 public class C extends B{
 public void aaa(){}
 public void bbb(){}
 public void ccc(){}
 }

追问3:抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类。

面试题2:final 在 Java 中有什么作用?

正经回答:

用于修饰类、方法和属性;

1、修饰类

  当用final修饰类的时,表明该类不能被其他类所继承。需要注意的是:final类中所有的成员方法都会隐式的定义为final方法。

 

 2、修饰方法

使用final方法的原因主要是把方法锁定,以防止继承类对其进行更改或重写。

  若父类中final方法的访问权限为private,将导致子类中不能直接继承该方法,因此,此时可以在子类中定义相同方法名的函数,此时不会与重写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、修饰变量

 当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变化;如果final修饰一个引用类型时,则在对其初始化之后便不能再让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。本质上是一回事,因为引用的值是一个地址,final要求值,即地址的值不发生变化。

  final修饰一个成员变量(属性),必须要显示初始化。这里有两种初始化方式,一种是在变量声明的时候初始化;第二种方法是在声明变量的时候不赋初值,但是要在这个变量所在的类的所有的构造函数中对这个变量赋初值。

  当函数的参数类型声明为final时,说明该参数是只读型的。即你可以读取使用该参数,但是无法改变该参数的值。
 

深入追问:

追问1:能分别说一下final、finally、finalize的区别么?

  • final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
  • finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。当然,还有多种情况走不了finally~
  • finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。

课间学习:  口水鸡

口水鸡做法:

鸡腿2-3个,生姜1小块,花生米20克,花椒3克,八角2个,香叶1片,干红辣椒3个,食盐适量,白糖3克;

第一步,首先准备好鸡腿,将其在室温下解冻后,清洗干净,同时生姜洗净后,去皮,切成片,在锅中添上适量的水,冷水放入洗净的鸡腿,再加上几片生姜,将锅煮开后;

第二步,用勺子将上面的浮沫撇干净,继续煮10分钟的时间,待用筷子扎入鸡腿中,无血水的时候,关火,加上锅盖,焖10分钟,将煮好的鸡腿捞出来,放入在事先准备好的冰水中冷却;

第三步,将其切成块,摆放入盘子中待用,这个时候便可以准备配料,在炒锅中添上适量的食用油,放入花椒、八角和香叶,小火将其中的香味炸出来后,捞出这些香料不要,然后放入花生米;

第四步,继续用小火,慢慢将花生米中的香味炸出来,待花生米被炸至微微开裂的时候,捞出碾碎,在之前的油锅中,放入干红辣椒段,炸香后,将辣椒碎捞出,热油倒入在辣椒粉中,搅拌均匀;

第五步,小碗中放入生抽、辣椒油、米醋、食盐、白糖,搅拌均匀后,浇在盛有鸡肉的盘子中,撒上花生米、蒜末和葱花,即可开始享用。

烹饪小技巧:

1、鸡肉煮制的时间不宜过长,用筷子可以轻松扎入,且无血水的时候即可,煮好鸡腿后,注意不要急着捞出,关火焖一会,鸡肉的口感会更加好;

2、煮好的鸡肉,放入事先准备好的冰水中激一下,这样鸡肉的肉质会变得脆嫩好吃,所以这个步骤一定不能错过,而且注意,浸泡鸡肉的水应当是凉开水,否则不卫生;

3、口水鸡的料汁相当重要,大家要按照食谱中的方法认真去做,这样口水鸡的口感才会更佳,注意料汁可以适当多一点,浇在鸡肉上后,放入冰箱冷藏一下,鸡肉更加脆嫩好吃。


面试题3:你对Java序列化了解么?

正经回答:

序列化过程:

把一个二进制内容(也就是byte[]数组)变回Java对象。有了反序列化,保存到文件中的byte[]数组又可以“变回”Java对象,或者从网络上读取byte[]并把它“变回”Java对象。

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

  • 以面向对象的方式将数据存储到磁盘上的文件,例如,Redis存储Student对象的列表。
  • 将程序的状态保存在磁盘上,例如,保存游戏状态。
  • 通过网络以表单对象形式发送数据,例如,在聊天应用程序中以对象形式发送消息。

一个Java对象要能序列化,必须实现一个特殊的java.io.Serializable接口,它的定义如下:

 public interface Serializable {
}

 Serializable接口没有定义任何方法,它是一个空接口。我们把这样的空接口称为“标记接口”(Marker Interface),实现了标记接口的类仅仅是给自身贴了个“标记”,并没有增加任何方法。

深入追问:

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

 当且仅当对象的类实现java.io.Serializable接口时,该对象才有资格进行序列化。可序列化 是一个标记接口(不包含任何方法),该接口告诉Java虚拟机(JVM)该类的对象已准备好写入持久性存储或通过网络进行读取。

  默认情况下,JVM负责编写和读取可序列化对象的过程。序列化/反序列化功能通过对象流类的以下两种方法公开:

  • ObjectOutputStream。writeObject(Object):将可序列化的对象写入输出流。如果要序列化的某些对象未实现Serializable接口,则此方法将引发NotSerializableException。
  • ObjectInputStream。readObject():从输入流读取,构造并返回一个对象。如果找不到序列化对象的类,则此方法将引发ClassNotFoundException。

  如果序列化使用的类有问题,则这两种方法都将引发InvalidClassException,如果发生I / O错误,则将引发IOException。无论NotSerializableExceptionInvalidClassException是子类IOException异常。

  让我们来看一个简单的例子。以下代码将String对象序列化为名为“ data.ser”的文件。字符串对象是可序列化的,因为String类实现了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()返回一个Object类型的对象,因此您需要将其强制转换为可序列化的类,在这种情况下为String类。

  让我们看一个涉及使用自定义类的更复杂的示例。

  给定以下学生班

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);
    }
}

 如上面代码,你会发现两点:

  • long serialVersionUID类型的常量。
  • 成员变量age被标记为transient。

    下面两个问题让我们搞明白它们。

追问2:什么是serialVersionUID常数

serialVersionUID是一个常数,用于唯一标识可序列化类的版本。从输入流构造对象时,JVM在反序列化过程中检查此常数。如果正在读取的对象的serialVersionUID与类中指定的序列号不同,则JVM抛出InvalidClassException。这是为了确保正在构造的对象与具有相同serialVersionUID的类兼容。

  请注意,serialVersionUID是可选的。这意味着如果您不显式声明Java编译器,它将生成一个。

  那么,为什么要显式声明serialVersionUID呢?

  原因是:自动生成的serialVersionUID是基于类的元素(成员变量,方法,构造函数等)计算的。如果这些元素之一发生更改,serialVersionUID也将更改。想象一下这种情况:

  • 您编写了一个程序,将Student类的某些对象存储到文件中。Student类没有显式声明的serialVersionUID。
  • 有时,您更新了Student类(例如,添加了一个新的私有方法),现在自动生成的serialVersionUID也被更改了。
  • 您的程序无法反序列化先前编写的Student对象,因为那里的serialVersionUID不同。JVM抛出InvalidClassException。

  这就是为什么建议为可序列化类显式添加serialVersionUID的原因。
 

追问3、那你知道什么是瞬时变量么?

 在上面的Student类中,您看到成员变量age被标记为transient,对吗?JVM 在序列化过程中跳过瞬态变量。这意味着在序列化对象时不会存储age变量的值。

  因此,如果成员变量不需要序列化,则可以将其标记为瞬态。

  以下代码将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个
123 - John - 0

每日小结

      再长的路,一步步也能走完;再短的路,不迈开双脚也无法到达。还在咬牙坚持的你,请不要泄气。你的日积月累,早晚会成为别人的望尘莫及。

        如果自己都在偷懒,命运又怎么会认可你。别再虚度光阴,叫醒那个沉睡的自己。记住,只要开始,就永远不晚。

向前走,不回头,一路奋斗

感谢哈哈赞助

https://blog.csdn.net/qq_39390545/article/details/117638169?spm=1001.2014.3001.5501

这篇关于[Java大厂必备面试题] 点滴促就辉煌, 每日三题【Day5】:基础篇2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/651914

相关文章

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

java8的新特性之一(Java Lambda表达式)

1:Java8的新特性 Lambda 表达式: 允许以更简洁的方式表示匿名函数(或称为闭包)。可以将Lambda表达式作为参数传递给方法或赋值给函数式接口类型的变量。 Stream API: 提供了一种处理集合数据的流式处理方式,支持函数式编程风格。 允许以声明性方式处理数据集合(如List、Set等)。提供了一系列操作,如map、filter、reduce等,以支持复杂的查询和转

UE3脚本UnrealScript UC语法点滴

持续更新 目录 类定义修饰符  1.dependson(CLASSNAME) 2.config(ININAME) 3.native 4.notplaceable 5.inherits(CLASSNAME1[,CLASSNAME2,...]) 类对象实例创建 类默认属性设置 变量 1.声明 var local 2.修饰符 config  3.array 类型变量 以及

Vim使用基础篇

本文内容大部分来自 vimtutor,自带的教程的总结。在终端输入vimtutor 即可进入教程。 先总结一下,然后再分别介绍正常模式,插入模式,和可视模式三种模式下的命令。 目录 看完以后的汇总 1.正常模式(Normal模式) 1.移动光标 2.删除 3.【:】输入符 4.撤销 5.替换 6.重复命令【. ; ,】 7.复制粘贴 8.缩进 2.插入模式 INSERT

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

电脑不小心删除的文件怎么恢复?4个必备恢复方法!

“刚刚在对电脑里的某些垃圾文件进行清理时,我一不小心误删了比较重要的数据。这些误删的数据还有机会恢复吗?希望大家帮帮我,非常感谢!” 在这个数字化飞速发展的时代,电脑早已成为我们日常生活和工作中不可或缺的一部分。然而,就像生活中的小插曲一样,有时我们可能会在不经意间犯下一些小错误,比如不小心删除了重要的文件。 当那份文件消失在眼前,仿佛被时间吞噬,我们不禁会心生焦虑。但别担心,就像每个问题

详细分析Springmvc中的@ModelAttribute基本知识(附Demo)

目录 前言1. 注解用法1.1 方法参数1.2 方法1.3 类 2. 注解场景2.1 表单参数2.2 AJAX请求2.3 文件上传 3. 实战4. 总结 前言 将请求参数绑定到模型对象上,或者在请求处理之前添加模型属性 可以在方法参数、方法或者类上使用 一般适用这几种场景: 表单处理:通过 @ModelAttribute 将表单数据绑定到模型对象上预处理逻辑:在请求处理之前