评论走起

java基础面试题整理

以下面试题通过网络整理,参考了很多文章,并结合自己的一点理解进行描述,因参考文章较多,因此不再注明来源,望谅解。 [b]HashMap原理[/b] HashMap由数组和链表组成,在HashMap实现中,维护这一个数组结构,在HashMap中存入键值时,通过计算键的哈希值进而确定存放数组中的位置。然而,哈希值的计算过程中,有可能会出现哈希值一直样的情况,称为哈希冲突,也叫哈希碰撞。在这种情况下,HashMap通过在数组中存储链表的方式解决了哈希冲突的问题。在每个数组中,同时又维护了一个链表结构,这样共同组成了HashMap。 如果在对应数组中没有链表的存在,那么在插入数据和查询数据的操作效率都很高,因为不存在链表结构,只需要维护数组对应位置的一个Entry对象。 但是在如果数组位置上维护这链表情况下,查询效率会降低,因为要一个一个的遍历链表上的数据;但添加和删除操作效率更高。这也是和链表本身的结构特性相关的。 HashMap是可以使用空键值对的,当key为null时,HashMap会把对应的键值存放在内部数组索引为0的位置,如果通过get方法获取一个key为null的值时,HashMap会直接从数组中的索引为0的位置获取对应的值进行返回。 此外,HashMap是线程不安全的,在使用的时候应该注意。 [b]HashMap和HashTable的区别[/b] 1.HashMap是线程不安全的,而HashTable是线程安全的。 2.HashMap允许使用null键值存储,而HashTable不允许,无论是键或值为null键值会抛NullPointerException异常。 [b]String类为什么是final修饰的?[/b] String类使用final修饰的原因在于对String实例的安全性做考虑。在String类的内部实际上是维护这一个final修饰的char数组value,而final修饰的数组实际上仅仅只是引用地址不能被修改,而数组内部的元素还是可以修改的。在String内部的各种对string进行操作的方法中,都刻意保证了char数组中的元素不会被修改。同时,通过final修饰的String类无法被其他类继承,这也就从根源阻止了子类对他的方法的覆盖,增加了String类的安全性。 [b]ArrayList和LinkedList各自实现和区别[/b] ArrayList内部维护着一个数组,该数组可以根据添加元素的数量进行扩容。ArrayList可以对其中的元素实行精确定位,并可以指定元素添加的位置。在查询上效率比较高,而修改上效率会相对比较低下,因为修改元素后需要重新调整元素的位置。 LinkedList内部维护这一个链表结构,在修改上效率会相对较高,而在元素查找时,LinkedList需要遍历链表上的元素,效率相对低下。 此外,ArrayList和LinkedList都不是线程安全的,在多线程并发访问情况下,应注意线程安全问题。 [b]Java中的队列都有哪些,有什么区别?[/b] java中的队列分为阻塞队列和普通队列。阻塞队里在添加元素时,如果队列已经满了,那添加会被阻塞,直到有空间才能继续添加;同时,在获取元素的时候,如果队列中的元素为空,获取动作会被阻塞,直到队列中有元素才能继续获取。 普通队列使用了非阻塞算法,通过使用低层次的并发原语,比如比较交换(CAS)取代了锁。 [b]Class.forName和ClassLoader的区别[/b] Class.forname和ClassLoader都可以对类进行加载,区别如下: 1. Class.forName:除了将类的.class文件加载到jvm以外,还做了对类的解释,执行类中的static静态代码块。 2. ClassLoader:ClassLoader仅仅只会加载class文件到jvm中,而不会执行static静态代码块。只有在newInstance的时候去执行static静态代码块的代码。 [b]Java数组和链表两种结构的操作效率[/b] 相对而言,在数组中维护这元素的索引,所以在查询元素的时候,数组能够很快定位到元素的位置,效率会高些。而链表维护这元素的上一个元素和下一个元素的引用,在添加和删除的操作上效率会高很多,但是在查询是,因链表需要遍历所有元素进行比较,所以效率会相对较低。 [b]String、StringBuilder、StringBuffer区别[/b] 1.String:string是字符串常量,是不可变的,对string字符串进行拼接时,实际是重新创建了一个字符串对象,并把原来的变量引用指向新的字符串对象地址。 2.StringBuffer:StringBuilder是一个线程安全的动态字符串拼接方案,通过StringBuilder对字符串进行拼接不会重新创建字符串对象,而所有的操作都在同一个StringBuilder对象上完成,提高了代码执行的效率。 3.StringBuilder:StringBuilder在实现上通StringBuffer十分相似,但他不是线程安全的,在不考虑并发情况下,使用StringBuilder的效率要高于StringBuffer。 [b]检查异常和非检查异常的区别[/b] 检查异常:除了继承自RuntimeException的异常都是检查异常。检查异常即非运行时异常,此类异常由编译时产生,这类异常必须try catch或者throw出去,否则不能通过编译。比如:FileNotFoundException 非检查异常:相反,非检查异常则是继承自RuntimeException的异常,即运行时异常。此类异常不需要在编程中进行try catch,发生此异常是在程序运行过程中,比如:ArrayIndexOutOfBoundsException [b]异常和错误的区别[/b] 异常:异常是应用程序中可预测、可恢复的问题,大多数异常表示为中、轻度问题,他是在程序运行过程中在特定环境操作下产生的。 错误:错误表示程序运行中比较严重的问题,大多数与程序编写无关,而是在jvm运行过程中出现问题产生的,比如:OutOfMemoryError [b]java中基础数据类型和包装类有什么区别[/b] 声明方式不同,基础数据类型创建不需要通过new的方式创建,包装类需要。 包装类提供数据操作的方法,对象的调用是通过引用对象的地址。基础类型不是。 基础类型是值传递,包装类是引用传递。 存储位置不同,基础类型存储在栈中,包装类对象存储在堆中。 初始值不同。基础类型有自己独有的默认值,而包装类初始值为null。 [b]java的引用类型有哪几种[/b] 强引用:如果一个对象存在强引用,则绝不会被垃圾回收器回收。强引用示例:A a = new A(); 软引用:如果一个对象存在软引用,当内存足够的时候垃圾回收器不会回收他。 弱引用:与软引用相比,弱引用具有更短的声明周期。在垃圾回收器管辖的内存范围内,如果发现对象是软引用,不管内存是否足够,都会回收他,只是垃圾回收器不一定立即会回收而已。 虚引用:虚引用不会决定对象的生命周期,如果一个对象仅持有虚引用,垃圾回收器将随时会回收他。 [b]接口和抽象类的区别[/b] 接口通过interface进行定义,而抽象类通过abstract进行修饰。 接口中的变量隐式的通过public static final进行修饰,而抽象类中可以自由定义。 接口中所有方法都没有具体实现,只有定义(在java8中接口可以有默认的方法实现),而抽象类中可以有方法的具体实现,也可以不实现。 接口可以多实现,抽象类只能单继承。 [b]解决hash冲突的方法[/b] 开放地址法 再哈希法 链地址法 建立公共溢出区 [b]IO和NIO的区别[/b] IO面向流,NIO面向缓冲区。面向流即每次从流中读一个或多个字节,直到读完所有字节,在读取过程中没有缓存区,也不可以前后移动从流中读取的数据;而NIO读取数据到缓冲区,可以前后移动读取数据,但在读取数据到缓冲区时应注意不要覆盖已读的数据。 IO是阻塞的,NIO是非阻塞的,从而NIO效率会更高。 [b]什么时候用字节流,什么时候用字符流[/b] 处理字节或者二进制对象是用字节流;处理文字或者字符串用字符流。

评论