Java超高频面试题!!!

前言

本文将会涉及到Java面试中的高频考题,覆盖面非常广,但是并不会讲解的特别详细,推荐当作面试前的 复习提纲 使用。

文章会不断更新,也可能会另开新篇。

祝各位面试顺利,收获理想offer!

Redis 5种 【基本数据类型】

  1. String:字符串。
  2. Hash:哈希,由键和值组成的map,键 / 值 皆为 String 类型。
  3. List:列表,按照 输入的顺序 存储 String 类型数据。
  4. Set:集合,唯一、无序 的存储 String 类型数据。
  5. ZSet:有序集合,唯一、有序 的存储 String 类型数据。(Sorted Set)

Java 4种【修饰权限】

  1. private:类内
  2. protected:类内、子类、包内
  3. 默认(友好型):包内
  4. public:无限制

cookie / session / token

CookieSession
数据大小小文本数据,限制4KB多样数据类型,稍大
存储位置客户端服务器(压力大),并会在cookie中设置session ID
安全性较高
使用场景每次HTTP请求,浏览器自动携带cookie给服务器,校验登录状态…通过唯一 session ID 识别用户

Token:“令牌技术”。

服务端生成 的一串 加密的字符串jwt:header + payload + signature),客户端 在每次请求时发送给服务器做校验。

不依赖于cookie,因此可以用于 移动应用跨域 请求 ❗

可以包含用户的身份信息和权限数据,但是 敏感数据 ❌ 不推荐写入token,token是可以被轻松破译的。


Java【反射】

  1. 获取Class对象:String.class / str.getClass()
  2. 创建对象:getConstructor() + newInstanse()
  3. 获取方法与变量:getMethod() + getField()
  4. 使用方法:method.invoke()

MyBatis 的【# 与 $】

#会 预编译,对于字符串参数会加上引号,防止SQL注入;

$只是作简单的 字符串替换,不会有预编译效果,所以可能会被注入恶意SQL,例如delete…


StringBuilder 和 StringBuffer

在这里插入图片描述

StringBuilder 线程不安全,但是效率高;

StringBuffer 线程安全,内置锁,但是效率低。


【抽象类 和 接口】

相同点:都不能直接使用,都是抽象概念。

【抽象类】强调所属关系,可以有构造方法,可以有方法实现;【接口】强调功能的抽象。

【抽象类】用 extends 继承;【接口】用 implements 实现


【final】关键字

  • 变量:只能被赋值一次
  • 方法:不可被重写
  • 类:不可继承

JVM【内存模型】

在这里插入图片描述

  • 线程 共有:方法区 + 堆;
  • 线程 私有:本地方法栈 + 虚拟机栈 + 程序计数器。

“源代码 → 可执行文件” 的过程

在这里插入图片描述

注意:Java编译器和Java解释器都是JVM的一部分。


【JDK / JRE / JVM】

  • JDK:Java Development Kit,Java开发工具包,包含Java的开发工具JRE;开发工具包括:编译工具(javac.exe)打包工具(jar.exe)等。
  • JRE:Java Runtime Environment,Java运行环境,包括Java虚拟机 (JVM) 和 核心类库等;如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
  • JVM:Java Virtual Machine,java虚拟机,它只认识.class为后缀的文件,它能将class文件中的 字节码指令 进行识别,并调用操作系统向上的API完成动作。JVM是java能够跨平台的核心机制。通俗的说就是跨平台用的,就是把我们写的代码,转换成class文件用的

在这里插入图片描述


【Linux】常用命令

  1. ls:当前目录 内容
  2. pwd:当前目录 路径
  3. mkdir创建目录;
  4. cd打开目录;
  5. vim创建或打开文件(使用vim);
  6. rm删除文件或目录;
  7. mv修改文件或目录名称;
  8. tar:解压缩包
  9. ps显示运行的进程
  10. grep:在文件中搜索指定文本
  11. (nohup) java -jar xxx.jar:启动Java项目;
  12. ps -ef | grep xxx:查看Java项目进程;
  13. kill终止进程;
  14. shutdown关机
  15. sudo:以超级用户权限运行命令(sudo useradd 创建用户…)。

1 ~ 2:当前目录 的内容与位置;
3 ~ 7:目录与文件 增删改查
9 ~ 13:Java项目 与 进程的查阅 / 终止

此处并不全面,有更多需求可以查阅 👉 Linux常用命令60条


Java【IO流】

