0
点赞
收藏
分享

微信扫一扫

JAVA最全面试题汇总基础篇(四)


1.Java IO NIO 的区别(补充)


NIO 即 New IO ,这个库是在 JDK1.4 中才引入的。 NIO 和 IO 有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以 NIO 的效率要比 IO 高很多。在 Java API 中提供了两套 NIO ,一套是针对标准输入输出NIO ,另一套就是网络编程 NIO 。


2 java 反射的作用于原理


1 、定义:


反射机制是在运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意个对象,


都能够调用它的任意一个方法。在 java 中,只要给定类的名字,就可以通过反射机制来获得类的所


有信息。


这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。


2 、哪里会用到反射机制?


jdbc 就是典型的反射


Class . forName ( 'com.mysql.jdbc.Driver.class' ); // 加载 MySQL 的驱动类


这就是反射。如 hibernate , struts 等框架使用反射实现的。


3 、反射的实现方式:


第一步:获取 Class 对象,有 4 中方法: 1 ) Class.forName(“ 类的路径 ”) ; 2 )类名 .class 3 )对象


名 .getClass() 4 )基本类型的包装类,可以调用包装类的 Type 属性来获得该包装类的 Class 对象


4 、实现 Java 反射的类:


1 ) Class :表示正在运行的 Java 应用程序中的类和接口 注意:


所有获取对象的信息都需要 Class 类


来实现。 2 ) Field :提供有关类和接口的属性信息,以及对它的动态访问权限。 3 ) Constructor :


提供关于类的单个构造方法的信息以及它的访问权限 4 ) Method :提供类或接口中某个方法的信息


5 、反射机制的优缺点:


优点: 1 )能够运行时动态获取类的实例,提高灵活性; 2 )与动态编译结合 缺点: 1 )使用反射


性能较低,需要解析字节码,将内存中的对象进行解析。 解决方案: 1 、通过 setAccessible(true)


关闭 JDK 的安全检查来提升反射速度; 2 、多次创建一个类的实例时,有缓存会快很多 3 、


ReflflectASM 工具类,通过字节码生成的方式加快反射速度 2 )相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)


3 、说说 List,Set,Map 三者的区别?


List( 对付顺序的好帮手 ) List 接口存储一组不唯一(可以有多个元素引用相同的对象),有序


的对象


Set( 注重独一无二的性质 ): 不允许重复的集合。不会有多个元素引用相同的对象。


Map( Key 来搜索的专家 ): 使用键值对存储。 Map 会维护与 Key 有关联的值。两个 Key 可以引


用相同的对象,但 Key 不能重复,典型的 Key 是 String 类型,但也可以是任何对象。


4. Object 有哪些常用方法?大致说一下每个方法的含义


java.lang.Object 下面是对应方法的含义。


clone 方法


保护方法,实现对象的浅复制,只有实现了 Cloneable 接口才可以调用该方法,否则抛出


CloneNotSupportedException 异常,深拷贝也需要实现 Cloneable ,同时其成员变量为引用类型


的也需要实现 Cloneable ,然后重写 clone 方法。


fifinalize 方法


该方法和垃圾收集器有关系,判断一个对象是否可以被回收的最后一步就是判断是否重写了此方


法。


equals 方法


该方法使用频率非常高。一般 equals 和 == 是不一样的,但是在 Object 中两者是一样的。子类一


般都要重写这个方法。


hashCode 方法


该方法用于哈希查找,重写了 equals 方法一般都要重写 hashCode 方法,这个方法在一些具有哈


希功能的 Collection 中用到。


一般必须满足 obj1.equals(obj2)==true 。可以推出 obj1.hashCode()==obj2.hashCode() ,但是


hashCode 相等不一定就满足 equals 。不过为了提高效率,应该尽量使上面两个条件接近等价。


JDK 1.6 、 1.7 默认是返回随机数;


JDK 1.8 默认是通过和当前线程有关的一个随机数 + 三个确定值,运用 Marsaglia’s xorshift


scheme 随机数算法得到的一个随机数。


wait 方法


配合 synchronized 使用, wait 方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥


有者,也就是具有该对象的锁。 wait() 方法一直等待,直到获得锁或者被中断。 wait(long timeout)


设定一个超时间隔,如果在规定时间内没有获得锁就返回。


调用该方法后当前线程进入睡眠状态,直到以下事件发生。


1. 其他线程调用了该对象的 notify 方法;


2. 其他线程调用了该对象的 notifyAll 方法;


