Java面试题全集(二)

发布时间 2023-07-24 08:29:54作者: 等风来う

1. ⾸先CopyOnWriteArrayList内部也是⽤过数组来实现的,在向CopyOnWriteArrayList添加元素时,会复制⼀个新的数组,写操作在新数组上进⾏,读操作在原数组上进⾏

2. 并且,写操作会加锁,防⽌出现并发写⼊丢失数据的问题

3. 写操作结束之后会把原数组指向新数组

4. CopyOnWriteArrayList允许在写操作时来读取数据,⼤⼤提⾼了读的性能,因此适合读多写少的应⽤场景,但是CopyOnWriteArrayList会⽐较占内存,同时可能读到的数据不是实时最新的数据,所以不适合实时性要求很⾼的场景

 

什么是字节码?采⽤字节码的好处是什么?

编译器(javac)将Java源⽂件(*.java)⽂件编译成为字节码⽂件(*.class),可以做到⼀次编译到处运⾏,
windows上编译好的class⽂件,可以直接在linux上运⾏,通过这种⽅式做到跨平台,不过Java的跨平
台有⼀个前提条件,就是不同的操作系统上安装的JDK或JRE是不⼀样的,虽然字节码是通⽤的,但是
需要把字节码解释成各个操作系统的机器码是需要不同的解释器的,所以针对各个操作系统需要有各⾃
的JDK或JRE。
采⽤字节码的好处,⼀⽅⾯实现了跨平台,另外⼀⽅⾯也提⾼了代码执⾏的性能,编译器在编译源代码
时可以做⼀些编译期的优化,⽐如锁消除、标量替换、⽅法内联等。

 

Java中的异常体系是怎样的

Java中的所有异常都来⾃顶级⽗类Throwable。 Throwable下有两个⼦类Exception和Error。 Error表示⾮常严重的错误,⽐如java.lang.StackOverFlowError和 Java.lang.OutOfMemoryError,通常这些错误出现时,仅仅想靠程序⾃⼰是解决不了的,可能是 虚拟机、磁盘、操作系统层⾯出现的问题了,所以通常也不建议在代码中去捕获这些Error,因为捕 获的意义不⼤,因为程序可能已经根本运⾏不了了。 Exception表示异常,表示程序出现Exception时,是可以靠程序⾃⼰来解决的,⽐如NullPointerException、IllegalAccessException等,我们可以捕获这些异常来做特殊处理。 Exception的⼦类通常⼜可以分为RuntimeException和⾮RuntimeException两类 RunTimeException表示运⾏期异常,表示这个异常是在代码运⾏过程中抛出的,这些异常是⾮检查 异常,程序中可以选择捕获处理,也可以不处理。这些异常⼀般是由程序逻辑错误引起的,程序应该从逻 辑⻆度尽可能避免这类异常的发⽣,⽐如NullPointerException、IndexOutOfBoundsException等。 ⾮RuntimeException表示⾮运⾏期异常,也就是我们常说的检查异常,是必须进⾏处理的异常,如果 不处理,程序就不能检查异常通过。如IOException、SQLException等以及⽤户⾃定义的Exception异 常。

 

在Java的异常处理机制中,什么时候应该抛出异常,什么时候捕获异常?

异常相当于⼀种提示,如果我们抛出异常,就相当于告诉上层⽅法,我抛了⼀个异常,我处理不了这个 异常,交给你来处理,⽽对于上层⽅法来说,它也需要决定⾃⼰能不能处理这个异常,是否也需要交给 它的上层。 所以我们在写⼀个⽅法时,我们需要考虑的就是,本⽅法能否合理的处理该异常,如果处理不了就继续 向上抛出异常,包括本⽅法中在调⽤另外⼀个⽅法时,发现出现了异常,如果这个异常应该由⾃⼰来处 理,那就捕获该异常并进⾏处理。

 

Java中有哪些类加载器

JDK⾃带有三个类加载器:bootstrap ClassLoader、ExtClassLoader、AppClassLoader。

  1. BootStrapClassLoader是ExtClassLoader的⽗类加载器,默认负责加载%JAVA_HOME%lib下的 jar包和class⽂件。
  2. ExtClassLoader是AppClassLoader的⽗类加载器,负责加载%JAVA_HOME%/lib/ext⽂件夹下的 jar包和class类。
  3. AppClassLoader是⾃定义类加载器的⽗类,负责加载classpath下的类⽂件。

 

说说类加载器双亲委派模型

JVM中存在三个默认的类加载器:

1. BootstrapClassLoader

2. ExtClassLoader

3. AppClassLoader

AppClassLoader的⽗加载器是ExtClassLoader,ExtClassLoader的⽗加载器是 BootstrapClassLoader。 JVM在加载⼀个类时,会调⽤AppClassLoader的loadClass⽅法来加载这个类,不过在这个⽅法中,会 先使⽤ExtClassLoader的loadClass⽅法来加载类,同样ExtClassLoader的loadClass⽅法中会先使⽤ BootstrapClassLoader来加载类,如果BootstrapClassLoader加载到了就直接成功,如果 BootstrapClassLoader没有加载到,那么ExtClassLoader就会⾃⼰尝试加载该类,如果没有加载到, 那么则会由AppClassLoader来加载这个类。 所以,双亲委派指得是,JVM在加载类时,会委派给Ext和Bootstrap进⾏加载,如果没加载到才由⾃⼰ 进⾏加载。