序
疫情过后,本来想着经济要迎来一波大力发展,企业老板们都应该要挣钱了,我们苦命的程序员也能多少喝点汤的。哪知,老板们不中用啊(开个玩笑),好多公司垮掉了,这就导致了很多程序员兄弟姐妹们现在没工作,然后没工作的兄弟姐妹们就要开始卷有工作的。完犊子了,Java越来越难,能力不强的被逼开始转行或者开始重新捡起书本学习;作者就是那个能力不强的,作为一个80后大龄程序员,本该躺平享受生活的,现在落到没收入下场,怪就怪,老板不争气。这就是作者为什么要写这系列文章的初衷。一个字——为了生活,学!
写这本面试书,实际上也是作者自己在学习的过程中做的总结,通过手写,也能加深自己的印象,同时作者也是希望能用最直白、幽默的语言来解释清除枯燥晦涩的专业术语帮助需要面试的同学能更好的记住面试题。全书几乎每道题的结构都分为白话解析和参考答案两个模块:白话解析旨在通过白话来帮助大家理解本题,而参考答案旨在总结回答话术。如果想短时间通过本书去面试,可以只背参考答案的内容就好了。如果时间比较充裕,建议去理解白话解析中的内容。
本文总共分为4篇,分别为入门篇、初级篇、中级篇和高级篇。
1、入门篇:适合刚学过Java但是没有企业级工作经验的同学,像大三的学妹马上要找实习工作了,或者大四帅小伙要进行校招了,那这篇内容你们必须掌握个80%以上。当然对于那些工作5年以上的老腊肉们(高级开发),你们以后面试基本上不会被问到这些面试题了,但是你们至少也要掌握个70%以上才说的过去吧。该篇包括:
-
第1章 Java基础
-
第2章 Java集合
-
第3章 并发编程
-
第4章 文件IO
-
第5章 网络编程
-
第6章 反射机制
2、初级篇:适合工作1年或以上的同学,这一篇内容主要是针对企业级开发中牵涉到的技术。需掌握70%以上。该篇包括:
-
第7章 SpringMVC
-
第8章 Spring
-
第9章 Mybatis
-
第10章 MySQL
-
第11章 Redis
3、中级篇:适合工作3—5年左右的同学,如果你都写了5年代码了,这一篇的内容你还基本没玩过,那你完犊子了,以后到了作者这个年龄就躺不平了(不说百分百,但是很大一部分)。该篇包括:
-
第12章 设计模式
-
第13章 并发编程高阶
-
第14章 JVM
-
第15章 SpringBoot
-
第16章 Zookeeper
-
第17章 MQ
4、高级篇:适合工作5年以上的大佬们,这一篇内容如果都懂,都会,随便面个高级开发或者技术经理甚至架构师,问题不算太大。该篇包括:
-
第18章 SpringCloud生态
-
第19章 Dubbo
-
第20章 Netty
以上说的只是正常情况下不同的年限学不同的内容。当然如果你刚毕业,就能掌握高级篇的内容,那我只能说,天才,带带我,我很好带的。
1.1 什么是变量?什么是常量?Java中定义常量的方式
难度:★
重点:★
白话解析
在使用Java语言进行编程的时候,实际上我个人的理解就是对数据进行一些逻辑上的操作,而数据在计算机里面最基本的表现形式无非就是常量和变量,所以我们先搞明白常量和变量的概念。
1、变量:就相当于我们中学时期学的x未知数,它是可以变的。
2、常量:顾名思义就是一旦给了值之后就不能变了,比如我们的数字、字符、字符串等都属于常量。
3、定义方式:在Java中方式,一种叫普通字面量(字面意义能看出来的,比如刚才说的数字,字符等);一种是通过final关键字修饰之后的变量,例如:
final int x = 10;
在这段代码里面,x原本是变量,但是被final修饰了之后它就不能变了,此时它也就是常量了。
注意:上面final是修饰int型的x,同时给x赋的值是字面量10,所以两边都是常量,不会变了。当final修饰的是一个引用的话,例如:
final Object obj = new Object();
//像这种情况的话,obj存的是对象在内存中的地址,因为被final修饰了,所以obj存的内存地址是不能变的,但是对象里面的属性依然可以变。
参考答案
1、变量:可以变的。
2、常量:跟变量相对,一旦写好之后它不能变了。
3、常量的定义方式:
-
普通的字面量
-
通过final修饰的
1.2 Java基本数据类型有哪几种
难度:★
重点:★★★
白话解析
搞明白常量变量的概念之后,接下来我们看到数据在Java里面一般使用方式是讲一个常量的赋值给变量,但是刚刚也说道了常量有数字,有字符串等等,那不同类型的数据要赋值给变量,变量也需要区分类型,接下来我们捋捋Java中的基本数据类型,这道题不需要背,稍微理解就好。然后每个数据类型最大的长度不用去记,知道字节数就好了。
参考答案
在Java中,基本数据类型有8个,分为三大类分别是:
1、数值型
-
byte(整数):1字节,默认0
-
short(整数):2字节,默认0
-
int(整数):4字节,默认0
-
float(浮点数):4字节,默认0.0f
-
long(整数):8字节,默认0
-
double(浮点数):8字节,默认0.0d
2、字符型
-
char,2字节,默认null;String它不是基本的,它是一个类。
3、布尔型
-
boolean,1字节;只有true和false两个值,默认false
1.3 char型变量能赋值汉字吗
难度:★★
重点:★★
白话解析
说白了,这个题目就是考你对字符集编码熟不熟悉了,对于字符集,用简单的话来解释就是,全世界有各种语言,但是计算机只认识二进制,所以要想计算机认识就需要人为制定一种语言文字跟计算机的二进制一一对应的关系,而不同语言在计算机里面的对应关系又不相同。此时又需要一种统一的语言作为全球通用语言,比如现在的汉语就是全球语言,那一样的,计算机也需要一种全球通用的字符集,就是Unicode。这哥们包含了全球绝大部分语言的编码,当然也包含了汉字。说了这么多,回到正题,char就是存Unicode编码的。所以你觉得能不能存汉字呢?
编码的意思就是将二进制转文字,和将文字转二进制的一套规范,就理解成这哥们就是加密解密的。
参考答案
一个字:能,然后在面试中将上面那段话掰扯掰扯一些。
1.4 int和Integer的关系
难度:★★
重点:★★★
白话解析
在Java中除了8种基本数据类型以外,Java还给我们提供了8种基本数据类型的包装类,例如Integer、Long等,说白了,就是Java的设计大佬们觉得基本的数据类型功能不够强大,数据类型只不过是"类型",没有给使用者提供任何其他的方法,比如数字转字符串,字符串转数字等方法。所以大佬们看不下去了,把基本数据类型包装了一下,设计成了一个类,在类里面可以定义很多常用的方法而已。
参考答案
1、联系:
包装类就是对基本数据类型的封装,在基本数据类型的基础上提供各种常用方法。
2、区别:
-
int是类型;Integer是类,里面有方法的。
-
int a=1000;这是把真实的1000这个值给到了a。Integer a = 1000;这是把1000所处的内存地址给到了a。
-
默认值不同,int是0,Integer是null(对象的引用如果没赋值,默认都是null)
1.5 Integer a=100;Integer b=100,a==b返回true吗
难度:★★★
重点:★★★★
白话解析
这算是前几年对初中级程序员考察的一道比较高频的题,考察的点就在于你有没有对Integer底层的源码了解过。
实际上在-128—127之间,a和b是相等的,但是超出这个范围就不相等了,接下来捋具体原因:
当我们执行Integer a=100的时候,默认会调用Integer.valueOf()把数字100包装成一个对象。而在Integer内部维护了一个IntegerCache哥们,它缓存了 -128—127这个区间的数值对应的Integer类型对象。
说白了就是在赋值的时候不是简单的把100给到a,而是Java底层偷偷摸摸给你创建了一个Integer类型的对象,然后这个对象里面的值是等于100的。而且在Integer类里面已经帮我们把 -128—127的所有对象都创建好而且缓存起来了,那不管是给a赋值100也好还是给b赋值100,都是从缓存里面拿同一个对象,既然对象相同,那对象的内存地址也想同,上面讲过Integer的赋值是把对象的内存赋值给a或者b,那这个时候a==b就是true了。如果不在 -128—127之间的话,那每次赋值都会创建新对象,这个时候内存地址就不同了,返回的也是false。
参考答案
当a和b的值在 -128—127之间的时候,a==b返回的是true;如果不在这个范围内,即使他们等于同一个数,返回的也是false。
1.6 如何理解自动拆箱和装箱
难度:★★★
重点:★★
白话解析
啥拆箱装箱啊,就喜欢整专业名词,说白了就是把类当做一个黑箱子,当转成基本数据类型的时候就是拆。当基本数据类型转成包装类的时候就是装。而自动就是手动的反义词,手动就是让程序员自己去转,自动肯定就是Java底层帮我们做了。
1、自动拆箱:
-
就是将包装类型(如Integer、Double等)转换为对应的基本数据类型(如int、double等)的过程。
-
在Java 1.4及以前的版本中(不用记哪个版本),我们必须手动调用包装类型的intValue()、doubleValue()等方法才能将其转换为基本数据类型,如下:
Integer i = new Integer(10); // 先创建Integer对象 int j = i.intValue(); // 然后调用intValue()方法将i转换为int
-
而在Java 1.5及以后的版本中,我们可以直接将包装类型赋值给基本数据类型变量,上面的步骤不由我们程序员手动去做了,Java编译期帮我们做了,如下:
Integer i = new Integer(10); int j = i; // 自动拆箱,将i转换为int类型
在上面的代码中,我们并没有调用intValue()方法的步骤,直接将Integer对象赋值给了int变量。此时,Java编译器会自动将Integer对象转换为int类型,这个过程叫做自动拆箱。
-
存在一个问题,当创建对象的时候,如果是null的话,自动拆箱会抛空指针异常
2、自动装箱:
跟拆箱相反,将基本数据类型自动转成包装类型。不需要手动通过new关键字去包装了
//手动装箱
int i = 1;
Integer j = new Integer(i); //手动调new关键字创建Integer对象,对i进行包装
//自动装箱
int i = 1;
Integer j = i; // 自动装箱:将int类型的i转换为对应的Integer类型
参考答案
1、自动拆箱:就是将Integer等转换为对应的基本数据类型int、double的过程。在Java1.5版本之后,这个过程由Java底层自动实现。所以叫自动拆箱。
2、自动装箱:跟自动拆箱刚好相反。
1.7 & 和&& 的区别
难度:★
重点:★★
白话解析
这道题完全不需要背,理解了就好了,&就是对每一位进行与运算,0代表false,1代表true。&&就是直接把两个值进行与运算。
1、&它是按位与,例如下面两个8位的二进制数,从右到左为第1位——第8位:
01011101
10110110
相同位都为1,&的结果为1,一旦相同位中有0,则&结果为0,所以上面的两个8位数去&的结果为:
00010100
2、&&是按逻辑与,就是我们高中学过的,全真则真,一假则假,例如:
(1 > 0) && (3 > 1) 结果为true
(1 < 0) && (3 > 1) 结果为false
参考答案
1、&是按位取与。
2、&&是按逻辑与。
1.8 continue、break和return三者之间的区别
难度:★★
重点:★★★
白话解析
这仨哥们功能总结起来就一句话continue是跳出当前循环,进入下一循环,它没有结束for;break是把当前的for整个结束了(但是你for外面还有一个for的话,它是不能结束外层for的),当前for的所有循环不往下走了;return是整个Java的方法都结束了;用一段代码你们就明白了。
public class Demo {
public static void main(String[] args) {
doSomething();
}
public static int doSomething(){
//第一层循环
for (int i = 0; i < 100; i++) {
//第二层循环
for (int j = 0; j < 100; j++) {
if(j%2 == 0){
//当遇到j等于偶数的时候不继续执行下面的代码,而是继续走第二层循环的下一次循环,
//说白了就是将j++,走下一个循环了
continue;
}
if(j == 9){
//break就是当前第二层循环全部结束不走了,但是第一层循环还要继续
break;
}
System.out.println(j);
}
if(i == 10){
//整个方法结束,返回到main方法
return i;
}
}
return 0;
}
}
参考答案
1、continue是跳出当前i=0的循环,继续下一次i=1的循环;
2、break是跳出当前整个for循环;
3、return是整个方法结束。
1.9 Java的特性是什么
难度:★
重点:★★★
白话解析
从Java的背景出发,它是在C的基础之上发展而来,那C是面向过程的,Java要有所改进,变成了面向对象,万物皆对象。
而对象是基于类创建的,类是干嘛的呢?它就相当于一个黑箱子,把属性啊方法啊全部包到一起,想访问我的属性就只能通过我的方法才行,例如用人作为一个类,而人这个类包了一些属性(姓名、年龄、性别等,不对外公开)和一些方法(获取姓名、年龄等属性的方法以及其他的方法,这个是对外公开的)。这就是封装的意思。
然后呢不同的类可能会存在一样的方法,那能不能单独提出来呢,这样能少写很多重复代码,然后让这些类继承单独提出来的那个类这就是继承的概念。比如老鹰会飞,麻雀也会飞,在创建类的时候,可以创建一个鸟类,把会飞的方法单独提出来放在鸟的类中,老鹰和麻雀这两个类就是鸟类的子类。这就是继承的概念。
那在继承的时候,如果不同的类对方法的实现不同可不可以做到呢?可以,重写方法就完事了,多态不就来了吗?多态多态,不就是方法的多种表现形态嘛。比如叫喊这种行为,猫是喵呜,狗是汪汪汪等。实现方式就是在接口或者父类里面定义一个方法,不同的类实现接口或父类的方法就好了。
参考答案
1、封装:这哥们说白了就是把一堆属性和一堆方法用一个类包一下,然后别人要访问这些属性的话,只能通过调你的方法。
2、继承:就是把一些公有的东西单独提出来建个类,
3、多态:就是一种行为,它的实现方式可以有多种形态。
4、面向对象:相信系统学过Java的都知道,Java有句名言叫万物皆对象,说的一点没毛病,在Java中,所有的操作都是基于对象实现的。(这句话很重要,真正到高级程序员的时候,接触的核心源码多了,你就会明白这句话的重要性。后面不管是使用什么技术,只要用Java集成了,都是先创建对象,再调方法;例如在使用Redis的时候,在Java代码中就要创建RedisTemplate对象,然后再调增删改查,其他的技术组件都差不多。)
1.10 访问修饰符有哪些,请说出他们的区别
难度:★
重点:★★
白话解析
public既然是公有的,都能访问;private既然是私有的,只有自己能访问;其他的不背也没事。
参考答案
作用域 | 当前类 | 同一包下 | 子孙类 | 不同包下 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
friendly | √ | √ | × | × |
private | √ | × | × | × |