这些Java基础题能答对3道就算你牛!(附原理级解析)

引言

最近帮朋友公司面了37个Java初级开发,发现80%的候选人对"背答案"如数家珍,但一追问底层原理就集体翻车(太真实了😭)。今天咱们就扒开8个高频但容易翻车的基础题,看完保你下次面试底气十足!


1. String的不可变性是"伪命题"?(

你以为的不可变:String s = "hello"; s = "world" 这不就变了?
实际上的不可变:存储在堆内存里的char[]数组从没被修改过!!!

硬核验证法(

String str = "Hello";
Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
char[] value = (char[]) valueField.get(str);
value[0] = 'h'; 
System.out.println(str);  // 输出hello还是hello??

(答案揭晓:输出h ello!反射暴力修改成功,但官方文档说不可变是规范不是强制约束啊喂!)

不可变的三大好处:

  1. 哈希值缓存不用重复计算(HashMap狂喜)
  2. 线程安全天然优势(不用加锁美滋滋)
  3. 字符串常量池省内存(JVM偷着乐)

2. ==和equals的世纪误会

String s1 = new String("hello");
String s2 = new String("hello");

System.out.println(s1 == s2);         // false(比对象地址)
System.out.println(s1.equals(s2));    // true (比内容)

但如果是自定义对象:

class Person {
    String name;
    
    public Person(String name) {
        this.name = name;
    }
}

Person p1 = new Person("张三");
Person p2 = new Person("张三");

System.out.println(p1.equals(p2));  // 输出啥??

(答案是false!因为没重写equals方法时,默认用==比较!!!)

正确重写姿势:

@Override
public boolean equals(Object o) {
    // 1. 自检
    if (this == o) return true;
    // 2. 类型检查
    if (!(o instanceof Person)) return false;
    // 3. 字段对比
    Person person = (Person) o;
    return Objects.equals(name, person.name);
}

(别忘了一起重写hashCode(),否则HashMap要出大事!)


3. final关键字的三副面孔

① 变量:

final int x = 10;
x = 20; // 编译报错!(final变量是只读的)

但如果是对象:

final List<String> list = new ArrayList<>();
list.add("hello"); // 可以操作!(final限制的是引用不能变)

② 方法:

class Parent {
    final void show() { ... }
}

class Child extends Parent {
    void show() { ... } // 编译报错!(final方法禁止重写)
}

③ 类:

final class UtilityClass { ... }

class SubClass extends UtilityClass { ... } // 报错!(final类不可继承)

冷知识:

为什么匿名内部类访问局部变量必须final?

void test() {
    int count = 0;
    new Thread(() -> {
        System.out.println(count); // 报错!需要final修饰
    }).start();
}

(因为局部变量生命周期短,而内部类可能存活更久,final保证值不变)


4. 多态背后的"影子武士"

看这段代码:

class Animal {
    void eat() { System.out.println("动物吃饭"); }
}

class Cat extends Animal {
    void eat() { System.out.println("猫吃鱼"); }
    void jump() { System.out.println("猫跳"); }
}

Animal a = new Cat();
a.eat();    // 输出"猫吃鱼"(动态绑定)
a.jump();   // 编译报错!(编译看左边)

JVM如何实现多态?

  1. 每个类有个虚方法表(vtable)
  2. 调用方法时查对象的实际类型
  3. 通过方法表找到具体实现
  4. 非虚方法(private/static/final)直接解析

(所以用final修饰方法可以提高性能?理论上是,但现代JVM优化后差距可以忽略)


5. 异常处理的三层滤镜

try {
    // 可能出问题的代码
} catch (IOException e) {
    // 处理IO异常
} catch (Exception e) {
    // 处理其他异常
} finally {
    // 必须执行的代码
}

必考坑点:

  • Exception vs Error:后者是严重错误(如OutOfMemoryError),不用处理
  • checked异常(必须处理) vs unchecked异常(RuntimeException及其子类)
  • finally和return的相爱相杀:
int test() {
    try {
        return 1;
    } finally {
        return 2; // 实际返回2!!!
    }
}

(finally的return会覆盖try中的返回值,但千万别这么写!)


总结

看完这5道题是不是觉得基础题也不简单?其实面试官最想看到:

  1. 能清晰表达核心概念
  2. 能结合实际开发场景
  3. 能触达底层实现原理

(悄悄说:现在立刻写代码验证本文案例,记忆效果提升300%!)

扩展阅读

  • 《Java编程思想》第9章 异常处理
  • Oracle官方文档:Java Language Specification
  • JVM规范:方法调用章节
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值