3. 其他线程调用了 interrupt 中断该线程;


4. 时间间隔到了。


此时该线程就可以被调度了,如果是被中断的话就抛出一个 InterruptedException 异常。


notify 方法


配合 synchronized 使用,该方法唤醒在该对象上 等待队列 中的某个线程(同步队列中的线程是给


抢占 CPU 的线程,等待队列中的线程指的是等待唤醒的线程)。


notifyAll 方法


配合 synchronized 使用,该方法唤醒在该对象上等待队列中的所有线程。


总结


只要把上面几个方法熟悉就可以了, toString 和 getClass 方法可以不用去讨论它们。该题目考察的是对 Object 的熟悉程度,平时用的很多方法并没看其定义但是也在用,比如说: wait() 方法,


equals() 方法等。


大致意思: Object 是所有类的根,是所有类的父类,所有对象包括数组都实现了 Object 的方法。


5 Java 创建对象有几种方式?


这题目看似简单,要好好回答起来还是有点小复杂的,我们来看看,到底有哪些方式可以创建对


象?


使用 new 关键字 ,这也是我们平时使用的最多的创建对象的方式,示例:


使用反射方式创建对象 ,使用 newInstance() ,但是得处理两个异常 InstantiationException 、


IllegalAccessException :


Class Object is the root of the class hierarchy.Every class has Object as a


superclass. All objects, including arrays, implement the methods of this class.


User user=new User();


User user=User.class.newInstance();


Object object=(Object)Class.forName("java.lang.Object").newInstance()


使用 clone 方法 ,前面题目中 clone 是 Object 的方法,所以所有对象都有这个方法。


使用反序列化创建对象 ,调用 ObjectInputStream 类的 readObject() 方法。


我们反序列化一个对象, JVM 会给我们创建一个单独的对象。 JVM 创建对象并不会调用任何构造函 数。一个对象实现了 Serializable 接口,就可以把对象写入到文件中,并通过读取文件来创建对


象。


总结


创建对象的方式关键字: new 、反射、 clone 拷贝、反序列化。


6 、获取一个类 Class 对象的方式有哪些?


搞清楚类对象和实例对象,但都是对象。


第一种:通过类对象的 getClass() 方法获取,细心点的都知道,这个 getClass 是 Object 类里面的


方法。


第二种:通过类的静态成员表示,每个类都有隐含的静态成员 class 。


第三种:通过 Class 类的静态方法 forName() 方法获取。


7 ArrayList LinkedList 的区别有哪些?


ArrayList


优点 : ArrayList 是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询


操作效率会比较高(在内存里是连着放的)。


缺点 :因为地址连续, ArrayList 要移动数据,所以插入和删除操作效率比较低。


LinkedList


User user = new User ();


//clazz 就是一个 User 的类对象


Class <?> clazz = user . getClass ();


//clazz 就是一个 User 的类对象


Class <?> clazz = User . class ;


Class <?> clazz = Class . forName ( "com.tian.User" );


优点 : LinkedList 基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等


一个连续的地址。对于新增和删除操作, LinkedList 比较占优势。 LinkedList 适用于要头尾操


作或插入指定位置的场景。


缺点 :因为 LinkedList 要移动指针,所以查询操作性能比较低。


适用场景分析


当需要对数据进行对随机访问的时候,选用 ArrayList 。


当需要对数据进行多次增加删除修改时,采用 LinkedList 。


如果容量固定,并且只会添加到尾部,不会引起扩容,优先采用 ArrayList 。


当然,绝大数业务的场景下,使用 ArrayList 就够了,但需要注意避免 ArrayList 的扩容,以及非顺


序的插入。


8 、用过 ArrayList 吗?说一下它有什么特点?


只要是搞 Java 的肯定都会回答 “ 用过 ” 。所以,回答题目的后半部分 ——ArrayList 的特点。可以从这几个方面去回答:


Java 集合框架中的一种存放相同类型的元素数据,是一种变长的集合类,基于定长数组实现,当加入数据达到一定程度后,会实行自动扩容,即扩大数组大小。


底层是使用数组实现,添加元素。


如果 add(o) ,添加到的是数组的尾部,如果要增加的数据量很大,应该使用 ensureCapacity()


方法,该方法的作用是预先设置 ArrayList 的大小,这样可以大大提高初始化速度。


如果使用 add(int,o) ,添加到某个位置,那么可能会挪动大量的数组元素,并且可能会触发扩


