一读小说 » 都市言情 » 蓝星文娱:从微末崛起的娱乐大亨 » 第八章(核心基础篇-2)2024年Java求职面试与工作编程要点实录

第八章(核心基础篇-2)2024年Java求职面试与工作编程要点实录

    【Java基础篇-2之4个基础小题】

    那么,我们继续,开启IT大厂面试题进阶之路。

    Java核心大厂公司的面试题,通常涵盖了广泛的Java知识领域。

    包括Java基础、JVM、多线程、集合框架、并发编程、设计模式、数据库、网络编程、分布式系统、大数据处理等诸多方面。

    以下列举一些典型代表,供你参考学习。

    一、Java基础(4个)

    1、解释下Java中的值传递和引用传递?

    在Java中,参数传递只有值传递,没有引用传递。

    但这里可能会有些混淆,因为当我们谈论Java的对象时,我们实际上是在传递对象的引用,而不是对象本身。

    但即使如此,这仍然是值传递的一种形式。下面我会详细解释这个概念。

    一、值传递

    在Java中,当我们传递一个基本数据类型(如int、double、char等)的参数时,我们实际上是传递了该参数值的一个副本。

    这意味着在方法内部,对参数值的任何修改都不会影响到原始变量。

    这是因为,方法操作的是参数值的一个副本,而不是原始变量本身。

    例如:

    publicclassMain{

    publicstaticvoidmain(String[]args){

    intx=10;

    changeValue(x);

    System.out.println(x);//输出:10

    }

    publicstaticvoidchangeValue(intnum){

    num=20;

    }

    }

    在上面的例子中,尽管我们在changeValue方法中将num的值更改为20。

    但main方法中的x的值,仍然是10。

    这是因为我们传递的是x值的一个副本,而不是x本身。

    二、对象传递(看似引用传递,实际上是值传递):

    当我们传递一个对象作为参数时,我们传递的是对象引用的一个副本,而不是对象本身。

    这意味着,我们可以在方法内部,通过引用修改对象的状态(即对象的字段)。

    但我们不能,使引用指向一个新的对象。

    例如:

    publicclassMain{

    publicstaticvoidmain(String[]args){

    MyObjectobj=newMyObject(10);

    changeObject(obj);

    System.out.println(obj.getValue);//输出:20

    }

    publicstaticvoidchangeObject(MyObjectobj){

    obj.setValue(20);

    }

    }

    classMyObject{

    privateintvalue;

    publicMyObject(intvalue){

    this.value=value;

    }

    publicintgetValue{

    returnvalue;

    }

    publicvoidsetValue(intvalue){

    this.value=value;

    }

    }

    在上面的例子中,尽管我们在changeObject方法中没有直接修改main方法中的obj引用。

    但我们通过obj引用,修改了MyObject的状态(即value字段的值)。

    因此,当我们在main方法中打印obj.getValue时,得到的是20,而不是原始的10。

    然而,如果我们试图在changeObject方法中,让obj引用指向一个新的MyObject实例。

    那么main方法中的obj引用,将不会受到影响,因为它仍然指向原始的MyObject实例。

    总结:

    Java只有值传递,没有引用传递。

    当我们传递对象时,我们传递的是对象引用的一个副本,而不是对象本身。

    这允许我们在方法内部,通过引用修改对象的状态,但不允许我们使引用指向新的对象。

    …

    2、描述下Java中的垃圾回收机制?

    Java中的垃圾回收机制(GarbageCollection,GC)是Java内存管理的核心部分。

    旨在自动回收不再被程序使用的内存空间,以防止内存泄漏和崩溃等问题。

    这是Java语言的一个重要特性,大大减轻了开发人员对内存管理的负担。

    Java程序的内存空间,主要被划分为四个区域:堆区、栈区、代码区和静态区。

    其中,堆区是对象实例的分配区域。

    当我们在代码中声明一个对象时,实际上是在栈中创建了一个对象的引用,而对象的实际内存分配则在堆中完成。

    垃圾回收机制,通过一个被称为垃圾收集器(GarbageCollector)的程序来实现。

    垃圾收集器,定期自动扫描内存中的对象。

    使用MarkandSweep算法等策略,来识别哪些对象是不再被使用的,并将它们标记为垃圾。

    然后,垃圾收集器,会释放这些垃圾对象所占用的内存空间,以便其他对象可以使用。

    垃圾回收机制,主要分为标记阶段和清除阶段。

    在标记阶段,垃圾收集器遍历内存中的所有对象,并识别出哪些是被引用的对象,哪些是未被引用的对象。

    未被引用的对象会被标记为“可回收对象”。

    在清除阶段,垃圾收集器会释放这些可回收对象所占用的内存空间。

    Java的垃圾回收机制具有三个优点:

    1)它实现了自动内存管理,减轻了开发人员对内存管理的负担。

    程序员无需手动跟踪对象的生命周期和手动释放内存,这大大降低了内存泄漏和野指针等内存错误的风险。

    2)垃圾回收机制有助于避免内存泄漏问题。

    即使开发人员忘记释放对象的引用,垃圾回收器也能检测到并回收这些对象。

    3)垃圾回收机制提高了开发效率。

    使开发人员能够更专注于业务逻辑和功能实现,而无需过多关注内存管理。

    然而,Java的垃圾回收机制,也存在一些缺点。

    由于垃圾回收,是由垃圾收集器自动触发的,程序员无法精确控制回收的时间和频率。

    这可能导致,在某些情况下出现短暂的暂停,即所谓的“停顿时间”。

    这可能会,影响某些对实时性要求较高的应用程序。

    总之,Java的垃圾回收机制,是一种高效的内存管理机制。

    它通过自动回收不再使用的内存空间,来优化程序性能,并减少内存泄漏的风险。

    虽然存在一些缺点,但其优点使得它在Java编程中,发挥着至关重要的作用。

    …

    3、谈谈Java中的异常处理机制?

    在Java中,异常处理机制,是确保程序稳健运行的关键。

    当程序遇到某种意外情况,比如试图访问一个不存在的文件,或者执行了非法的操作,Java就会抛出异常。

    异常处理机制的核心是try-catch语句。

    在try块中,我们放置可能会抛出异常的代码。

    如果,在执行这些代码时发生异常,那么控制流就会立即跳出try块,进入相应的catch块。

    在catch块中,我们可以编写处理异常的代码,比如记录错误信息、尝试恢复程序的正常状态,或者进行清理操作。

    此外,Java还提供了throw语句,允许我们显式地抛出异常。

    这通常用于,在检测到某些特定条件不满足时,主动抛出异常,以通知调用者。

    Java的异常类主要分为两大类:

    1)受检异常(CheckedException);

    2)非受检异常(UncheckedException,也就是运行时异常RuntimeException及其子类)。

    受检异常在编译时就必须被处理,要么用try-catch捕获,要么在方法签名中,用throws声明可能会抛出。

    而非受检异常,则不需要在编译时处理,通常是由于程序逻辑错误导致的,比如空指针异常。

    最后,Java的异常处理机制还支持异常链,即一个异常可以由另一个异常引发。

    这在处理复杂的异常情况时非常有用,可以帮助我们更好地理解异常的来源和原因。

    总的来说,Java的异常处理机制,提供了一种结构化和系统化的方式,来处理程序中的错误情况,使得程序能够更稳健地运行。

    …

    4、如何实现Java中的单例模式?

    在Java中,要实现单例模式有多种方式,每种方式都有其特点和适用场景。

    下面我会介绍六种常见的实现方法:

    1)饿汉式(静态常量)

    这是最简单,且线程安全的实现方式。

    在类加载时,就完成了初始化,所以类加载较慢,但获取对象的速度快。

    publicclassSingleton{

    //类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快

    privatestaticfinalSingletonINSTANCE=newSingleton;

    privateSingleton{}

    publicstaticSingletongetInstance{

    returnINSTANCE;

    }

    }

    2)懒汉式(线程不安全)

    这种实现,在第一次调用getInstance方法时,初始化实例,实现了延迟加载。

    但是,在多线程的环境下,这是不安全的。

    publicclassSingleton{

    privatestaticSingletoninstance;

    privateSingleton{}

    publicstaticSingletongetInstance{

    if(instance==null){

    instance=newSingleton;

    }

    returninstance;

    }

    }

    3)懒汉式(线程安全,同步方法)

    通过synchronized关键字,对getInstance方法进行同步,保证线程安全。

    但是,效率较低,每次获取实例都需要进行同步。

    publicclassSingleton{

    privatestaticSingletoninstance;

    privateSingleton{}

    publicstaticsynchronizedSingletongetInstance{

    if(instance==null){

    instance=newSingleton;

    }

    returninstance;

    }

    }

    4)懒汉式(线程安全,双重检查锁定)

    这种方式,既实现了延迟加载,又保证了多线程环境下的线程安全。

    同时,由于使用了双重检查锁定,减少了不必要的同步开销,因此效率较高。

    publicclassSingleton{

    privatevolatilestaticSingletoninstance;

    privateSingleton{}

    publicstaticSingletongetInstance{

    if(instance==null){

    synchronized(Singleton.class){

    if(instance==null){

    instance=newSingleton;

    }

    }

    }

    returninstance;

    }

    }

    5)静态内部类

    这种方式,同样实现了延迟加载和线程安全,而且只需要编写很少的代码。

    它是单例模式中的最佳实现方式之一。

    publicclassSingleton{

    privatestaticclassSingletonHolder{

    privatestaticfinalSingletonINSTANCE=newSingleton;

    }

    privateSingleton{}

    publicstaticfinalSingletongetInstance{

    returnSingletonHolder.INSTANCE;

    }

    }

    6)枚举

    这种实现方式,不仅能避免多线程同步问题。

    而且在Java中,枚举类型是一种特殊的类,它包含了一组固定的常量。

    由于Java枚举类型的特性,它可以自然地实现单例模式。

    枚举类型的每个实例,在JVM中都是唯一的。

    因此,利用枚举类型来实现单例模式,是非常简单且线程安全的。

    下面是一个使用枚举,实现单例模式的示例代码:

    publicenumSingleton{

    INSTANCE;

    //这里可以添加其他方法或者字段

    publicvoidsomeMethod{

    //实现单例对象需要的功能

    }

    //获取单例对象的方法

    publicstaticSingletongetInstance{

    returnINSTANCE;

    }

    }

    在这个示例中,我们定义了一个名为Singleton的枚举类型,它有一个枚举常量INSTANCE。

    由于枚举常量在JVM中是唯一的,因此INSTANCE就是我们的单例对象。

    我们还提供了一个静态方法getInstance来获取单例对象。

    这个方法直接返回枚举常量INSTANCE,非常简单。

    你可以像下面这样,使用这个单例对象:

    publicclassMain{

    publicstaticvoidmain(String[]args){

    Singletonsingleton=Singleton.getInstance;

    singleton.someMethod;

    }

    }

    使用枚举实现单例模式的好处是:

    (1)线程安全

    由于JVM保证枚举类型的实例,在内存中唯一,因此无需额外的同步措施。

    (2)防止反序列化重新创建对象

    由于枚举类型,默认实现了serializable接口。

    并且每个枚举常量,在反序列化时,都会映射到对应的枚举类型。

    因此,不会重新创建新的对象。

    (3)防止通过反射攻击

    Java的枚举类型,在反射机制下,也是安全的。

    使得无法通过反射,来创建新的枚举实例。

    因此,使用枚举实现单例模式,是一种既简洁又安全的方式。

    总结:

    以上六种实现的单例模式的方法,你可以根据自己的需求和使用场景,选择你认为最合适的单例模式实现方式。

    ……

    以上,就是今天的分享啦!

    希望,对你有那么一点点、一丢丢、一戳戳地帮助哈~

    所以哩…

    评论、收藏、关注一键三连可好?

    推荐票、月票、打赏,好伐?!

    嘻嘻…