java面试题:基础知识

时间:2021-07-08 03:19:23

类和对象

Q:讲一下面向对象OOP思想。
面向对象主要是抽象,封装,继承,多态。
多态又分为重载和重写。重载主要是方法参数类型不一样,重写则是方法内容不一样。
Q:抽象类和接口有什么区别?

  1. 抽象类中可以没有抽象方法;接口中的方法必须是public abstract抽象方法;
  2. 抽象类中可以有普通的成员变量;接口中的变量必须是public static final 类型的,必须被初始化,接口中只有常量,没有变量。
  3. 抽象类只能单继承,接口可以继承多个父接口;
  4. Java 8 中接口中会有 default 方法,即方法可以被实现。

Q:java是值传递还是引用传递?
java是值传递。
因为 Java 是值传递的,也就是说,我们在调用一个需要传递参数的函数时,传递给函数的参数并不是我们传递进去的参数本身,而是它的一个副本,我们改变了数据其实只是改变了副本的数据而已,并不会对原来的参数有任何的改变。
Q:类初始化的顺序是怎样的?
创建类的对象的时候,先初始化静态变量和静态代码块(静态变量和静态代码块的初始化顺序按照在类中的先后顺序),然后再初始化非静态变量和非静态代码块(非静态变量和非静态代码块之间也是按照在类中的先后顺序),如果非静态变量未显示赋值会被赋值为默认值。最后执行构造函数。
Q:final修饰符有什么作用?
1.final修饰的类,不可以被继承。
2.final修饰方法,可以把方法锁定,以防任何继承类修改它的含义。
3.fianl修饰的变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
Q:创建对象的方式有哪些?
new,反射(包括使用Class类的newInstance方法和Constructor类的newInstance方法),clone,反序列化
还可以使用建造者模式。

Object

Q:Object有哪些方法?
getClass(),hashCode(),equals(),wait(),notify(),notifyAll(),toString(),finalize(),clone()
Q:如何理解hashCode()?
Q:hashCode()和equals()有什么联系?
重写equals()必须重写hashCode()。
首先equals与hashcode间的关系是这样的:
1、如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,它们并不一定相同(即用equals比较返回false)
Q:clone()的深复制和浅复制,有什么区别?
浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
深复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

基础类型

Q:基础类型有哪些?怎么比较?
int,char,float,double都是基本类型。 String不是基本类型。
基础类型直接用==比较。
Q:Integer和int的区别?
Integer是int的包装类。
Integer默认值是null,int默认值是0。
int默认是4个字节,Integer是16个字节。
Q: Integer和int怎么比较?Integer怎么比较?
Integer是int的包装类。Integer跟Integer不可以使用==比较。Integer跟int可以使用==比较,Integer会自动拆箱。

String

Q:String怎么比较?从内存角度讲。
使用equals()比较。如果使用==比较的是内存,使用equals()比较的是对象的内容。
Q:String可以继承吗?
String用final修饰,不可以继承。
Q:String和StringBulider、StringBuffer有什么区别?
String长度不可变。StringBuilder、StringBuffer长度可变。
StringBuffer是线程安全的,StringBuilder是线程不安全的。
StringBuffer通过synchronized 关键字来实现同步操作
Q:String里面的equals()是怎么实现的?

IO

Q:IO中用到了哪些设计模式?
IO中用到了装饰器模式,适配器模式。
装饰器模式表现如: BufferedReader reader=new BufferedReader(new FileReader( new File(fileName)));
同样是增强对象的功能,为什么使用装饰器, 而不是继承?
比如功能一,功能二,功能三。装饰器可以根据需要增强功能,随意组合装配。
而由于功能的随机组合有六种,想通过继承增强功能要写六个类。当需要的功能较多时,组合总和太大,通过继承完成不太理想。

异常