在这里插入图片描述

  • 字节 流(InputStream / OutputStream):万能 的IO流,但是其内容无法查阅(是字节码);
  • 字符 流(Reader / Writer):主要处理 文本,其内容是可查阅的。

Java【多线程】开启方法

  1. 继承 Thread 类;
  2. 实现 Runnable 接口;
  3. FutureTask 封装 Callable 接口实例…

Java是 【单继承、多实现】 的,所以通常使用Runnable较多,可以避免单继承的局限性。


Java 常见的【线程安全类】

  • 单列集合:Vector
  • 多列集合:HashTableConcurrentHashMap
  • StringBuffer…

Java 常见的【加密】方法

  • 单向加密算法(不可破解):MD5、SHA、HMAC…
  • 非单项加密算法(可解密):BASE64对称加密算法、非对称加密算法、数字签名算法、数字证书…

Java【泛型】

泛型的【本质】是 参数化类型,也就是说所操作的 数据类型 被指定为一个 参数

如果没有泛型,程序会在 运行时 报错;而使用泛型后,我们在编译时就可以检查错误。

泛型可以避免因类型不同而重复书写类、接口和方法的情况,提高 代码复用

常见的 泛型标识
T :代表一般的任何类。
E :代表 Element 元素的意思,或者 Exception 异常的意思。
K :代表 Key 的意思。
V :代表 Value 的意思,通常与 K 一起配合使用。
S :代表 Subtype 的意思,文章后面部分会讲解示意。

1. 泛型类

最典型的泛型类就是Java的各种集合类,例如:ArrayList、HashMap

// ArrayList
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}

// 自定义泛型类
public class Generic<T> { 
 
    private T key;

    public Generic(T key) { 
        this.key = key;
    }

    public T getKey(){ 
        return key;
    }
}

2. 泛型接口

Java类库中的常见接口也不在少数:List、Map、Set

// Map
public interface Map<K,V> {}

// 自定义泛型接口
public interface Inter<T> {
    public abstract void show(T t) ;
}

3. 泛型方法

public <类型参数> 返回类型 方法名(类型参数 变量名) {
    ...
}

public class Test<T> { // 泛型类
	public void testMethod(T t) { // 泛型类中的【普通方法】
		System.out.println(t);
	}
	
	public <T> T testMethod1(T t) { // ⭐ 泛型类中的【泛型方法】
		return t;
	}
}

4. 泛型通配符

通配符通常在 规定泛型的 上界、下界 时使用:

类型通配符:< ? >
有上界的类型通配符:< ? extends T > 【?不能高于 T类型】
有下界的类型通配符:< ? super T > 【?不能低于 T类型】

List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
List<?> list3 = new ArrayList<Integer>();

//        List<? extends Number> list4 = new ArrayList<Object>(); -> 报错
List<? extends Number> list5 = new ArrayList<Number>();
List<? extends Number> list6 = new ArrayList<Integer>();

List<? super Number> list7 = new ArrayList<Object>();
List<? super Number> list8 = new ArrayList<Number>();
//        List<? super Number> list9 = new ArrayList<Integer>(); -> 报错

