3、4 月份是面试的黄金季,最近不管是知乎还是微信里,都有不是人在问我要资料,也或者是让我下载一些面试资料。
所以,我还是分享一些简单的面试题吧,希望能够帮助到你们!
面试其实就是靠复习,复习的好,就容易找到工作!
那些面试好几次都没有面试上的,面试的多了,见的题多了。最后不都找到了工作吗?所以说,没有差的程序员,只有懒的程序员!
问:Java 中能创建 volatile 数组吗?
答:能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。
问:volatile 能使得一个非原子操作变成原子操作吗?
答:一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或 double 变量的读写是原子。
问:volatile 修饰符的有过什么实践?
答:一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中 volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(write barrier),读一个 volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个 volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。
问:volatile 类型变量提供什么保证?
答:volatile 变量提供顺序和可见性保证,例如,JVM 或者 JIT为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和 long 就是原子的。
问:Java 中 sleep 方法和 wait 方法的区别?
答:虽然两者都是用来暂停当前运行的线程,但是 sleep() 实际上只是短暂停顿,因为它不会释放锁,而 wait() 意味着条件等待,这就是为什么该方法要释放锁,因为只有这样,其他等待的线程才能在满足条件时获取到该锁。
推荐阅读:《代码中的Thread.sleep(0) 有什么意义?是写错了吗?》,《java线程最熟悉而又陌生的知识点:sleep与wait》。
问:什么是不可变对象(immutable object)?Java 中怎么创建一个不可变对象?
答:不可变对象指对象一旦被创建,状态就不能再改变。任何修改都会创建一个新的对象,如 String、Integer及其它包装类。详情参见答案,一步一步指导你在 Java 中创建一个不可变的类。
推荐阅读:《String 的“不可变性”是因为 final?请别再错下去了!》、《欲练神功必先自宫,String 自宫后“不可变性”到底有啥好处?》、《Java 11 更新了 String 字符串 API,你得重新认识它》。
问:Java 中 ++ 操作符是线程安全的吗?
答:不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差。
推荐阅读:《从 i++ 和 ++i 说起局部变量表和操作数栈!》。
问:a = a + b 与 a += b 的区别?
答:+= 隐式的将加操作的结果类型强制转换为持有结果的类型。如果两这个整型相加,如 byte、short 或者 int,首先会将它们提升到 int 类型,然后在执行加法操作。如果加法操作的结果比 a 的最大值要大,则 a+b 会出现编译错误,但是 a += b 没问题,如下:
byte a = 127; byte b = 127; b = a + b; // error : cannot convert from int to byte b += a; // ok
问:3*0.1 == 0.3 将会返回什么?true 还是 false?
答:false,因为有些浮点数不能完全精确的表示出来。
问:Serial 与 Parallel GC之间的不同之处?
答:Serial 与 Parallel 在GC执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认的复制收集器,执行 GC 的时候只有一个线程,而 parallel 收集器使用多个 GC 线程来执行。
问:32 位和 64 位的 JVM,int 类型变量的长度是多数?
答:32 位和 64 位的 JVM 中,int 类型变量的长度是相同的,都是 32 位或者 4 个字节。
问:Java 中 WeakReference 与 SoftReference的区别?
答:虽然 WeakReference 与 SoftReference 都有利于提高 GC 和 内存的效率,但是 WeakReference ,一旦失去最后一个强引用,就会被 GC 回收,而软引用虽然不能阻止被回收,但是可以延迟到 JVM 内存不足的时候。
问:解释 Java 堆空间及 GC?
答:当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内部的一个进程,回收无效对象的内存用于将来的分配。
问:你能保证 GC 执行吗?
答:不能,虽然你可以调用 System.gc() 或者 Runtime.gc(),但是没有办法保证 GC 的执行。
问:List、Set、Map 和 Queue 之间的区别
答:List 是一个有序集合,允许元素重复。它的某些实现可以提供基于下标值的常量访问时间,但是这不是 List 接口保证的。Set 是一个无序集合。
问:队列的 poll() 方法和 remove() 方法的区别?
答:poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。
问:用哪两种方式来实现集合的排序?
答:你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有顺序的的集合,如 list,然后通过 Collections.sort() 来排序。
问:Java 中怎么打印数组?
答:你可以使用 Arrays.toString() 和 Arrays.deepToString() 方法来打印数组。由于数组没有实现 toString() 方法,所以如果将数组传递给 System.out.println() 方法,将无法打印出数组的内容,但是 Arrays.toString() 可以打印每个元素。
问:Java 中,编写多线程程序的时候你会遵循哪些最佳实践?
答:最佳实践:给线程命名,这样可以帮助调试;最小化同步的范围,而不是将整个方法同步,只对关键部分做同步;如果可以,更偏向于使用 volatile 而不是 synchronized;使用更高层次的并发工具,而不是使用 wait() 和 notify() 来实现线程间通信,如 BlockingQueue,CountDownLatch 及 Semeaphore;优先使用并发集合,而不是对集合进行同步。并发集合提供更好的可扩展性。
问:说出几点 Java 中使用 Collections 的最佳实践?
答:最佳实践:使用正确的集合类,例如,如果不需要同步列表,使用 ArrayList 而不是 Vector;优先使用并发集合,而不是对集合进行同步。并发集合提供更好的可扩展性;使用接口代表和访问集合,如使用List存储 ArrayList,使用 Map 存储 HashMap 等等;使用迭代器来循环集合;使用集合的时候使用泛型。
今天我们就先到这里吧,后面我们再加入高难度的面试题!上面这个个人简历,你们看一下吧!有何感想?
: » 分享几个你可能忽视的 java 面试题
原创文章,作者:745907710,如若转载,请注明出处:https://blog.ytso.com/252048.html