写点什么

2021 最新最全 Java 基础高频面试题汇总(1W 字详细解析)

  • 2022 年 4 月 19 日
  • 本文字数:5872 字

    阅读完需:约 19 分钟

}


public void sayHello() {


System.out.println("Hello");


}


}


class Son extends Father{


@Override


public void sayHello() {


// TODO Auto-generated method stub


System.out.println("hello by ");


}


}复制代码


重写 总结:


《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 1)发生在父类与子类之间


(2)方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同


(3)访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)


(4)重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常


重载(Overload)


在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)


则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来


判断重载。


public static void main(String[] args) {


// TODO Auto-generated method stub


Father s = new Father();


s.sayHello();


s.sayHello("wintershii");


}


public void sayHello() {


System.out.println("Hello");


}


public void sayHello(String name) {


System.out.println("Hello" + " " + name);


}


}复制代码


重载 总结:


(1)重载 Overload 是一个类中多态性的一种表现


(2)重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)


(3) Java 开源项目【ali1024.coding.net/public/P7/Java/git】 重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准


8、 equals 与==的区别




== :


== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。


(1)比较的是操作符两端的操作数是否是同一个对象。


(2)两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。


(3)比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为 true,如:


int a=10 与 long b=10L 与 double c=10.0 都是相同的(为 true),因为他们都指向地址为 10 的堆。


equals:


equals 用来比较的是两个对象的内容是否相等,由于所有的类都是继承自 java.lang.Object 类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是 Object 类中的方法,而 Object 中的 equals 方法返回的却是==的判断。


总结:


所有比较是否相等时,都是用 equals 并且在对常量相比较时,把常量写在前面,因为使用 object 的 equals object 可能为 null 则空指针在阿里的代码规范中只使用 equals ,阿里插件默认会识别,并可以快速修改,推荐安装阿里插件来排查老代码使用“==”,替换成 equals


9、 Hashcode 的作用




java 的集合有两类,一类是 List,还有一类是 Set。前者有序可重复,后者无序不重复。当我们在 set 中插入的时候怎么判断是否已经存在该元素呢,可以通过 equals 方法。但是如果元素太多,用这样的方法就会比较满。


于是有人发明了哈希算法来提高集合中查找元素的效率。 这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储的那个区域。


hashCode 方法可以这样理解:它返回的就是根据对象的内存地址换算出的一个值。这样一来,当集合要添加新的元素时,先调用这个元素的 hashCode 方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的 equals 方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。这样一来实际调用 equals 方法的次数就大大降低了,几乎只需要一两次。


10、String、String StringBu?er 和 StringBuilder 的区别是什么?




String 是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个?nal 类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对 String 的操作都会生成新的 String 对象。


private final char value[];复制代码


每次+操作 : 隐式在堆上 new 了一个跟原字符串相同的 StringBuilder 对象,再调用 append 方法 拼接+后面的字符。


StringBu?er 和 StringBuilder 他们两都继承了 AbstractStringBuilder 抽象类,从 AbstractStringBuilder 抽象类中我们可以看到


/**


  • The value is used for character storage.


*/


char[] value;复制代码


他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用 StringBu?er 和 StringBuilder 来进行操作。 另外 StringBu?er 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。


11、ArrayList 和 linkedList 的区别




Array(数组)是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。


Array 获取数据的时间复杂度是 O(1),但是要删除数据却是开销很大,因为这需要重排数组中的所有数据,(因为删除数据以后, 需要把后面所有的数据前移)


缺点: 数组初始化必须指定初始化的长度, 否则报错


例如:


int[] a = new int[4];


//推介使用 int[] 这种方式初始化


int c[] = {23,43,56,78};


//长度:4,索引范围:[0,3]复制代码


List—是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式,它继承 Collection。


List 有两个重要的实现类:ArrayList 和 LinkedList


ArrayList: 可以看作是能够自动增长容量的数组


ArrayList 的 toArray 方法返回一个数组


ArrayList 的 asList 方法返回一个列表


ArrayList 底层的实现是 Array, 数组扩容实现


LinkList 是一个双链表,在添加和删除元素时具有比 ArrayList 更好的性能.但在 get 与 set 方面弱于


ArrayList.当然,这些对比都是指数据量很大或者操作很频繁。


12、 HashMap 和 HashTable 的区别




(1)两者父类不同


