栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

面试专题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

面试专题

1.通过字面量创建字符串和new一个字符串对象有什么区别?

内存分配的方式不不一样
通过字面量创建字符串对象会分配到常量池中 若再次使用该字面量创建新字符串时候,不在创建新对象,而是从常量池中获取
通过new一个字符串对象会分配到堆内存中

2.什么是常量池?

常量池在Java用于保存在编译器已确定的,已编译的class文件中的一份数据.它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = “Java” 这种声明方式; 当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间

3.做字符串拼接的时候可以使用String吗?

不建议直接使用String做拼接,最好使用StringBuilder或者StringBuffer来做拼接

4.StringBuilder和StringBuffer有什么区别呢?

共同之处:
1.都继承了AbstractStringBuilder这个抽象类,实现了CherSequence接口
2.其append方法都是super.append(str),调用了父类AbstractStringBuilder的append(String str)方法
3.初始容量都是16,扩容机制都是"旧容量*2+2"
4.底层都是char[]字符数组实现,且字符数组都是可变的,这点不同于String
不同之处
1.StringBuffer从JDK1.0就有了,StringBuilder是JDK5.0才出现
2.StringBuilder是非线程安全的,效率更高。StringBuffer是线程安全的,效率低一些,但安全。
3.只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。
4.在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全而StringBuffer则每次都需要判断锁,效率相对更低。

5.子类重写父类含有抛出异常的方法时候,有哪些要求?

不再抛出任何异常;
仅抛出部分异常;
抛出子类异常;
不可以抛出额外异常;
不可以抛出父类异常;

6.final. finally. finalize有什么区别?

final 用于修饰类,变量,方法,修饰类表示该类不可以被继承,修饰方法表示该方法不可以被重写,修饰变量表示不可以重新赋值
finally一般作用在try-catch捕获异常代码块中,不论代码是否发生异常,finally中的代码一定会被执行,通常用来关闭一些资源时候使用
finalize 属于Object类中的一个方法,当对象被收回的时候,会调用此方法

7.List集合和Set集合有什么区别?

相同部分:
List 与 Set 具有相似性,他们都是单列元素的集合,所以他们有一个功能共同的父接口,叫Collection

区别:
Set里边不允许有重复的元素,所谓重复,即不能有两个相等的对象.
假设Set集合中有了一个A对象,现在我要向Set集合中再存入一个B对象,但是B对象与A对象equals相等,则B对象存储不进去,所以,Set集合的add方法有一个boolean的返回值,当集合中没有某个元素,此时add方法可成功加入该元素,则返回true,当集合含有与某个元素equals相等的元素时,此时add方法无法加入该元素,则返回值结果为false.
Set取元素时候,没法说取第几个,只能以Iterator接口取得所有的元素,再逐一遍历各个元素.

List表示有先后顺序的集合, 注意, 不是那种按照年龄,按大小, 按价格之类的排序
当我们多次调用当我们多次调用 add(Obj e)方法时,每次加入的对象就像火车站买票有排队顺序一样,按先来后到的顺序排序。有时候,也可以插队,即调用 add(int index,Obj e)方法,就可以指定当前对象在集合中的存放位置.一个对象可以被反复存入List中,每调用一次add方法,这个对象就被插入进集合中一次,其实并不是把这个对象本身存储到集合中,而是在集合中用一个索引变量指向这个对象,当这个对象被add多次时候,即相当于集合中有多个索引指向了这个对象.
List除了可以以Iterator接口取得所有的元素,再逐一遍历各个元素之外,还可以调用get(index i)来明确的说明取第几个元素

总结:
List以特定次序来持有元素,可以有重复元素, Set无法拥有重复元素,内部排序
另外,再Set集合中, hashset集合比较两个对象是否相等,首先看Hashcode方法是否相等,然后看equals方法是否相等. new两个Student插入到HashSet中,看HashSet的size,实现hashcode和equals方法后再看size

8.集合中的泛型有什么用?

泛型,在C++中被称为模板,就是一种抽象的编程方式,当我们定义类和方法的时候,可以用一种通用的方式进行定义,而不必写出具体的类,这些未知的东西会在真正使用的时候再确定
对于集合类来说,他们可以存放格中类型的元素,如果在存放之前,就能确定元素的类型,那么就可以更加直观.也让代码更简洁.示例代码如下:

public class Test4 {
 
	public static void main(String[] args) {
		List list=new ArrayList();//无泛型创建链表对象
		list.add("a");
		list.add("b");
		Iterator it=list.iterator();//获取链表迭代器
		while (it.hasNext()) {
			Object obj=it.next();//获取元素,类型为Object
			String s=(String) obj;
			System.out.println(s);
		}
		Listlist2=new ArrayList<>();//String泛型链表对象
		list2.add("c");
		list2.add("d");
		//用foreach进行遍历,类型转换为String
		for (String str : list2) {
			System.out.println(str);
		}
	}
}