容机制。高并发的情况下,线程不安全。多个线程同时操作 ArrayList ,会引发不可预知的异常或错误。


ArrayList 实现了 Cloneable 接口,标识着它可以被复制。注意: ArrayList 里面的 clone() 复制其实


是浅复制。


9 、有数组了为什么还要搞个 ArrayList 呢?


通常我们在使用的时候,如果在不明确要插入多少数据的情况下,普通数组就很尴尬了,因为你不


知道需要初始化数组大小为多少,而 ArrayList 可以使用默认的大小,当元素个数到达一定程度


后,会自动扩容。


可以这么来理解:我们常说的数组是定死的数组, ArrayList 却是动态数组。


10 、说说什么是 fail-fast


fail-fast 机制是 Java 集合( Collection )中的一种错误机制。当多个线程对同一个集合的内容进行


操作时,就可能会产生 fail-fast 事件。


例如:当某一个线程 A 通过 iterator 去遍历某集合的过程中,若该集合的内容被其他线程所改变


了,那么线程 A 访问集合时,就会抛出 ConcurrentModifificationException 异常,产生 fail-fast 事


件。这里的操作主要是指 add 、 remove 和 clear ,对集合元素个数进行修改。


解决办法:建议使用 “java.util.concurrent 包下的类 ” 去取代 “java.util 包下的类 ” 。


可以这么理解:在遍历之前,把 modCount 记下来 expectModCount ,后面 expectModCount 去


和 modCount 进行比较,如果不相等了,证明已并发了,被修改了,于是抛出


ConcurrentModifificationException 异常。


11 、说说 Hashtable HashMap 的区别


本来不想这么写标题的,但是无奈,面试官都喜欢这么问 HashMap 。


1. 出生的版本不一样, Hashtable 出生于 Java 发布的第一版本 JDK 1.0 , HashMap 出生于 JDK


1.2 。


2. 都实现了 Map 、 Cloneable 、 Serializable (当前 JDK 版本 1.8 )。


3. HashMap 继承的是 AbstractMap ,并且 AbstractMap 也实现了 Map 接口。 Hashtable 继承


Dictionary 。


4. Hashtable 中大部分 public 修饰普通方法都是 synchronized 字段修饰的,是线程安全的,


HashMap 是非线程安全的。


5. Hashtable 的 key 不能为 null , value 也不能为 null ,这个可以从 Hashtable 源码中的 put 方


法看到,判断如果 value 为 null 就直接抛出空指针异常,在 put 方法中计算 key 的 hash 值之


前并没有判断 key 为 null 的情况,那说明,这时候如果 key 为空,照样会抛出空指针异常。


6. HashMap 的 key 和 value 都可以为 null 。在计算 hash 值的时候,有判断,如果


key==null ,则其 hash=0 ;至于 value 是否为 null ,根本没有判断过。


7. Hashtable 直接使用对象的 hash 值。 hash 值是 JDK 根据对象的地址或者字符串或者数字算出


来的 int 类型的数值。然后再使用除留余数法来获得最终的位置。然而除法运算是非常耗费时


间的,效率很低。 HashMap 为了提高计算效率,将哈希表的大小固定为了 2 的幂,这样在取


模预算时,不需要做除法,只需要做位运算。位运算比除法的效率要高很多。


8. Hashtable 、 HashMap 都使用了 Iterator 。而由于历史原因, Hashtable 还使用了


Enumeration 的方式。


9. 默认情况下,初始容量不同, Hashtable 的初始长度是 11 ,之后每次扩充容量变为之前的


2n+1 ( n 为上一次的长度)而 HashMap 的初始长度为 16 ,之后每次扩充变为原来的两倍。


另外在 Hashtable 源码注释中有这么一句话:


Hashtable is synchronized. If a thread-safe implementation is not needed, it is


recommended to use HashMap in place of Hashtable . If a thread-safe highly


concurrent implementation is desired, then it is recommended to use


ConcurrentHashMap in place of Hashtable.


大致意思: Hashtable 是线程安全,推荐使用 HashMap 代替 Hashtable ;如果需要线程安全高并


发的话,推荐使用 ConcurrentHashMap 代替 Hashtable 。


这个回答完了,面试官可能会继续问: HashMap 是线程不安全的,那么在需要线程安全的情况下


还要考虑性能,有什么解决方式?


这里最好的选择就是 ConcurrentHashMap 了,但面试官肯定会叫你继续说一下


ConcurrentHashMap 数据结构以及底层原理等。

举报

相关推荐

0 条评论