### 2022年程序员面试之九阴真经资料
#### final, finally, finalize的区别
1. **final**:这是一个关键字,在Java中用于限制类、变量或方法的行为。如果一个类被声明为`final`,那么这个类就不能被继承,也就是说不能创建新的子类。同时,一个类不能同时被声明为`abstract`和`final`,因为`abstract`意味着这个类是用来被继承的,而`final`则不允许继承。当我们将变量或方法声明为`final`时,这些变量或方法就不能被改变或重写。对于`final`变量来说,它必须在声明时被初始化,并且之后只能读取不能修改;对于`final`方法,则不能在子类中被重写。
2. **finally**:在异常处理中,`finally`块用于确保无论是否发生异常,其中的代码都会被执行。这通常用于释放资源,比如关闭文件流或数据库连接等。当程序抛出异常并且被匹配的`catch`子句捕获后,控制权会进入`finally`块(如果存在的话)。即使异常未被捕获,或者`return`语句被执行,`finally`块中的代码仍然会被执行。
3. **finalize**:这是`Object`类中的一个方法,允许在垃圾回收器删除对象之前执行必要的清理工作。通过覆盖`finalize()`方法,开发者可以在对象不再被引用时进行资源清理或其他必要的操作。然而,这种方法的使用并不推荐,因为它依赖于垃圾回收器的不确定行为,而且现代Java版本提供了更好的资源管理机制,如`try-with-resources`。
#### Anonymous Inner Class(匿名内部类)
- 匿名内部类是一种特殊的内部类,没有名称。它可以实现接口或继承类,但通常只用来实现接口。匿名内部类的主要优点是简化了代码编写,特别是在需要实现接口时,可以直接在定义时实现接口的所有方法,而不必为这个内部类起一个名称。
#### & 和 && 的区别
- `&` 是按位与运算符,当用于布尔表达式时,表示逻辑与运算,但不会进行短路计算,即无论第一个操作数的值如何,都会计算第二个操作数。
- `&&` 是逻辑与运算符,它支持短路计算。这意味着如果第一个操作数为`false`,则不会计算第二个操作数。
#### HashMap 和 Hashtable 的区别
- `HashMap` 和 `Hashtable` 都实现了 `Map` 接口,用于存储键值对数据。主要区别在于:
- `HashMap` 允许使用 `null` 键和 `null` 值,而 `Hashtable` 不允许。
- `Hashtable` 是同步的,意味着它是线程安全的,而 `HashMap` 不是线程安全的。因此,在多线程环境中,如果不需要线程安全性,通常建议使用 `HashMap` 来提高性能。
- `Hashtable` 继承自 `Dictionary` 类,而 `HashMap` 是 Java 1.2 引入的新类。
- `HashMap` 移除了 `contains` 方法,并提供了 `containsKey` 和 `containsValue` 方法来代替。
#### Collection 和 Collections 的区别
- `Collection` 是一个接口,它是所有集合类型的父接口,定义了一系列集合操作的基本行为。
- `Collections` 是一个工具类,包含了许多静态方法,用于辅助集合的操作,如排序、查找等。
#### GC(Garbage Collection)
- **GC**(垃圾收集器)是 Java 自动内存管理的一部分,负责自动回收不再使用的对象所占用的内存空间。Java 开发者无需手动管理内存,这是因为 JVM(Java 虚拟机)内置了垃圾回收机制。可以通过调用 `System.gc()` 或 `Runtime.getRuntime().gc()` 来请求执行垃圾回收,但实际执行时机由 JVM 控制。
#### Strings 创建对象数量
- 当执行 `String s = new String("xyz");` 时,实际上创建了两个对象。一个是字符串常量 `"xyz"`,它位于字符串常量池中;另一个是通过 `new` 关键字创建的对象 `s`,它指向字符串 `"xyz"`。
#### Math.round 行为
- `Math.round(11.5)` 返回 `12`(类型为 `long`),`Math.round(-11.5)` 返回 `-11`(类型为 `long`)。这是因为 `Math.round` 方法对小数部分 `.5` 采用四舍五入的方式,向远离零的方向舍入。
#### short 类型赋值问题
- `short s1 = 1; s1 = s1 + 1;` 这行代码存在问题,因为 `s1 + 1` 的结果是 `int` 类型,需要显式地转换回 `short` 类型。正确的做法是 `s1 = (short) (s1 + 1);`。
- `short s1 = 1; s1 += 1;` 这种方式是正确的,因为 `+=` 运算符会自动处理类型转换的问题。
#### sleep() 和 wait() 的区别
- `sleep()` 方法用于让当前线程暂停指定的时间。这段时间结束后,线程可能不会立即恢复执行,因为线程调度是由操作系统控制的。
- `wait()` 方法用于等待其他线程唤醒当前线程,通常在同步上下文中使用,如对象锁上。线程调用 `wait()` 后,会释放对象锁并进入等待状态,直到被其他线程唤醒或等待时间结束。
#### 数组和 String 的 length 属性
- 数组没有 `length()` 方法,而是有一个 `length` 属性来获取数组的长度。
- `String` 类有 `length()` 方法,用于返回字符串中字符的数量。