HashMap 是继承自 AbstractMap 类,而 Hashtable 是继承自 Dictionary 类。不过它们都实现了同时实现了 map、Cloneable(可复制)、Serializable(可序列化)这三个接口。


(2)对外提供的接口不同


Hashtable 比 HashMap 多提供了 elments() 和 contains() 两个方法。


elments() 方法继承自 Hashtable 的父类 Dictionnary。elements() 方法用于返回此 Hashtable 中的 value 的枚举。


contains()方法判断该 Hashtable 是否包含传入的 value。它的作用与 containsValue()一致。事实上,contansValue() 就只是调用了一下 contains() 方法。


(3)对 null 的支持不同


Hashtable:key 和 value 都不能为 null。


HashMap:key 可以为 null,但是这样的 key 只能有一个,因为必须保证 key 的唯一性;可以有多个 key 值对应的 value 为 null。


(4)安全性不同


HashMap 是线程不安全的,在多线程并发的环境下,可能会产生死锁等问题,因此需要开发人员自己处理多线程的安全问题。


Hashtable 是线程安全的,它的每个方法上都有 synchronized 关键字,因此可直接用于多线程中。虽然 HashMap 是线程不安全的,但是它的效率远远高于 Hashtable,这样设计是合理的,因为大部分的使用场景都是单线程。当需要多线程操作的时候可以使用线程安全的 ConcurrentHashMap。


ConcurrentHashMap 虽然也是线程安全的,但是它的效率比 Hashtable 要高好多倍。因为


ConcurrentHashMap 使用了分段锁,并不对整个数据进行锁定。


(5)计算 hash 值的方法不同


13、 Collection 包结构,与 Collections 的区别




Collection 是集合类的上级接口,子接口有 Set、List、LinkedList、ArrayList、Vector、Stack、Set;Collections 是集合类的一个帮助类, 它包含有各种有关集合操作的静态多态方法,用于实现对各种集合的搜索、排序、线程安全化等操作。此类不能实例化,就像一个工具类,服务于 Java 的 Collection 框架。


14、 Java 的四种引用,强弱软虚




强引用


强引用是平常中使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式:


String str = new String("str");复制代码


软引用


软引用在程序内存不足时,会被回收,使用方式:


// 注意:wrf 这个引用也是强引用,它是指向 SoftReference 这个对象的,


// 这里的软引用指的是指向 new String("str")的引用,也就是 SoftReference 类中 T


SoftReference<String> wrf = new SoftReference<String>(new String("str"));复制代码


可用场景: 创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM 就会回收早先创建的对象。


弱引用


弱引用就是只要 JVM 垃圾回收器发现了它,就会将之回收,使用方式:


WeakReference<String> wrf = new WeakReference<String>(str);复制代码


可用场景: Java 源码中的 java.util.WeakHashMap 中的 key 就是使用弱引用,我的理解就是,一旦我不需要某个引用,JVM 会自动帮我处理它,这样我就不需要做其它操作。


虚引用


虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入 ReferenceQueue 中。注意哦,其它引用是被 JVM 回收后才被传入 ReferenceQueue 中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有 ReferenceQueue,使用


例子:


PhantomReference<String> prf = new PhantomReference<String>(new


String("str"), new ReferenceQueue<>());复制代码


可用场景: 对象销毁前的一些操作,比如说资源释放等。** Object.finalize()虽然也可以做这类动作,但是这个方式即不安全又低效


15、 泛型常用特点 (待补充)




泛型是 Java SE 1.5 之后的特性, 《Java 核心技术》中对泛型的定义是:


“泛型” 意味着编写的代码可以被不同类型的对象所重用。


“泛型”,顾名思义,“泛指的类型”。我们提供了泛指的概念,但具体执行的时候却可以有具体的规则来约束,比如我们用的非常多的 ArrayList 就是个泛型类,ArrayList 作为集合可以存放各种元素,如 Integer, String,自定义的各种类型等,但在我们使用的时候通过具体的规则来约束,如我们可以约束集合中只存放 Integer 类型的元素,如


List<Integer> iniData = new ArrayList<>()复制代码


使用泛型的好处?


以集合来举例,使用泛型的好处是我们不必因为添加元素类型的不同而定义不同类型的集合,如整型集合类,浮点型集合类,字符串集合类,我们可以定义一个集合来存放整型、浮点型,字符串型数据,而这并不是最重要的,因为我们只要把底层存储设置了 Object 即可,添加的数据全部都可向上转型为 Object。 更重要的是我们可以通过规则按照自己的想法控制存储的数据类型。


