java

java #

long/double 原子性? #

  • 没加 volatile 修饰符时,在 32bit 平台上,存取 long/double 变量不是原子操作(分成2步,每次操作32bit)。
  • 加了 volatile 修饰符之后,存取 long/double 变量是原子操作。

volatile 修饰符作用? #

  • 保证顺序(防止JVM或JTI对语句重排序)和可见性(happens-before,确保一个线程的修改对其他线程可见)。
  • 保证变量读写的原子性(针对64位数据类型,如 long 和 double)。

String 类有哪些常用方法? #

Get:

  • length(): int
  • isEmpty(): boolean
  • charAt(int index): char
  • getBytes(String charsetName): byte[]
  • getBytes(Charset charset): byte[]
  • getBytes(): byte[]
  • toCharArray(): char[]

Search:

  • contains(CharSequence str): boolean
  • indexOf(int ch): int
  • indexOf(String str): int
  • indexOf(int ch, int fromIndex): int
  • indexOf(String str, int fromIndex): int
  • lastIndexOf(int ch): int
  • lastIndexOf(String str): int
  • lastIndexOf(int ch, int fromIndex): int
  • lastIndexOf(String str, int fromIndex): int
  • startsWith(String prefix): boolean
  • endsWith(String suffix): boolean
  • matches(String regex): boolean
  • compareTo(String str): int
  • compareToIgnoreCase(String str): int
  • equals(Object str): boolean
  • equalsIgnoreCase(Object str): boolean

Transform:

  • toUpperCase(): String
  • toLowerCase(): String
  • trim(): String
  • substring(int beginIndex): String
  • substring(int beginIndex, endIndex): String
  • replace(CharSequence target, CharSequence replacement): String
  • replaceFirst(String regex, String replacement): String
  • replaceAll(String regex, String replacement): String
  • split(String regex): String[]
  • split(String regex, int limit): String[]
  • {static} join(CharSequence delimiter, CharSequence… elements): String
  • {static} format(String format, Object… args): String

java.io.File 类有哪些常用方法? #

  • getName(): String
  • getPath(): String
  • getAbsolutePath(): String
  • getParent(): String
  • getParentFile(): File
  • exists(): boolean
  • isDirectory(): boolean
  • isFile(): boolean
  • list(): String[]
  • listFiles(): File[]
  • length(): long
  • delete(): boolean
  • mkdir(): boolean
  • mkdirs(): boolean
  • renameTo(File): boolean
  • {static} createTempFile(String prefix, String suffix): File

FileDescriptor 中的 fd 和 handle 字段意义? #

  • FileInputStream/FileOutputStream/RarndomAccessFile 使用 handle 表示底层的文件句柄。
  • Socket/ServerSocket 使用 fd 表示底层的文件句柄。

BIO、NIO模型的区别? #

  • BIO代表模型有java.io包中的输入输出流;NIO代表模型有java.nio包中的通道、缓冲区、选择器。
  • BIO模型是同步阻塞的(在读写时线程阻塞);而NIO模型是同步非阻塞的(在等待就绪阶段是非阻塞的,在读写操作阶段是同步阻塞的)。

NIO模型的特性? #

  • 同步非阻塞
  • 多路复用

AIO模型的特性? #

  • 异步非阻塞
  • 事件通知机制

通道(Channel)与输入输出流(InputStream/OutputStream)的区别? #

  • 通道既可以读,也可以写,而流通常是单向的。
  • 通道可以异步读写,而流是同步阻塞的。
  • 通道中的数据总是先读或写到缓冲区(Buffer),而输入输出流则直接操作数据。

缓冲区(java.nio.Buffer)常用方法? #

Get:

  • capacity(): int
  • position(): int
  • limit(): int
  • remaining(): int

Judge:

  • hasRemaining(): boolean
  • isReadOnly(): boolean
  • isDirect(): boolean

Update:

  • position(int): Buffer
  • limit(int): Buffer
  • mark(): Buffer
  • reset(): Buffer
  • clear(): Buffer
  • flip(): Buffer
  • rewind(): Buffer

字节缓冲区(java.nio.ByteBuffer)常用方法? #

