# Java 基础

# object中定义了哪些方法?

clone()
equals()
hashCode()
toString()
notify()
notifyAll()
wait()
finalize()
getClass()

# 为什么等待和通知是在 Object 类而不是 Thread 中声明的?

  1. 同步是提供互斥并确保 Java 类的线程安全,而 wait 和 notify 是两个线程之间的通信机制。
    记住同步和等待通知是两个不同的领域,不要把它们看成是相同的或相关的。
    要确保这个机制对每个对象可用, 那么 Object 类则是的正确声明位置。
  2. 每个对象都可上锁,这是在 Object 类而不是 Thread 类中声明 wait 和 notify 的另一个原因。
  3. 在 Java 中为了进入代码的临界区,线程需要锁定并等待锁定,
    他们不知道哪些线程持有锁,而只是知道锁被某个线程持有,
    并且他们应该等待取得锁, 而不是去了解哪个线程在同步块内,并请求它们释放锁定。
  4. Java 是基于 Hoare 的监视器的思想。在Java中,所有对象都有一个监视器。
    线程在监视器上等待,为执行等待,我们需要2个参数: 一个线程 一个监视器(任何对象) 在 Java 设计中,线程不能被指定,它总是运行当前代码的线程。但是,我们可以指定监视器(这是我们称之为等待的对象)。

# for-each 与 常规for循环的 效率对比

for-each能够让代码更加清晰,并且减少了出错的机会。
使用for-each循环与常规的for循环相比,并不存在性能损失,即使对数组进行迭代也是如此。
实际上,在有些场合下它还能带来微小的性能提升,因为它只计算一次数组索引的上限。

# hashCode的作用是什么?

# ”==“与”equals()"的区别

“关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系”

== 就是用来比较值是否相等 equals是Object类的方法,Object对它的实现是比较内存地址 可以重写这个方法来自定义“相等”这个概念

# String, StringBuilder, StringBuffer的区别是什么?

String: 不可变的字符序列,若要向其中添加新字符需要创建一个新的String对象 StringBuilder: 可变字符序列,支持向其中添加新字符(无需创建新对象) StringBuffer: 可以看作线程安全版的StringBuilder

# 为什么 String 在 Java 中是不可变的?

  1. 由于 String 是不可变的,它可以安全地共享许多线程,这对于多线程编程非常重要
  2. 字符串已被广泛用作许多 Java 类的参数
  3. Java 中的不可变 String 缓存其哈希码
    使得它在 Java 中的 HashMap 中使用的 HashMap 键非常快。
    因为 String 是不可变的,所以没有人可以在创建后更改其内容,这保证了 String 的 hashCode 在多次调用时是相同的。
  4. String 不可变的绝对最重要的原因是它被类加载机制使用,因此具有深刻和基本的安全考虑。
    如果 String 是可变的,加载“java.io.Writer” 的请求可能已被更改为加载 “mil.vogoon.DiskErasingWriter”。
  5. 字符串池的使用。
    使得String是多引用的。

安全性和字符串池是使字符串不可变的主要原因。

# 为什么 char 数组比 Java 中的 String 更适合存储密码?

在字符数组中存储密码可以明显降低窃取密码的安全风险。
String 在字符串池中, 它很可能会保留在内存中持续很长时间,从而构成安全威胁。

# IO与NIO的区别?

IO 是面向流的,这意味着我们需要每次从流中读取一个或多个字节,直到读取完所有字节。 NIO是面向缓冲的,也就是说会把数据读取到一个缓冲区中,然后对缓冲区中的数据进行相应处理。

IO 是阻塞 IO,而 NIO 是非阻塞 IO

NIO中存在一个称为选择器(selector)的东西,它允许你把多个通道(channel)注册到一个选择器上, 然后使用一个线程来监视这些通道,若这些通道里有某个准备好可以开始进行读或写操作了,则开始对相应的通道进行读写。 而在等待某通道变为可读/写期间,请求对通道进行读写操作的线程可以去干别的事情。