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

发布于:2023-01-04 ⋅ 阅读:(233) ⋅ 点赞:(0)
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 数据结构以及底层原理等。

网站公告

今日签到

点亮在社区的每一天
去签到