Q:Java中的异常有哪些?
Exception分为运行时异常和非运行时异常。
RuntimeException, 运行时异常,特点是Java编译器不会检查它。
非运行时异常 (编译异常): 是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常
Error:用于指示合理的应用程序不应该试图捕获的严重问题。如OutOfMemoryError、*Error。
Q:RuntimeException有哪些?
空指针异常类:NullPointerException
类型强制转换异常:ClassCastException
数组下标越界异常:ArrayIndexOutOfBoundsException
文件已结束异常:EOFException
文件未找到异常:FileNotFoundException
字符串转换为数字异常:NumberFormatException
操作数据库异常:SQLException
输入输出异常:IOException
方法未找到异常:NoSuchMethodException
Q:什么时候会出现OutOfMemoryError、*Error?
内存溢出OutOfMemoryError,当内存不够用时,会抛出OutOfMemoryError。需要优化代码,或者调整jvm参数,通过-Xmx将最大内存数调大。
栈溢出*Error,当大量嵌套递归时,可能会出现*Error,递归从本质上讲也是栈的使用。

Jdk

Q:Jdk各个版本有哪些差别?
Q:Jdk1.8以后的特性,有没有了解过?
Jdk1.5:foreach迭代,可变参数,枚举,自动拆装箱,泛型,注解;
Jdk1.6:轻量级HttpServer的API,使用Complier API,对脚本语言的支持;
Jdk1.7:Switch支持字符串,泛型类型自动推断,try-with-resource资源关闭技巧(省去了自己在finally里去关闭资源),Objects工具类,ForkJoinPool
Jdk1.8:接口的默认方法实现与静态方法,Lambda表达式,函数式接口,方法与构造函数引用,新的日期与时间API,流式处理。
Jdk1.9:优化了HTTP Client,支持HTTP/2和HTTPS/TLS协议。
Jigsaw模块化项目,简化进程API,轻量级JSON API,钱和货币的API,进程改善和锁机制优化,代码分段缓存。
Jdk10:局部变量的类型推断var,改进GC和内存管理,线程本地握手,备用内存设备上的堆分配
Jdk11:可拓展的低延迟垃圾收集器ZGC。
Q:Java8的Lambda表达式,你会用吗?可以做哪些事情?能否手写一下?
匿名函数式。可以进行筛选,排序,求值,查找等功能。
Q:看过哪些Jdk源码?
集合,多线程,并发。

集合(重点)

关键词:ArrayList、LinkedList、HashTable、HashMap、ConcurrentHashMap、HashSet、
Q:List和Set有什么区别?
List有序可重复,Set无序不重复

ArrayList

Q:ArrayList和LinkedList有什么区别?(常问)
ArrayList数据结构是数组,查询比较快。LinkedList是一个双向链表,增删比较快。
Q:ArrayList什么时候扩容?如何扩容?扩容多少?
ArrayList在初始化的时候,是不会扩容的。比如List list=new ArrayList(20); 执行这句代码时不会进行扩容。
ArrayList数组的初始长度是10,当数组填满后会进行扩容,每次扩容0.5倍,也就是原来的1.5倍。
扩容的过程,由于数组的长度是不可变的,只能新建一个数组。
扩容的过程就是数组拷贝 Arrays.copyOf的过程,每一次扩容就会开辟一块新的内存空间和数据的复制移动。

HashSet

Q:讲一下HashSet
无序不重复,允许为null。
Q:HashSet是怎么实现的?
基于HashMap来实现的,底层采用HashMap来保存元素。
Q:HashSet源码是怎么实现不重复的?
HashMap的key是不能重复的,而这里HashSet的元素又是作为了map的key,当然也不能重复了。
HashMap的key怎么保证是不能重复的?
HashMap调用了对象的hashCode和equals方法进行的判断。

HashTable

Q:HashTable是怎么实现的?数据结构是什么?
哈希表(hash table, 也叫散列表),是种根据关键码值(Key value)而直接进行访问数据结构,它可以提供快速的插入操作和查找操作。也就是说,它通过把关键字值映射到一个位置来访问记录,以加快查找的速度。这个映射函数称为哈希函数。
Hashtable是通过"拉链法"实现的哈希表。由一个数组实现,数组元素都是单向链表。

HashMap(重点)

