1. 引言

Java类型系统是技术面试中的高频考点。本文整理了几个经典且容易踩坑的面试题,帮你快速梳理核心知识点。

2. 核心问题

2.1 问题1:Object类在类型体系中的地位?哪些类型继承自Object?数组呢?Lambda表达式能赋值给Object变量吗?

java.lang.Object位于Java类继承体系的顶端。所有类都直接或间接继承自它:

  • 显式继承:使用extends关键字
  • 隐式继承:省略extends时默认继承
  • 传递继承:通过继承链间接继承

但有8个基本类型不继承自Object:

  • booleanbyteshortcharintfloatlongdouble

根据JVM规范,数组也是对象:

int[] arr = new int[5];
Object obj = arr; // 合法
arr.hashCode();   // 可调用Object方法

Lambda表达式不能直接赋值给Object变量:

Object obj = () -> {}; // 编译错误!Object不是函数式接口

但可以通过强制转换实现:

Object obj = (Runnable) () -> {}; // 合法

2.2 问题2:基本类型和引用类型的区别?

核心差异对比表

特性 引用类型 基本类型
继承关系 继承自Object 不继承任何类
可继承性 可被子类继承(final类除外) 不可继承
参数传递 传递引用值 传递值本身
内存存储 对象头+实例数据 直接存储硬件值
空间开销 较大(对象头通常12-16字节) 极小(如int仅4字节)

⚠️ 关键区别:修改方法内基本类型参数不会影响外部值:

void modify(int x) {
    x = 10; // 不影响调用者
}

int num = 5;
modify(num);
// num仍为5

2.3 问题3:Java的8种基本类型及内存占用?

类型 大小 取值范围
boolean 未定义 true/false
byte 8位 -128 ~ 127
short 16位 -32,768 ~ 32,767
char 16位 0 ~ 65,535 (Unicode)
int 32位 -2³¹ ~ 2³¹-1
long 64位 -2⁶³ ~ 2⁶³-1
float 32位 IEEE 754单精度
double 64位 IEEE 754双精度

💡 boolean大小由JVM实现决定,通常用1字节存储

2.4 问题4:抽象类和接口的区别?使用场景?

核心区别

  • 继承数量:类可实现多个接口,但只能继承一个抽象类
  • 设计目的
    • 抽象类:表示"是什么"(is-a关系),如AbstractMap
    • 接口:表示"能做什么"(has-a能力),如Comparable

使用场景

// 抽象类:提供基础实现
public abstract class AbstractMap {
    public boolean equals(Object o) {
        // 通用实现...
    }
}

// 接口:定义能力契约
public interface Comparable {
    int compareTo(Object o);
}

2.5 问题5:接口成员的限制?

接口成员有严格限制:

  • 字段:隐式public static final,必须是常量
  • 方法
    • 隐式public
    • 要么隐式abstract
    • 要么显式default

禁止操作

interface BadExample {
    private int x = 1; // 编译错误!字段不能是private
    void method() {}    // 编译错误!方法体需加default
}

2.6 问题6:内部类和静态嵌套类的区别?

非静态内部类

  • 隐式持有外部类引用
  • 需通过外部类实例创建 ```java public class Outer { public class Inner {
      public Outer getOuter() {
          return Outer.this; // 访问外部类实例
      }
    
    } }

// 创建方式 Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();


**静态嵌套类**:
- 不持有外部类引用
- 可独立创建
```java
public class Outer {
    public static class Nested {
    }
}

// 创建方式
Outer.Nested nested = new Outer.Nested();

2.7 问题7:Java支持多重继承吗?

类不支持多重继承

class A {}
class B {}
class C extends A, B {} // 编译错误!

接口可实现多重继承

interface Flyable { void fly(); }
interface Swimmable { void swim(); }

class Duck implements Flyable, Swimmable {
    // 实现多个接口
}

💡 Java 8的default方法让接口更接近多重继承,但避免了菱形问题

2.8 问题8:包装类和自动装箱是什么?

包装类:为8种基本类型提供对象形式

  • BooleanByteShortCharacter
  • IntegerFloatLongDouble

自动装箱/拆箱:编译器自动转换

// 装箱:int -> Integer
List<Integer> list = new ArrayList<>();
list.add(5); // 等价于 list.add(Integer.valueOf(5))

// 拆箱:Integer -> int
int value = list.get(0); // 等价于 list.get(0).intValue()

2.9 问题9:equals()和==的区别?

==操作符

  • 比较基本类型:值是否相等
  • 比较引用类型:是否指向同一对象
    String a = new String("Hi");
    String b = new String("Hi");
    System.out.println(a == b); // false(不同对象)
    

equals()方法

  • 默认行为同==
  • 通常被重写实现值比较
    String a = new String("Hi");
    String b = new String("Hi");
    System.out.println(a.equals(b)); // true(值相同)
    

2.10 问题10:如何检查对象是否是某个类的实例?

不能用instanceof(需要字面量类名),改用Class.isInstance()

Class<?> integerClass = Integer.class;
assertTrue(integerClass.isInstance(new Integer(42)));
assertTrue(integerClass.isInstance(42)); // 自动装箱

2.11 问题11:匿名类是什么?使用场景?

匿名类:一次性使用的无名类,定义和实例化同时完成

典型场景

  1. Java 8之前:实现单方法接口

    Thread t = new Thread(new Runnable() {
     @Override
     public void run() {
         System.out.println("匿名线程");
     }
    });
    
  2. 快速初始化集合

    Map<String, Integer> map = new HashMap<String, Integer>(){{
     put("张三", 30);
     put("李四", 25);
     put("王五", 29);
    }};
    

💡 Java 8后优先用Lambda替代单方法接口的匿名类


原始标题:Java Type System Interview Questions