16、Java 创建对象有几种方式?




java 中提供了以下四种创建对象的方式:


(1)new 创建新对象


(2)通过反射机制


(3)采用 clone 机制


(4)通过序列化机制


17、有没有可能两个不相等的对象有相同的 hashcode




有可能.在产生 hash 冲突时,两个不相等的对象就会有相同的 hashcode 值.当 hash 冲突产生时,一般有以下几种方式来处理:


(1)拉链法:每个哈希表节点都有一个 next 指针,多个哈希表节点可以用 next 指针构成一个单向链表,被分配到同一个索引上的多个节点可以用这个单向链表进行存储.


(2)开放定址法:一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入


(3)再哈希:又叫双哈希法,有多个不同的 Hash 函数.当发生冲突时,使用第二个,第三个….等哈希函数计算地址,直到无冲突.


18、深拷贝和浅拷贝的区别是什么?




浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.


深拷贝:被复制对象的所有变量都含有与原来的对象相同的值.而那些引用其他对象的变量将指向被复制过的新对象.而不再是原有的那些被引用的对象.换言之.深拷贝把要复制的对象所引用的对象都


19、?nal 有哪些用法?


?nal 也是很多面试喜欢问的地方,但我觉得这个问题很无聊,通常能回答下以下 5 点就不错了:


(1)被?nal 修饰的类不可以被继承


(2)被?nal 修饰的方法不可以被重写


(3)被?nal 修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.


(4)被?nal 修饰的方法,JVM 会尝试将其内联,以提高运行效率


(5)被?nal 修饰的常量,在编译阶段会存入常量池中.


除此之外,编译器对?nal 域要遵守的两个重排序规则更好:


在构造函数内对一个?nal 域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序


初次读一个包含?nal 域的对象的引用,与随后初次读这个?nal 域,这两个操作之间不能重排序.


20、static 都有哪些用法?




所有的人都知道 static 关键字这两个基本的用法:静态变量和静态方法.也就是被 static 所修饰的变量/方法都属于类的静态资源,类实例所共享.


除了静态变量和静态方法之外,static 也用于静态块,多用于初始化操作:


public calss PreCache{


static{


//执行相关操作


}


}复制代码


此外 static 也多用于修饰内部类,此时称之为静态内部类.


最后一种用法就是静态导包,即 import static.import static 是在 JDK 1.5 之后引入的新特性,可以用来指定导入某个类中的静态资源,并且不需要使用类名,可以直接使用资源名,比如:


import static java.lang.Math.*;


public class Test{


public static void main(String[] args){


//System.out.println(Math.sin(20));传统做法


System.out.println(sin(20));


}


}复制代码


21、3*0.1 0.3 返回值是什么




false,因为有些浮点数不能完全精确的表示出来.


22、a=a+b 与 a+=b 有什么区别吗?




操作符会进行隐式自动类型转换,此处 a+=b 隐式的将加操作的结果类型强制转换为持有结果的类型,


byte a = 127;


byte b = 127;


b = a + b;


// 报编译错误:cannot convert from int to byte


b += a;复制代码


以下代码是否有错,有的话怎么改?


short s1= 1;


s1 = s1 + 1;复制代码


有错误.short 类型在进行运算时会自动提升为 int 类型,也就是说 s1+1 的运算结果是 int 类型,而 s1 是 short 类型,此时编译器会报错.


正确写法:


short s1= 1;


s1 += 1;复制代码


+=操作符会对右边的表达式结果强转匹配左边的数据类型,所以没错.


23、try catch ?nally,try 里有 return,?nally 还执行么?




执行,并且?nally 的执行早于 try 里面的 return


结论:

分享

首先分享一份学习大纲,内容较多,涵盖了互联网行业所有的流行以及核心技术,以截图形式分享:


(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+设计思想开源框架解读+性能直线提升架构技术+高效存储让项目性能起飞+分布式扩展到微服务架构.........实在是太多了)


其次分享一些技术知识,以截图形式分享一部分:


Tomcat 架构解析:



算法训练+高分宝典:



Spring Cloud+Docker 微服务实战:



最后分享一波面试资料:


切莫死记硬背,小心面试官直接让你出门右拐


1000 道互联网 Java 面试题:



Java 高级架构面试知识整理:



用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
2021最新最全Java基础高频面试题汇总(1W字详细解析)_Java_爱好编程进阶_InfoQ写作平台