【金融行业】众安保险 java后端校招 最新面试题

目录

String、StringBuilder、StringBuffer的区别?

抽象类和接口的区别是什么?

接口的成员变量和方法的访问权限是怎样的?

内部类能否访问外部类的私有变量?

深拷贝和浅拷贝的区别是什么?

HashMap如何处理哈希冲突?

常见哈希冲突有哪些解决方法?

常见线程安全的集合你知道哪些?

JVM

JVM 内存结构说一下

堆和栈的区别是什么?

方法区的作用是什么?

双亲委派机制介绍一下

常见回收算法你知道哪些?

垃圾回收器有哪些?

MySQL

事务 ACID特性是什么?

数据库三大范式清楚吗?

mysql 的隔离级别有哪些?

常见的索引有哪些?

唯一索引如何实现不可重复的?

索引的数据结构有哪些?

mysql 锁的分类有哪些?

update加锁后是否可以读?

操作系统

进程通信的方式?

场景题

如何设计一个秒杀场景?

算法

判断链表是否存在环


String、StringBuilder、StringBuffer的区别?

1、可变性 :String 是不可变的(Immutable),一旦创建,内容无法修改,每次修改都会生成一个新的对象。StringBuilder 和 StringBuffer 是可变的(Mutable),可以直接对字符串内容进行修改而不会创建新对象。

2、线程安全性 :String 因为不可变,天然线程安全。StringBuilder 不是线程安全的,适用于单线程环境。StringBuffer 是线程安全的,其方法通过 synchronized 关键字实现同步,适用于多线程环境。

3、性能 :String 性能最低,尤其是在频繁修改字符串时会生成大量临时对象,增加内存开销和垃圾回收压力。StringBuilder 性能最高,因为它没有线程安全的开销,适合单线程下的字符串操作。StringBuffer 性能略低于 StringBuilder,因为它的线程安全机制引入了同步开销。

4、使用场景 :如果字符串内容固定或不常变化,优先使用 String。如果需要频繁修改字符串且在单线程环境下,使用 StringBuilder。如果需要频繁修改字符串且在多线程环境下,使用 StringBuffer

对比总结如下:

特性 String StringBuilder StringBuffer
不可变性 不可变 可变 可变
线程安全 是(因不可变) 是(同步方法)
性能 低(频繁修改时) 高(单线程) 中(多线程安全)
适用场景 静态字符串 单线程动态字符串 多线程动态字符串

例子代码如下:

// String的不可变性
String str = "abc";
str = str + "def"; // 新建对象,str指向新对象

// StringBuilder(单线程高效)
StringBuilder sb = new StringBuilder();
sb.append("abc").append("def"); // 直接修改内部数组

// StringBuffer(多线程安全)
StringBuffer sbf = new StringBuffer();
sbf.append("abc").append("def"); // 同步方法保证线程安全

抽象类和接口的区别是什么?

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

  • 定义 :抽象类是一个不能实例化的类,可以包含具体方法和抽象方法;接口是一个完全抽象的结构,主要用于定义行为规范。

  • 继承与实现 :抽象类通过 extends 继承,只能单继承;接口通过 implements 实现,可以多实现。

  • 成员变量 :抽象类可以有普通变量和常量;接口只能有常量(public static final)。

  • 方法 :抽象类可以有抽象方法和具体方法;接口从 JDK 8 开始支持默认方法和静态方法。

  • 构造器 :抽象类可以有构造器,接口不能有构造器。

  • 设计目的 :抽象类用于描述“是什么”,强调类的继承关系;接口用于描述“能做什么”,强调行为的规范。

接口的成员变量和方法的访问权限是怎样的?

成员类型 默认修饰符 访问权限说明 其他特性说明
成员变量 public static final 可以被任何类访问,因为是 public;通过接口名直接访问,因为是 static 必须在定义时初始化,且初始化后值不能被修改,是常量
抽象方法(Java 8 之前接口中的普通方法) public abstract 任何实现该接口的类都要实现这些方法,可被外部类访问 只有方法声明,没有方法体,由实现类提供具体实现
default 方法(Java 8 及以后) public 实现类可直接使用,也可重写,外部类通过实现类对象调用 有方法体,为实现类提供默认行为
static 方法(Java 8 及以后) public 通过接口名直接调用 有方法体,属于接口本身,与接口的实例无关
private 方法(Java 9 及以后) private 只能在接口内部被其他 default 方法或 private static 方法调用 用于抽取接口中 default 方法或 static 方法的重复代码
private static 方法(Java 9 及以后) private static 只能在接口内部被其他 static 方法或 default 方法调用

