Java面试笔记
【前言】已经属于准备秋招的落后选手了,2022受大环境影响实习还挺难找的,本人也属于Java小白,读研之后才开始用Java做开发,本科期间一直在用python。文章中许多资料出自代码随想录、黑马程序员等处。
文章目录
基础知识
JDK与JRE
- JDK(Java Development Kit)是Java开发工具包,里面包含Java的开发环境(提供了编译器javac等工具,用于将java文件编译为class文件)和运行环境(提供了JVM和Runtime辅助包,用于解析class文件使其运行)。如果你安装了JDK,那么你即可以开发Java程序,也同时拥有了运行java程序的平台。Jdk是整个java的核心,包括了jre(java运行环境)。
- JRE(Java Runtime Enviroment)是JAVA的运行环境。面向Java程序的使用者,而不是开发者。如果你仅下载并安装了JRE,那么你的系统只能运行Java程序。不能开发Java程序。jre是运行Java程序所必须环境的集合,包含Jvm标准实现及Java核心类库。
数据结构
ArrayList和LinkedList
ArrayList底层使用Object[] 数组实现,默认初始化容量10,每次扩容1.5倍,内存空间连续,适合查询操作
LinkedList底层是双向链表,适合插入删除的操作
Vector
底层是数组,初始化容量10,每次扩容为原始容量的2倍;
线程安全,方法带有synchronized关键字
HashMap
- 1.7中底层:数组+链表 1.8中底层:数组+红黑树
- 数组中每个元素是一个单向链表,单链表每个结点是node<Key, Value>类型
- 该数据结构特点:无序,不可重复(重写了equals)
- 默认初始化容量:16;数组容量达到3/4时,开始扩容
- 单链表元素超过8个,链表转为红黑树;红黑树结点小于6,转为单链表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rsvQCn5W-1656079199279)(C:\Users\11041\AppData\Roaming\Typora\typora-user-images\image-20220621170830338.png)]
为什么使用红黑树?为什么树化阈值是8?
方法
方法名和参数表共同构成方法签名,修饰符和返回值类型不属于方法签名。
引用传递与值传递:
1.按值传递不会改变实际参数的数值,Java 中只有值传递。值传递的含义是将实参的值传递给形参,当参数类型是基本数据类型时,传递的是实参的值,当参数类型是对象时,传递的是对象的引用,但是不能让实参引用新的对象。
2.按引用传递可以改变实际参数的内容,但不能改变实际参数的参考地址(一般是对数组,对象,Map等非基本数据类型)
Collections工具类
Collections.sort(List list, *Compataor cmp)
如果要排序的是HashSet,利用ArrayList构造器转换为list
ArrayList list = new ArrayList(set);
Collections.sort(list);
String存储原理
String类型不可变
//这类""中的字符串直接存储在方法去的字符串常量池
String s1 = "abc";
String s2 = "abc";
System.out.println(s1==s2); //false,地址不同
System.out.println(s1.equals(s2)); //true,比较内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q9FrpTGw-1656079199279)(C:\Users\11041\AppData\Roaming\Typora\typora-user-images\image-20220623112007636.png)]
- String底层数组用final修饰,不可变
- StringBuilder底层数组可变;线程不安全,效率高
- StringBuffer底层数组可变;线程安全,效率低
【例题】String s = new String(“xyz”) 创建了几个字符串对象?
一个或两个。如果字符串常量池已经有“xyz”,则是一个;否则,两个。 当字符创常量池没有 “xyz”,此时会创建如下两个对象:
- 一个是字符串字面量 “xyz” 所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,此时该实例也是在堆中,字符串常量池只放引用。
- 另一个是通过 new String() 创建并初始化的,内容与"xyz"相同的实例,也是在堆中。
==和equals
==:用于比较基础类型变量和引用类型变量
- 对于基础类型变量,比较的变量保存的值是否相同,类型不一定要相同
- 对于引用类型变量(通过new创建),比较的是两个对象的地址是否相同
equals:Object 类中定义的方法,通常用于比较两个对象的值是否相等
面向对象
概念
- 面向对象和面向过程的区别有哪些?分别有什么优缺点?
面向过程将问题分解成步骤,按照步骤实现函数,并依次调用,数据和对数据的操作是分离的。面向对象将问题分解成对象,描述事物的行为,对象与属性和行为是关联的。
面向过程的优点是性能高,缺点是不容易维护、复用和扩展。面向对象的优点是具有封装、继承、多态的特性,因而容易维护、复用和扩展,缺点是性能低。
- 对象和类之间有哪些联系?
对象是具体的实例,有自己独有的状态和行为。类是对具有相同特征的对象的抽象,用来定义对象的状态和行为。可以从一个类创建多个对象。
构造方法
构造方法没有返回值,用于初始化
静态和实例
从外部调用静态的类成员时,可以通过类名调用,也可以通过对象名调用。从外部调用实例的类成员,则只能通过对象名调用。
静态方法只能访问静态的类成员,不能访问实例的类成员。实例方法既可以访问实例的类成员,也可以访问静态的类成员。
初始化块
分类
初始化块可以分成静态初始化块和非静态初始化块,前者在加载类时被隐式调用,后者在创建对象时被隐式调用。
执行顺序(在main函数前)
更一般的情况,对于多个类之间的继承关系(可能超过两个类,例如 B 继承了 A,C 继承了 B),执行顺序如下。
-
按照从父类到子类的顺序,依次执行每个类的静态初始化块。
-
按照从父类到子类的顺序,对于每个类,依次执行非静态初始化块和构造器,然后执行子类的非静态初始化块和构造器,直到所有类执行完毕。
示例代码
public class Main {
static {
System.out.println("Static initialization of Main");
}
{
System.out.println("Instance initialization of Main");
}
public Test() {
System.out.println("Constructor of Main");
}
public static void main(String[] args) {
new Class3();
}
}
class Class1 {
static {
System.out.println("Static initialization of Class1");
}
{
System.out.println("Instance initialization of Class1");
}
Class1() {
System.out.println("Constructor of Class1");
}
}
class Class2 extends Class1 {
static {
System.out.println("Static initialization of Class2");
}
{
System.out.println("Instance initialization of Class2");
}
Class2() {
System.out.println("Constructor of Class2");
}
}
class Class3 extends Class2 {
static {
System.out.println("Static initialization of Class3");
}
{
System.out.println("Instance initialization of Class3");
}
Class3() {
System.out.println("Constructor of Class3");
}
}
/**
*输出
Static initialization of Main
Static initialization of Class1
Static initialization of Class2
Static initialization of Class3
Instance initialization of Class1
Constructor of Class1
Instance initialization of Class2
Constructor of Class2
Instance initialization of Class3
Constructor of Class3
*/
关键字this
class Square {
int side;
public Square() {
this(1);
}
public Square(int side) {
this.side = side;
}
public int getPerimeter() {
return this.side * 4;
}
public int getArea() {
return this.side * this.side;
}
}
this不可以在静态方法中使用
修饰符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlR0Vbk4-1656079199280)(C:\Users\11041\AppData\Roaming\Typora\typora-user-images\image-20220412233948872.png)]
Java并发
Java线程
线程的六种状态:

虚拟机

Java Source就是在IDE中敲的代码,经过javac编译后成为字节码,变为Java Class,可以跨平台
私有数据区
程序计数器
Java虚拟机栈
为创建的线程分配内存
局部变量表
Java序列化
Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
2797

被折叠的 条评论
为什么被折叠?