除了继承自 java.nio.Buffer 中的方法外,还包括:

Get:

  • get(): byte
  • get(int index): byte
  • get(byte[] dst, int offset, int length): ByteBuffer
  • get(byte[] dst): ByteBuffer
  • slice(): ByteBuffer
  • duplicate(): ByteBuffer
  • {static} allocateDirect(int capacity): ByteBuffer
  • {static} allocate(int capacity): ByteBuffer
  • {static} wrap(byte[] array, int offset, int length): ByteBuffer
  • {static} wrap(byte[] array): ByteBuffer

Update:

  • compact(): ByteBuffer
  • put(byte): ByteBuffer
  • put(int index, byte b): ByteBuffer
  • put(byte[] src, int offset, int length): ByteBuffer
  • put(byte[] src): ByteBuffer
  • put(ByteBuffer src): ByteBuffer

About backed array:

  • hasArray(): boolean
  • array(): byte[]
  • arrayOffset(): int

HashMap 实现原理? #

put 方法:

  • HashMap 内部维护一个数组,key 经过 hash 和取余操作之后得到下标位置,找到数组对应的节点。
  • 此节点是一个链表表头或树根或为空,链表或树中存放着所有哈希冲突的节点,找到 key 对应节点替换其中的数据,没有找到则插入新节点。
  • 当链表长度超过阈值(TREEIFY_THRESHOLD=8),则链表会转换为红黑树(since java 8),冲突数量少于6时又退化为链表。

为什么 HashMap 里的 table 数组长度是 2 的幂次? #

优化取模计算,提高存储下标位置计算效率。

为什么 HashMap 里的 table、entrySet 成员变量用 transient 修饰? #

  • transient 修饰的成员变量,在序列化时会被忽略。
  • 考虑到不同平台 hash 结果可能不一样,为了保证兼容性,添加 transient 修饰符,序列化时忽略 hash 数据。
  • HashMap 采用自定义方法进行序列化和反序列化,序列化时会将内部字段和键值对直接写入对象输出流中,反序列化时从对象输入流中按顺序读取字段值和键值对,详见 writeObject(ObjectOutputStream) 和 readObject(ObjectInputStream) 方法。

为什么 hashCode 方法里使用 31 作为乘数? #

  • 乘数:因为经常需要将多个数据合并为一个数据,相较加法,乘数方法(对第一个数乘以一个固定值后加上第二个数)可以更大概率保留这两个数据的原始特征。
  • 质数:31作为质数乘数可以使结果更加分散,减少冲突概率。
  • 效率:31作为乘数,可优化为左移5位再减去原始值,提高计算效率。

外部命令? #

TODO search: java.lang.ProcessBuilder, java.lang.Process

注解 #

  • 代码中的特殊标记
  • 可以在编译、类加载、运⾏时被读取,执⾏相对应的处理

java自带常用注解:

  • FunctionanInterface

元注解:

  • ⽤来修饰注解的
  • 常用的有@Retention、@Target、@Documented

@Retention:

  • RetentionPolicy.SOURCE:注解只在源码阶段保留
  • RetentionPolicy.CLASS:注解只被保留到编译进行的时候
  • RetentionPolicy.RUNTIME:在程序运行时可以获取到它们

@Target:

  • ElementType.ANNOTATION_TYPE
  • ElementType.CONSTRUCTOR
  • ElementType.FIELD
  • ElementType.LOCAL_VARIABLE
  • ElementType.METHOD
  • ElementType.PACKAGE
  • ElementType.PARAMETER
  • ElementType.TYPE

@Inherited:

  • 修饰在父类中,子类继承该父类被@Inherited修饰的注解

@Repeatble:

  • 允许被修饰注解重复修饰同一处
  • 在java8以前没有此元注解,只能手动添加一个数组注解

@FunctionanInterface #

  • 将接口标记为函数式接口
  • 编译时检查被标记的接口是否是合法的函数式接口

函数式接口:

  • 只有一个抽象方法
  • 可以有任意数量的默认方法、静态方法、覆盖Object类的方法
  • 配合lambda表达式而设计

泛型 #

  • 将类型参数化
  • 编译期间匹配类型
2024年11月4日