接口中的成员变量默认是publicstaticfinal的。这意味着:

  • public:可以被任何类访问。

  • static:它属于接口本身,而不是接口的实例。

  • final:变量的值在初始化后不能被修改,即它是一个常量。所以在接口中定义成员变量时,通常会同时进行赋值,例如public static final int MAX_COUNT = 100; ,并且实际编码中public static final这些修饰符常常省略。

接口中的方法默认是publicabstract的。这表示:

  • public:任何实现该接口的类都必须实现这些方法,并且可以被外部类访问。

  • abstract:这些方法只有声明,没有方法体,需要由实现接口的类来提供具体的实现逻辑。在 Java 8 及以后版本,接口中还可以有default方法和static方法,default方法有方法体,为接口的实现类提供了一种默认的行为实现;static方法属于接口自身,可通过接口名直接调用,它们的访问权限同样是public 。

内部类能否访问外部类的私有变量?

部类可以访问外部类的私有变量,这是因为:

  1. 内部类是外部类的一部分,可以直接访问外部类的所有成员,包括私有成员。

  2. 对于非静态内部类,它持有对外部类实例的隐式引用(OuterClass.this),因此可以访问外部类的非静态私有变量,比如下面的例子,展示内部类如何访问外部类的私有变量:

public class OuterClass {
    private String outerField = "I am a private field of OuterClass";

    // 非静态内部类
    class InnerClass {
        public void accessOuterField() {
            // 内部类可以直接访问外部类的私有变量
            System.out.println("Accessing outerField: " + outerField);
        }
    }

    public static void main(String[] args) {
        // 创建外部类实例
        OuterClass outer = new OuterClass();
        // 创建内部类实例
        OuterClass.InnerClass inner = outer.new InnerClass();
        // 调用内部类方法,访问外部类的私有变量
        inner.accessOuterField();
    }
}

//输出结果
Accessing outerField: I am a private field of OuterClass
  1. 对于静态内部类,它只能访问外部类的静态私有变量,因为它不依赖于外部类的实例。例子如下代码:

public class OuterClass {
    private String outerField = "I am a private field of OuterClass";
    private static String staticField = "I am a static private field";

    // 静态内部类
    static class StaticInnerClass {
        public void accessStaticField() {
            // 可以访问外部类的静态私有变量
            System.out.println("Accessing staticField: " + staticField);

            // 无法直接访问非静态私有变量
            // System.out.println(outerField); // 编译错误
        }
    }

    public static void main(String[] args) {
        // 创建静态内部类实例
        OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
        staticInner.accessStaticField();
    }
}

//输出结果
Accessing staticField: I am a static private field

深拷贝和浅拷贝的区别是什么?

null

null

  • 浅拷贝是指只复制对象本身和其内部的值类型字段,但不会复制对象内部的引用类型字段。换句话说,浅拷贝只是创建一个新的对象,然后将原对象的字段值复制到新对象中,但如果原对象内部有引用类型的字段,只是将引用复制到新对象中,两个对象指向的是同一个引用对象。

  • 深拷贝是指在复制对象的同时,将对象内部的所有引用类型字段的内容也复制一份,而不是共享引用。换句话说,深拷贝会递归复制对象内部所有引用类型的字段,生成一个全新的对象以及其内部的所有对象。

HashMap如何处理哈希冲突?

在 JDK 1.7 版本之前, HashMap 数据结构是数组和链表,HashMap通过哈希算法将元素的键(Key)映射到数组中的槽位(Bucket)。如果多个键映射到同一个槽位,它们会以链表的形式存储在同一个槽位上,因为链表的查询时间是O(n),所以冲突很严重,一个索引上的链表非常长,效率就很低了。

图片

所以在 JDK 1.8 版本的时候做了优化,当一个链表的长度超过8的时候就转换数据结构,不再使用链表存储,而是使用红黑树,查找时使用红黑树,时间复杂度O(log n),可以提高查询性能,但是在数量较少时,即数量小于6时,会将红黑树转换回链表。

图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扫地僧009

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值