- JAVA中能创建volatile数组吗?volatile能使得一个非原子操作变成原子操作吗?
可以,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。
Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是volatile 型的 long 或 double 变量的读写是原子。 - 10个线程和2个线程的同步代码,哪个更容易写?
从写代码的角度来说,两者的复杂度是相同的,因为同步代码与线程数量是相互独立的。但是同步策略的选择依赖于线程的数量,因为越多的线程意味着更大的竞争,所以你需要利用同步技术,如锁分离,这要求更复杂的代码和专业知识。 - 什么是线程局部变量?
对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。 - 是否可以自己写一个容器类,然后使用for-each循环吗?
可以,你可以写一个自己的容器类。如果你想使用 Java 中增强的循环来遍历,你只需要实现 Iterable接口。如果你实现 Collection 接口,默认就具有该属性。 - 说出5条IO的最佳实践?
- 使用有缓冲区的 IO 类,而不要单独读取字节或字符。
- 使用 NIO 和 NIO2
- 在 finally 块中关闭流,或者使用 try-with-resource 语句。
- 使用内存映射文件获取更快的 IO。
- 使用非阻塞式而不要使用阻塞式的IO
- 说出至少5点在Java中使用线程的最佳实践?
- 对线程命名
- 将线程和任务分离,使用线程池执行器来执行 Runnable 或 Callable。
- 使用线程池
- 如果可以,更偏向于使用 volatile 而不是 synchronized。
- 优先使用并发集合,而不是对集合进行同步。并发集合提供更好的可扩展性。
- 能在不进行强制转换的情况下将一个double值赋值给long类型的变量吗?
不能,因为 double 类型的范围比 long 类型更广,所以必须要进行强制转换。 - 能在Switch中使用String吗?
在jdk 7 之前,switch 只能支持 byte、short、char、int 这几个基本数据类型和其对应的封装类型。switch后面的括号里面只能放int类型的值,但由于byte,short,char类型,它们会 自动 转换为int类型(精精度小的向大的转化),所以它们也支持。jdk1.7后,整形,枚举类型,boolean,字符串都可以。
jdk1.7并没有新的指令来处理switch string,而是通过调用switch中string.hashCode,将string转换为int从而进行判断。 - poll()方法和remove()方法的区别?
poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。 - LinkedList和ArrayList的区别?
- ArrayList和LinkedList可想从名字分析,它们一个是Array(动态数组)的数据结构,一个是Link(链表)的数据结构,此外,它们两个都是前者是数组队列,相当于动态数组;后者为双向链表结构,也可当作堆栈、队列、双端队列对List接口的实现。
- 当随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
- 当对数据进行增加和删除的操作时(add和remove操作),LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。
- 从利用效率来看,ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。
- ArrayList主要控件开销在于需要在lList列表预留一定空间;而LinkList主要控件开销在于需要存储结点信息以及结点指针信息。
- hashmap的扩容问题new hashmap(19)它的长度是多少?
初始长度是19,当达到默认加载因子的时候会进行扩容 - hashtable为什么是线程安全的?
Hashtable是线程安全的,其实现方式是在对应的方法上加上synchronized关键字,效率不高,不建议使用。目前,如果要使用线程安全的哈希表的话,推荐使用ConcurrentHashMap。 - java异常处理怎么做?
- 对代码块用try…catch进行异常捕获处理;
- 在该代码的方法体外用throws进行抛出声明,告知此方法的调用者这段代码可能会出现这些异常,你需要谨慎处理。此时有两种情况:1)如果声明抛出的异常是非运行时异常,此方法的调用者必须显示地用try…catch块进行捕获或者继续向上层抛出异常;2)如果声明抛出的异常是运行时异常,此方法的调用者可以选择地进行异常捕获处理。
- 在代码块用throw手动抛出一个异常对象,此时也有两种情况,跟上一点中的类似:1)如果抛出的异常对象是非运行时异常,此方法的调用者必须显示地用try…catch块进行捕获或者继续向上层抛出异常;2)如果抛出的异常对象是运行时异常,此方法的调用者可以选择地进行异常捕获处理。
- 异常处理的作用是什么?
因为不可能保证程序不出错,所以使用异常处理来防止程序出错的时候你无从下手的局面,对于调试程序和项目实际开发都是有用的 - jvm内存的分配?
- 程序计数器:线程私有,当前线程执行的字节码的行号指示器。
- 虚拟机栈:线程私有,存放基本数据类型、对象引用和returnAddress类型。
- 本地方法栈:为虚拟机使用到的Native方法服务。
- Java堆:线程共享,存放对象的实例,也是GC回收器管理的主要区域。
- 方法区:线程共享,存放已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
- 运行时常量池:方法区的一部分,存放编译期生成的各种字面量和符号引用。
- 直接内存:不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,容易引起OOM异常,NIO会调用,不受Java堆大小的限制。
- Abstract和interface区别?
- abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。
- 在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的。
- abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。
- 实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。
- 接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。
- 抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。
- 接口中的方法默认都是 public,abstract 类型的。
码巢对标阿里P6
获取更多面试以及学习资料,请扫码加入我们的群聊以及关注我们的微信公众号