❤三万字带你了解那些年面过的Java八股文建议收藏
Posted 白大锅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❤三万字带你了解那些年面过的Java八股文建议收藏相关的知识,希望对你有一定的参考价值。
目录
- 💖前言
- 🎄Java基础知识
- 💟基础知识导图
- 🎄IO流
- 🎈Lambda
- 🎃&和&&的区别?
- 🎋在java中如何跳出当前的多重循环?
- 🎨面向对象的三大特征
- 🎍"=="和equals方法究竟有什么区别?
- 🎎三个与取整有关的方法
- 🎏Java中运算符
- ✨重载和重写的区别?
- 🎢String和StringBuffuer、StringBuilder的区别?
- 🎨java中有几种方法实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用?
- 🎗sleep()和wait()有什么区别?
- 🎃基本语句(for、if else、switch、while、break和continue)
- 🎉关键字
- 🥫作用域public、private、protected 以及不写时的区别?
- 🥚forward和redirect两种跳转方式的区别?
- 🍧HashMap和Hashtable的区别?
- 🍨List、Set和Map的区别?
- 🍷hashCode与equals的区别与联系?
- 🧉模式
- 🥯Java常用类
- 🎄Java集合框架
- 🎄Java多线程
- 🎄Java虚拟机
- 🎄MySQL
- 🎄Spring相关知识点
- 🎄计算机网络
- 🎄MQ消息队列
- 🎄Redis
- 🎄Nginx
💖前言
国内的互联网面试,恐怕是现存的、最接近科举考试的制度。而且,我国的八股文(基础知识、集合框架、多线程、线程的五种状态、虚拟机、MySQL、Spring相关、计算机网络、MQ系列等)确实是独树一帜。以美国为例,北美工程师面试比较重视算法(Coding),近几年也会加入Design轮(系统设计和面向对象设计OOD)和BQ轮(Behavioral question,行为面试问题),今天博主为大家熬断半头青丝捋一捋这现代八股文
🎄Java基础知识
💟基础知识导图
需要完整图的小伙伴可联系博主
🎄IO流
详情见博主此文:IO流知识体系详解
按照流的方向:输入流(inputStream)和输出流(outputStream).
按照实现功能分:节点流(可以从或向一个特定的地方(节点)读写数据。如 FileReader)和处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如 BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接)
按照处理数据的单位: 字节流和字符流。字节流继承于 InputStream 和 OutputStream,字符流继承于InputStreamReader 和 OutputStreamWriter。
字节流如何转为字符流
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象
如何将一个 java 对象序列化到文件里
在 java 中能够被序列化的类必须先实现 Serializable 接口,该接口没有任何抽象方法只是起到一个标记作用
🎈Lambda
详情见博主此文:Lambda表达式详细讲解
🎃&和&&的区别?
&
:逻辑与(and
),运算符两边的表达式均为true
时,整个结果才为true
&&
:短路与,如果第一个表达式为false
时,第二个表达式就不会计算了
🎋在java中如何跳出当前的多重循环?
在循环语句外前面定义一个标号,然后在里层循环体的代码中使用带有标号的break语句,即可跳出循环。
比如:
ok:
for (int j = 0; j < 10; j++)
break ok;
🎨面向对象的三大特征
1.封装
作用:提高代码的安全性
1、将属性私有化,并提供对外界的接口(get/set
方法)。
2、用private
修饰的属性和方法,只能在本类中使用。
2.继承
作用:提高代码的复用性,减少重复代码
1、子类可以继承父类非私有的属性和方法,不能继承构造方法和私有的属性和方法。
2、可以综合子类的共同特征来去提炼父亲的类。
3、子类在继承父类的各种属性和方法时,也可以有自己的属性和方法。
4、一个子类只能有一个父类,java只能单继承,不能多继承,因为多个类中的方法名相同,方法体不同,不知使用哪个。
5、一个类继承最顶端叫做基类或者超类,所有的超类叫做object
。
6、在继承关系中,如果父类没有无参数的构造方法,如何解决?
1.子类中添加一个和父类构造方法参数列表相同的构造方法,通过super参数传递给父类的构造方法
2.如果父类允许修改的时候,可以在父类中创建一个无参的构造方法
7、在继承关系中,代码块的执行顺序:父静>子静>父构造代码块>父构造方法>子构造代码块>子构造方法
3.多态
1.分类
编译时多态:在编译过程中察觉的多态,重载,向上转型。
运行时多态:在运行过程中察觉的多态,向下转型。
2.向上转型、向下转型是在继承关系中,向下转型必须在向上转型的基之上。
3.在继承关系中,父类的对象可以指向子类的实例,父类引用实体方法的时候,是调用子类重写以后的方法。
4.向上转型
父类的引用指向子类的实体
父类类名对象名=new 子类类();
优点:减少重复代码,提高代码的复用性
缺点:父类的引用无法调用子类特有的属性和方法
解决方案:向下转型
5.向下转型:
子类对象的父类引用赋给子类
子类类名对象名=(子类类名)父类对象;
6. instanceof 判断左边的对象是否属于右边的类 对象名instanceof
类名(子类类名)
7.匿名对象
new
类名()只有堆空间,没有栈空间,只能属于一次,为了节省代码。
🎍"=="和equals方法究竟有什么区别?
==:表示两个变量的值是否相等,比较两个基本数据类型的数据或者引用变量,用 ==
equals:用于比较两个独立对象的内容是否相同,字符串的比较也用equals
🎎三个与取整有关的方法
Math.ceil():表示向上取整;Math.ceil(11.3)=12;Math.ceil(-11.3)=-12。
Math.floor():表示向下取整;Math.floor(11.6)=11;Math.floor(-11.6)=-12。
Math.round():表示四舍五入;Math.round(11.5)=12;Math.round(-11.5)=-11;
Math.round(11.3)=11;Math.round(-11.3)=-11;
🎏Java中运算符
算术运算符:+ 、 - 、 * 、 / 、 % 、 ++ 、 --
赋值运算符:= 、 += 、 -= 、 *= 、 /= 、 %=
关系运算符:> 、 < 、 >= 、 <= 、 == 、 !=
逻辑运算符:! 、 & (只要有一个false 最终结果就是false) 、
| (但凡有一个true 最终结果就是true) 、
^ (如果两边一样 最终结果为false 如果两边不同 最终结果为true)、
&&(如果第一个是false 那第二个不执行 最终结果是false)、
||(如果第一个表达式的结果是true 那第二个表达式 就不去计算了 ,最终结果是true)
位运算符: ~ 、 >> 、 << 、 >>>
字符串连接运算符:+
三目运算符:X ? Y : Z
X为boolean类型表达式,先计算x的值,若为true,整个三目运算的结果为表达式Y的值,否则整个运算结果为表达式Z的值。
✨重载和重写的区别?
重载(
Overload
):函数名相同,参数不同。可以改变返回值类型,参数的个数和类型。
重写(Override
):和父类的的方法名称、参数完全相同
🎢String和StringBuffuer、StringBuilder的区别?
String
:字符串数值不可变;
StringBuffer
:字符串可修改,可以动态构造字符数据。StringBuffer
类是可以通过Append()
来修改值。线程安全。
StringBuilder
:线程不安全。
三者在执行速度方面的比较:StringBuilder > StringBuffer > String
对于三者使用的总结:
1.如果要操作少量的数据用 =String
2.单线程操作字符串缓冲区下操作大量数据 =StringBuilder
3.多线程操作字符串缓冲区下操作大量数据 =StringBuffer
🎨java中有几种方法实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用?
第一种:继承Thread类。New Thread().start():表示调用子类对象的run方法
第二种:实现Runable接口
第三种:线程池创建多线程
第四种:实现Callable接口,重写call函数
继承Thread类实现多线程,重写run方法时没有返回值也不能抛出异常,使用Callable接口就可以解决这个问题
Callable接口和Runnable接口的不同之处:
1.Callable
规定的方法是call,而Runnable
是run
2.call
方法可以抛出异常,但是run
方法不行
3.Callable
对象执行后可以有返回值,运行Callable
任务可以得到一个Future
对象,通过Future
对象可以了解任务执行情况,可以取消任务的执行,而Runnable
不可有返回值
用synchronized
关键字修饰同步方法。
反对使用stop()
,是因为它不安全。
suspend()
方法容易发生死锁。调用suspend()
的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被" 挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend()
,而应在自己的Thread
类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()
命其进入等待状态。若标志指出线程应当恢复,则用一个notify()
重新启动线程。
🎗sleep()和wait()有什么区别?
sleep
是线程被调用时,占着cpu
休眠,其他线程不能占用cpu
,os
认为该线程正在工作,不会让出系统资源,wait
是进入等待池等待,让出系统资源,其他线程可以占用cpu
sleep()
和wait()
方法的区别可从两个角度阐述:
1.cpu的抢占权;2.锁旗标是否释放
两者都会释放cpu的抢占权;
wait()
方法执行完即可释放锁旗标,进入线程的等待队列;
sleep()
执行完,不会释放,进入等待队列;
🎃基本语句(for、if else、switch、while、break和continue)
1.for循环语句
for ([循环变量初始值设定]; [循环条件判断]; [改变循环变量的值]){
循环体
}
注意:1、表达式2一般不可以省略,否则死循环
2、表达式3可以省略,但是在循环体中必须有语句修改变量,以使表达式2在某一时刻为false结束循环。
3、若同时省略表达式1,表表达式3,则相当于while(表达式2)语句
4、三个表达式均省略 即for(;;)语句,此时相当于while(true)语句
5、表达式1、表达式3可以是逗号表达式,以使循环变量值在修改时可以对其它变量赋值
2.if…else… 判断语句
1、if()
2、if()else
3、if()else if()
4、if()if()else()
5、if()执行语句 esle 执行语句 注意:执行语句只有一条语句的时候.可以将if esle 的大括号省略
注意:()内是boolean类型表达式,是语句块
比较字符串用equals,比较内容。比较数值用==,比较地址。
基本数据类型:变量名、变量值在栈中。
引用数据类型:变量名在栈中,变量值在常量池中。
3.while 循环语句
while( 条件表达式语句){
循环体语句;
//初始条件
do{
//循环体;
//迭代
}while( 循环条件判断);
注意:1、当第一次执行时,若表达式=false时,则while语句不执行,而do/while语句执行一次后面的语句
2、一定要切记在switch循环中,如果没有break跳出语句,每一个case都要执行一遍,在计算最终结果。
4.switch 语句
switch(表达式expr)
case const1:
statement1;
break;
… …
case constN:
statementN;
break;
[default:
statement_dafault;
break;]
注意:1、表达式必须是int、byte、char、short、enmu、String类型
2、constN必须是常量或者finall变量,不能是范围
3、所有的case语句的值不能相同,否则编译会报错
4、default可要可不要
5、break用来执行完一个分支后使程序跳出switch语句块,否则会一直会执行下去。
5.if和switch的区别是什么?
1、
if
可以判断范围,也可以判断一个值
switch
只能判断指定的值
2、若只判断指定的值,则使用switch
语句,效率快
if判断范围,对数据判断灵活,自身的格式也比较灵活
6.break和continue区别是什么?
break
跳出某个循环
continue
跳过某个循环
注意:if外有循环可以用break
、continue
,单纯if不可以用。
🎉关键字
1、static调用格式:
1、同一个类中:
静态的:
方法名 属性名
类名.方法名 类名.属性名
对象名.方法名 对象名.属性名
非静态的:
对象名.属性名 对象名.方法名
2、不同类中:
静态的:
对象名.方法名 对象名.属性名
类名.方法名 类名.属性名
非静态的:
对象名.属性名 类名.方法名
注意:1、static可以修饰属性、方法、代码块,不可以修饰类和构造方法。
2、静态方法随着类的加载而加载。
3、在静态方法区内的东西只有一份,所有的对象共享这一份空间,只要有一个对象对属性进行修改,所有的对象调用都是修改后的数据。
4、代码块的执行顺序:静态代码块(只被调用一次)>构造代码块>构造方法>普通方法(需调用)
2、this关键字
1、可以调用属性和方法。
this.属性名(全局变量)
this.方法名();
2、在构造方法中:
1、this();括号内的参数个数、顺序、类型根据调用的方法来决定。
2、必须放在第一行,只能调用一次。
3、调用构造方法时只能在构造方法中调用,调用属性和方法时可以在构造方法中可以在普通方法中。
4、当全局变量和局部变量有重名字的时候,用this来区分。
3、super关键字
1、super指代父类对象。
2、super可以调用属性、方法、构造方法。
3、super调用父类的构造方法。
4、super调用构造方法时候必须放在第一行。
4、final最终的
1、可以修饰全局变量,声明的时候必须赋值,只能赋值一次。
2、可以修饰局部变量,声明时候可以不赋值,但也只能赋值一次。
3、可以修饰方法,可以正常使用,不能被重写。
4、可以修饰类,可以正常使用,不能被继承。
5、用final修饰的属性通常叫常量。
6、static final 全局变量。每个字母都要大写。
5、this和super的区别
1、this指的是本类创建的对象。 super指代的是父类的对象
2、this可以调用属性、方法、构造方法。 super也可以调用属性、方法、构造方法。
3、this调用属性和方法的时候,调用自己本类的属性和方法。 如果本类没有,那就用super去父类中找
4、this调用构造方法调用,调用本类的其他构造方法。 super调用父类的构造方法。
5、this和super在调用构造方法的时候必须放在第一行。
6、this和super不能同时存在
6、最小作用域最强原则:
局域变量在此方法中,比全局变量在此方法中的作用强。
🥫作用域public、private、protected 以及不写时的区别?
private
修饰的成员变量和函数只能在类本身和内部类中被访问
protected
修饰的成员变量和函数能被类本身、子类及同一个包中的类访问
public
修饰的成员变量和函数可以被类、子类、同一个包中的类以及任意其他类访问
默认情况(不写)下,属于一种包访问,即能被类本身以及同一个包中的类访问
作用域 | 当前类 | 统一package | 子孙类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
friendly | √ | √ | × | × |
private | √ | × | × | × |
🥚forward和redirect两种跳转方式的区别?
1.从地址栏显示来说
forward
是服务器请求资源,服务器直接访问目标地址的URL
,把那个URL
的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect
是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL
2.从数据共享来说
forward
:转发页面和转发到的页面可以共享request
里面的数据
redirect
:不能共享数据.
3.从运用地方来说
forward
:一般用于用户登陆的时候,根据角色转发到相应的模块
redirect
:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
4.从效率来说
forward
:高
redirect
:低
🍧HashMap和Hashtable的区别?
HashMap
:实现了Map接口,允许空(null)键值(key),由于非线程安全,在只有一个线程访问的情况下,效率高于Hashtable。
Hashtable
:不能将null作为key或者value。方法是同步的,线程安全。
🍨List、Set和Map的区别?
List:是存储单列数据的集合,存储有顺序,允许重复。继承Collection接口。
Set: 是存储单列数据的集合。继承Collection接口。不允许重复。
Map:存储键和值这样的双列数据的集合,存储数据无顺序,键(key)不能重复,值(value)。可以重复。
🍷hashCode与equals的区别与联系?
一、equals方法的作用
1、默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。
2 、要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。
二、Hashcode()方法:
1、我们并没有覆盖equals方法只覆盖了hashCode方法,两个对象虽然hashCode一样,但在将stu1和stu2放入set集合时由于equals方法比较的两个对象是false,所以就没有在比较两个对象的hashcode值。
2、覆盖一下equals方法和hashCode方法,stu1和stu2通过equals方法比较相等,而且返回的hashCode值一样,所以放入set集合中时只放入了一个对象。
3、我们让两个对象equals方法比较相等,但hashCode值不相等试试,虽然stu1和stu2通过equals方法比较相等,但两个对象的hashcode的值并不相等,所以在将stu1和stu2放入set集合中时认为是两个不同的对象。
总结:
1、equals方法用于比较对象的内容是否相等(覆盖以后)
2、hashcode方法只有在集合中用到
3、当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)。
4、将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。
🧉模式
1、单例模式
分类:懒汉式、饿汉式
1、构造方法私有化
2、在本类中创建本类对象
3、保证对象的唯一性final
4、给外界提供得到对象的方法 static
5、在多线程中,饿汉式安全,懒汉式不安全
2、简单工厂模式
批量创建对象
1 创建工厂类 : 创建对象的方法
2 果汁类 是所有种类果汁的父类
3 在工厂类的方法中返回果汁类
4 根据测试类中传递的字符串判断到底返回哪种果汁
5 测试类通过工厂类返回果汁对象
3、建造者模式
内部类使用场景
目的:静态内部类创建外部类对象
1、 创建外部类,在其中创建一个静态内部类
2、静态内部类中写属性,构造方法和set get方法
3、静态内部类中写一个方法,必须返回外部类对象
4、 给外部类创建对象,传递参数。
4、装饰者模式
1、在处理流中使用
2、子类重写父类的方法,提高父类方法的功能及效率
3、为了尽可能减少重复代码,在重写的方法中用父类的对象调用父类原来的方法
4、得到父类对象可以通过将父类对象作为子类属性,通过子类构造方法传递父类对象
🥯Java常用类
1.装箱拆箱
1、装箱:把基本数据类型转成包装类类型
2、拆箱:把包装类类型转成基本数据类型
3、为什么要包装类
八种基本数据类型不满足面向对象的思想,不包括属性和方法。如果给基本数据类型添加功能,只能创建其包装类,将方法和属性封装进去(jdk5.0以后出现了自动拆箱,装箱)
4、Integer支持字符串,但字符串必须是数字。Integer integer3=new Integer("2");
compareTo(); 比较大小,大返回整数,小于返回负数,相等返回0
toBinaryString(); 将十进制数转成二进制,返回String字符串的表现形式
toHexString(); 将十进制转成十六进制
toOctalString(); 将十进制转成八进制
toString(); 将int类型数据转成String字符串
Integer.valueOf(); 将int转成integer类型对象
new Integer(); 将int转成integer类型对象
parseInt(); 将Integer转成int
2.String字符串
== 比较地址
.equals() 比较内容
.equalsIgnoreCase() 忽略大小写比较是否相同
.charAt(); 字符串截取出指定的下标开始
.compareTo() 比较大小
.compareToIgnore() 忽略大小比较
.concat() 将参数字符串连接到指定字符串后面
.contains() 是否包含参数字符串
.startsWith() 以指定前缀开头
.endsWith() 以指定后缀结尾
.indexOf("/") 第一次出现
.indexOf("/", 3) 指定位置开始索引
.lastIndexOf("/") 最后一次出现
.substring(string11.lastIndexOf("/")+1);截取指定位置
.substring(string11.lastIndexOf("/")+1, string11.lastIndexOf("."));//截取字符串,指定开始位置和结束位置
.replace('a', 'b') 替换指定字符串,替换所有的
.toUpperCase() 全部转为大写
.toLowerCase() 全部转成小写
.trim() 去掉字符串前后的空格,中间的去不掉
3.Boolean
Boolean boolean=new Boolean("false");
System.out.println(boolean);
4.正则表达式
字符类
[abc] a、b、c其中任意一个
[^abc] 除了a、b、c中的任意一个
[a-zA-Z] a-z或A-Z范围中的任意一个
[a-zA-Z0-9] a-z A-Z 0-9 其中任意一个
[……] 可以自己定义范围
预定字符类
\\d 数字0-9
\\D 非数字0-9
\\s 空白字符:[ \\t\\n\\x0B\\f\\r]
\\S 非空白字符:\\s
\\w 单词字符:[a-zA-Z_0-9]
\\W 非单词字符\\w
数量词
? 一次或者一次也没有
* 0次到多次
+ 一次或者多次
n 恰好n次
n, 至少n次
n,m 至少n次但不超过m次
.matches(); 匹配是否适合
.spil(); 拆分
5.时间相关类
1、Date类
.getTime();计算毫秒
2、SimpleDateFormat类 格式化时间
.format();返回的是String字符串
3、Calendar接口 日历字段之间的转换提供了一些方法
.get(Calendar.YEAR);
.get(Calendar.MONTH);// 默认是当前月份减一 从0开始的
.get(Calendar.DAY_OF_MONTH);
.get(Calendar.DAY_OF_WEEK);
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
4、Runtime运行时时间
.freeMemory(); 当前的系统剩余空间
5、System.exit(0);退出程序,参数是0 是正常退出
System.gc();调用垃圾回收器 ,不一定能够起来 ,只是起到一个促进的作用
🎄Java集合框架
🚀常用的三种集合接口:
1.List:继承自Collection。可以存在相同的对象,有序的。具体实现类有ArrayList,LinkedList,Vector等(已经被抛弃,很少使用)
2.Set:继承自Collection。不能存在相同的对象,无序的,就是数学意义上的集合。具体实现类有HashSet,LinkedHashSet,TreeSet等。
3.Map:以键值对的形式存放对象。key-value。一般是key为String类型,value为Object的类型。具体实现类有HashMap,Linke以上是关于❤三万字带你了解那些年面过的Java八股文建议收藏的主要内容,如果未能解决你的问题,请参考以下文章
Python可视化应用实战-三万字长文(建议收藏)matplotlib可视化实例,实操有效
三万字<Java基础到就业> SpringMVC 必读(建议收藏)
三万字<Java基础到就业> SpringMVC 必读(建议收藏)