(推荐学习文章 👉 Java中的泛型


【static】关键字

被static修饰的 成员变量和方法 并不属于某个对象,而是属于类,不需要创建对象就可以调用。

⭐ 在类的内部:

  • 静态方法 只能使用 静态成员变量,只能调用 静态方法
  • 非静态方法 可以使用 所有成员变量,可以调用 所有方法
  • 静态成员变量 可以被 所有方法 使用。
  • 非静态成员变量 只能被 非静态方法 使用。

其实很好记忆:
① 静态就是一直都有的,非静态就是原本没有的
② 第一条举例:静态方法一直存在,为了不出错,他也只能使用一直存在的部分。
③ 第二条举例:非静态方法创建出来的时候,对象必然创建了,所有部分都已经可用了。


Java 中常用的【锁】

SynchronizedReentrantLock
所属位置Java内置锁util下的类
加锁方式自动手动
修饰范围代码块、方法代码块
响应中断不可响应线程中断可中断线程,解决死锁
实现原理JVM层面通过监视器基于AQS

ReentrantLock 开启锁的方式:(释放锁 unlock)

  1. lock():① 锁空闲:立刻获取;② 当前线程持有:持有数 +1;③ 其他线程持有:当前线程 一直休眠,直到获取锁。
  2. lockInterruptibly():逻辑同lock,但可 响应线程中断
  3. tryLock():① 锁空闲:立刻获取,返回true;② 当前线程持有:持有数 +1,返回true;③ 其他线程持有:返回false
  4. tryLock(long timeout, TimeUnit unit):逻辑同tryLock,但其他线程持有时会 等待一段时间

不难看出,ReentrantLock 的 2、3、4 加锁方式都可以有效 避免死锁 问题。

死锁检测工具:jstack、jconsole


Java 常用的【设计模式】

在这里插入图片描述

挑两个非常常见的介绍:单例模式、工厂模式。推荐学习 👉 Java中常用的设计模式

1. 单例模式

单例模式 是一种创建型设计模式,它确保一个类 只有一个实例,并 提供 一个 全局访问点 来访问该实例。

【优点】

  1. 在内存里只有一个实例,减少 内存开销,尤其是 频繁的创建和销毁 实例;
  2. 避免对 资源的多重占用(比如写文件操作)。

【缺点】

  1. 职责过重,违背 单一职责原则
  2. 没有抽象层,不能拓展

2. 工厂模式

工厂模式 属于创建型模式,它在 创建对象时 提供了一种 封装机制,将实际 创建对象的代码使用代码 分离。

您需要一辆汽车,可以直接 从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。

【优点】

  1. 大量的产品 需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。
  2. 扩展性高,如果想增加一个产品,只要 扩展一个工厂类 就可以;
  3. 屏蔽产品的具体实现,调用者只关心 产品的接口

【缺点】

工厂类负责创建所有实例;如果有 新的类加入,需要 不断的修改 工厂类,不利于后期维护


【HTTP 与 HTTPS】的区别

  1. 安全:HTTP 明文传输,安全性较差;HTTPS(SSL+HTTP) 数据传输过程是 加密的,安全性较好。
  2. 费用:使用 HTTPS 协议需要到 CA 申请证书,一般免费证书较少,因而需要一定费用。
  3. 响应速度:HTTP 页面 响应速度 比 HTTPS 快: HTTP 使用 TCP 三次握手建立连接,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
  4. 连接方式:HTTP 和 HTTPS 连接方式 不同,用的 端口 也不一样,前者是 80,后者是 443。
  5. 资源消耗:HTTPS 是建构在 SSL/TLS 之上的 HTTP 协议,所以 HTTPS 更耗费 服务器资源

推荐学习 👉 HTTP 与 HTTPS


五层【网络协议】

在这里插入图片描述

OSI 参考模型 通常只做理论层面的研究,实际应用都会采用 TCP/IP 五层协议 的体系结构。

TCP/IP 模型 中,每一层都有着特定的协议选择:

  1. 应用层HTTP(超文本传输协议)、FTP(文件传输协议)、DNS(域名解析协议)…
  2. 传输层TCP、UDP
  3. 网络层IP

注意:应用层传输层【端对端】 传输,它们不需要知道底层是如何传输的,是一条 逻辑链路;而下面三层是 【点对点】 传输,严格的从一台设备传输到另一台设备。


TCP【三次握手】

在这里插入图片描述

  1. 客户端向服务端发送一个连接请求报文段SYN;【客户端发送】
  2. 服务端收到请求后,回复一个确认报文段SYN-ACK,表示接受连接请求;【服务端接收 + 发送】
  3. 客户端再次回复一个确认报文段ACK,表示确认服务器的接受。【客户端接收】

在通过三次握手之后,客户端 和 服务端 都互相了解一个事实:彼此都拥有良好的【接收与发送】能力! 所以连接建立,可以通信。


TCP【四次挥手】

在这里插入图片描述

  1. 客户端向服务端发送一个连接释放请求报文段FIN;
  2. 服务端收到请求后,回复一个确认报文段ACK,表示接受释放请求;
  3. 服务端再向客户端发送一个连接释放请求报文段FIN;
  4. 客户端收到请求后,回复一个确认报文段ACK,表示接受释放请求。

首先弄清楚SYN、FIN、ACK代表什么意思:

  • SYN:我可以发送,我们连接好吗?
  • FIN:我不再发送,但是仍可以接收。
  • ACK:收到请求,发送同意回复。

所以,在【三次握手】时,“SYN-ACK” 一起发送并不影响逻辑;但是【四次挥手】的 “FIN 和 ACK” 不能一起发送,否则逻辑上形成 “我不再发送 + 我发送了同意回复” ❌;正确的应该是先ACK,再FIN,这就是为什么会多出一个步骤。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值