上面代码中, List 没有使用泛型,他所存放的元素都是Object类型,在使用的时候还需要进行类型的强制转换
泛型链表对象list2,在创建的时候就提供了元素的类型,因此,在获取元素的时候,类型会自动转换,这也是集合使用泛型的最直接的好处.

说明: java的泛型是停留在编译层的,也就是说JVM在对待泛型数据的时候,依然会把他们看成是Object类型,只不过在使用这些元素的时候,JVM会自动帮助我们进行相应的类型转换

总结: 集合使用泛型之后,可以达到元素类型明确的目的,避免了手动类型转换的过程,同时,也让我们更加明确容器保存的是什么类型的数据

9.常用的List集合有哪些呢? 有什么区别?

常用的List集合有ArrayList. linkedList. Voctor
ArrayList的一些特点及原理
排列有序,可重复,底层使用数组存储,读取速度快,增删慢,getter()和setter()方法快,线程不安全,当容量不够时候,ArrayList会扩容当前容量的一半
从源码可以看出,ArrayList本质就是数组,当采用无参的构造函数初始化的时候,最初容量是0,等到采用add()操作时,会将容量设为默认的容量10
通常情况下,数组列表的容量扩容是增加当前容量的一半,即扩容之后的容量是原容量的1.5倍,而且并不是可以无限扩容的,为了防止内存溢出,源码做了最大容量的限制,相关的新增删除的操作没有加锁或者synchronized关键字,因此线程不安全
linkedList的一些特点及原理
排列有序,可重复,底层使用的是双向循环链表数据结构存储.查询速度慢,增删快,add()和remove()方法快,线程不安全
linkedList内部定义了内部类Node作为双向链表的数据节点,因此双向链表的操作的特点就是linkedList操作的特点,并且相关的新增删除的操作没有加锁或者synchronized关键字,因此线程不安全
Vector的一些特点及其原理
排序有序,可重复,底层使用数组存储,读取速度快,增删慢,线程安全,sychronized关键字加在方法上,效率低,默认容量是10,当容量不够时候,Vector默认扩展一倍容量
Vector的内部和ArrayList一样也是使用数组存储,因此这两个类很多相似点不同的是:

  • ArrayList在内部定义数组的时候使用了transient关键字,而 Vector没有使用该关键字,因此在对象这两个类定义的对象在序列化的时候是不同的
  • ArrayList默认的扩容是当前容量的一半, 而Vector默认的扩容是当前容量的一倍
  • ArrayList的相关操作是线程不去安全的, 而Vector在相关的操作方法前加了Synchronized关键字,因此是线程安全的。
10.什么是队列? 什么是栈? 他们遵循什么原则?

队列是用于存储一组元素的数据结构,但是存取元素必须遵循先进先出的原则
栈也是用于存储一组元素,存取必须遵循先进后出的原则.

11.HashMap的底层数据结构是什么?

在JDK1.7 的时候是数组+链表
在JDK1.8 的时候是数组+链表+红黑树
当链表的长度大于8的时候,就会变为红黑树.

12.HashMap, HashTable, ConcurrentHashMap有什么区别

HashTable

  • 底层数组+链表实现, 无论key还是value都不能为null, 线程安全, 实现线程安全的方式实在修改数据时候锁住了整个HashTable, 效率低, ConcurrentHashMap做了相关优化
  • 初始size为11, 扩容: newsize = oldsize*2+1
  • 计算index的方法: index= (hash & 0x7FFFFFFF) % tab.length

HashMap

  • 底层数组+链表实现, 可以存储null键和null值, 线程不安全
  • 初始size为16, 扩容: newsize = oldsize*2, size一定为2的n次幂
  • 扩容针对整个Map.每次扩容时候,原来数组中的元素依次重新计算存放位置,并重新插入
  • 插入元素后才判断该不该扩容,有可能无效扩容(插入后扩容,如果没有再次插入,就会产生无效扩容)
  • 当Map中元素总数超过Entry数组的75%, 触发扩容操作,为了减少链表长度,元素分配更均匀
  • 计算index方法: index = hash & (tab.length -1)
  • HashMap的初始值还要考虑加载因子:
    • 哈希冲突: 若干Key的哈希值按数组大小取模后,如果落在同一个数组下标上,将组成一条Entry链,对Key的查找需要遍历Entry链上的每个元素执行equals()比较。
    • 加载因子 为了降低哈希冲突的概率,默认当HashMap中的键值对达到数组大小的75%时,即会触发扩容。因此,如果预估容量是100,即需要设定100/0.75=134的数组大小。
    • 空间换时间 如果希望加快Key查找的时间,还可以进一步降低加载因子,加大初始大小,以降低哈希冲突的概率。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/345126.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号