Q:HashMap有哪些遍历方式?
Map.Entry,EntrySet,Iterator(迭代器)
Q:HashMap和Hashtable的区别有哪些?
HashMap没有考虑同步,是线程不安全的;Hashtable使用了synchronized关键字,是线程安全的;
前者允许null作为Key;后者不允许null作为Key
HashTable继承了Dictionary类。而HashMap是基于AbstractMap
Q:HashMap的数据结构是什么?
HashMap数据结构是一个长度为16的数组,数组元素是链表,在jdk1.8中,当链表长度达到8时,会转换为红黑树。
注:红黑树是一种二叉查找树,每个节点都标记红色或黑色,根节点为黑色,规律是“有红必有黑,红红不相连”
Q:HashMap什么时候扩容?扩容多少?
HashMap中有一个负载因子loadFactor,0.75。当数组的长度达到数组长度(16)*负载因子(0.75)也就是12时,会进行扩容。
HashMap扩容时长度会翻倍。
Q:HashMap扩容后,是怎么查找数据的?数据的位置会变吗?Hash算法需要变吗??
扩容后需要重新计算数据的位置。
Q:HashMap中的Hash算法具体是怎样的?
Hash算法本质上就是三步:取key的hashCode值、高位运算 、取模运算。
通过Hash算法,对key计算出数组下标,把数据放在对应下标元素的链表上。
Hash碰撞:通过Key进行Hash的计算,就可以获取Key对应的HashCode。如果出现了重复的hashCode,就称作碰撞。
如果发生了碰撞事件,那么意味这数组的一个位置要插入两个或者多个元素,这个时候数组上面挂的链表起作用了,链表会将数组某个节点上多出的元素按照尾插法(jdk1.7及以前为头差法)的方式添加。

Q:HashMap 的长度为什么是2的幂次方?
在Hash算法中,需要进行以下操作:

  1. 通过将 Key 的 hash 值与 length - 1 进行 & 运算,实现了当前 Key 的定位,2 的幂次方可以减少冲突(碰撞)的次数,提高 HashMap 查询效率
  2. 如果 length 为 2 的次幂 则 length-1 转化为二进制必定是 11111……的形式,在与 h 的二进制与操作效率会非常的快,而且空间不浪费;如果 length 不是 2 的次幂,比如 length 为 15,则 length - 1 为 14,对应的二进制为 1110,在于 h 与操作,最后一位都为 0 ,而 0001,0011,0101,1001,1011,0111,1101 这几个位置永远都不能存放元素了,空间浪费相当大,更糟的是这种情况中,数组可以使用的位置比数组长度小了很多,这意味着进一步增加了碰撞的几率,减慢了查询的效率!这样就会造成空间的浪费。

ConcurrentHashMap(重点)

Q:可以在遍历ArrayList或者HashMap时,一边增删集合吗?
不可以。集合的fail-fast原则。
在遍历ArrayList或者HashMap时,一边增删集合会抛出ModifyCountException。
Q:HashMap和ConcurrentHashMap的区别是什么?
HashMap是线程不安全的。ConcurrentHashMap线程安全。
HashMap的Key和Value可以是null。而ConcurrentHashMap不可以。
Q:ConcurrentHashMap是如何实现的?
在jdk1.8之前,ConcurrentHashMap使用锁分段技术的。
在jdk1.8,ConcurrentHashMap主要使用了CAS(compareAndSwap)、volatile(保证可见性)、synchronized锁。
Q:ConcurrentHashMap是怎么保证线程安全的?
CAS,比较和替换,运用了乐观锁的机制。
Q: ArrayList是线程不安全的,如果要求线程安全,应该用什么集合代替ArrayList?
CopyOnWriteArrayList。写时拷背。

集合排序

集合排序,偏向算法,问的人比较少。
Q:Collections.sort()怎么排序?默认的排序是什么?
必须实现Comparable接口的compare方法。
默认的排序方法是Timsort。结合了合并排序和插入排序而得出的排序算法。
Q:Arrays.sort();默认的排序算法是什么?
数组有序就会采用归并排序,数组无序就会采用快速排序。
详情见:https://blog.csdn.net/timheath/article/details/68930482

参考资料:
《码出高效 java开发手册》
https://www.cnblogs.com/wmyskxz/p/9016611.html