From 97dd88a54c9418f47d21544350ed84500324cdc8 Mon Sep 17 00:00:00 2001 From: Guide Date: Sun, 14 Jul 2024 18:05:30 +0800 Subject: [PATCH] =?UTF-8?q?[docs=20update]=E5=AE=8C=E5=96=84=E5=AF=B9?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=92=8C=E6=8A=BD=E8=B1=A1=E7=B1=BB=E7=9A=84?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/database/mysql/mysql-questions-01.md | 16 +++-- docs/java/basis/java-basic-questions-02.md | 76 ++++++++++++++++++---- 2 files changed, 75 insertions(+), 17 deletions(-) diff --git a/docs/database/mysql/mysql-questions-01.md b/docs/database/mysql/mysql-questions-01.md index fcb60af0..ebc6f4a2 100644 --- a/docs/database/mysql/mysql-questions-01.md +++ b/docs/database/mysql/mysql-questions-01.md @@ -249,7 +249,11 @@ mysql> SHOW VARIABLES LIKE '%storage_engine%'; MySQL 存储引擎采用的是 **插件式架构** ,支持多种存储引擎,我们甚至可以为不同的数据库表设置不同的存储引擎以适应不同场景的需要。**存储引擎是基于表的,而不是数据库。** -并且,你还可以根据 MySQL 定义的存储引擎实现标准接口来编写一个属于自己的存储引擎。这些非官方提供的存储引擎可以称为第三方存储引擎,区别于官方存储引擎。像目前最常用的 InnoDB 其实刚开始就是一个第三方存储引擎,后面由于过于优秀,其被 Oracle 直接收购了。 +下图展示了具有可插拔存储引擎的 MySQL 架构(): + +![MySQL architecture diagram showing connectors, interfaces, pluggable storage engines, the file system with files and logs.](https://oss.javaguide.cn/github/javaguide/mysql/mysql-architecture.png) + +你还可以根据 MySQL 定义的存储引擎实现标准接口来编写一个属于自己的存储引擎。这些非官方提供的存储引擎可以称为第三方存储引擎,区别于官方存储引擎。像目前最常用的 InnoDB 其实刚开始就是一个第三方存储引擎,后面由于过于优秀,其被 Oracle 直接收购了。 MySQL 官方文档也有介绍到如何编写一个自定义存储引擎,地址: 。 @@ -353,7 +357,7 @@ MySQL 索引相关的问题比较多,对于面试和工作都比较重要, ## MySQL 查询缓存 -执行查询语句的时候,会先查询缓存。不过,MySQL 8.0 版本后移除,因为这个功能不太实用 +MySQL 查询缓存是查询结果缓存。执行查询语句的时候,会先查询缓存,如果缓存中有对应的查询结果,就会直接返回。 `my.cnf` 加入以下配置,重启 MySQL 开启查询缓存 @@ -369,7 +373,7 @@ set global query_cache_type=1; set global query_cache_size=600000; ``` -如上,**开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果**。这里的查询条件包括查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息。 +查询缓存会在同样的查询条件和数据情况下,直接返回缓存中的结果。但需要注意的是,查询缓存的匹配条件非常严格,任何细微的差异都会导致缓存无法命中。这里的查询条件包括查询语句本身、当前使用的数据库、以及其他可能影响结果的因素,如客户端协议版本号等。 **查询缓存不命中的情况:** @@ -377,12 +381,16 @@ set global query_cache_size=600000; 2. 如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL 库中的系统表,其查询结果也不会被缓存。 3. 缓存建立之后,MySQL 的查询缓存系统会跟踪查询中涉及的每张表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。 -**缓存虽然能够提升数据库的查询性能,但是缓存同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。** 因此,开启查询缓存要谨慎,尤其对于写密集的应用来说更是如此。如果开启,要注意合理控制缓存空间大小,一般来说其大小设置为几十 MB 比较合适。此外,**还可以通过 `sql_cache` 和 `sql_no_cache` 来控制某个查询语句是否需要缓存:** +**缓存虽然能够提升数据库的查询性能,但是缓存同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。** 因此,开启查询缓存要谨慎,尤其对于写密集的应用来说更是如此。如果开启,要注意合理控制缓存空间大小,一般来说其大小设置为几十 MB 比较合适。此外,还可以通过 `sql_cache` 和 `sql_no_cache` 来控制某个查询语句是否需要缓存: ```sql SELECT sql_no_cache COUNT(*) FROM usr; ``` +MySQL 5.6 开始,查询缓存已默认禁用。MySQL 8.0 开始,已经不再支持查询缓存了(具体可以参考这篇文章:[MySQL 8.0: Retiring Support for the Query Cache](https://dev.mysql.com/blog-archive/mysql-8-0-retiring-support-for-the-query-cache/))。 + +![MySQL 8.0: Retiring Support for the Query Cache](https://oss.javaguide.cn/github/javaguide/mysql/mysql8.0-retiring-support-for-the-query-cache.png) + ## MySQL 日志 MySQL 日志常见的面试题有: diff --git a/docs/java/basis/java-basic-questions-02.md b/docs/java/basis/java-basic-questions-02.md index a7fee741..75df8c36 100644 --- a/docs/java/basis/java-basic-questions-02.md +++ b/docs/java/basis/java-basic-questions-02.md @@ -136,13 +136,13 @@ true ### 构造方法有哪些特点?是否可被 override? -构造方法特点如下: +构造方法具有以下特点: -- 名字与类名相同。 -- 没有返回值,但不能用 void 声明构造函数。 -- 生成类的对象时自动执行,无需调用。 +- **名称与类名相同**:构造方法的名称必须与类名完全一致。 +- **没有返回值**:构造方法没有返回类型,且不能使用 `void` 声明。 +- **自动执行**:在生成类的对象时,构造方法会自动执行,无需显式调用。 -构造方法不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多个构造函数的情况。 +构造方法**不能被重写(override)**,但**可以被重载(overload)**。因此,一个类中可以有多个构造方法,这些构造方法可以具有不同的参数列表,以提供不同的对象初始化方式。 ### 面向对象三大特征 @@ -200,17 +200,67 @@ public class Student { ### 接口和抽象类有什么共同点和区别? -**共同点**: +#### 接口和抽象类的共同点 -- 都不能被实例化。 -- 都可以包含抽象方法。 -- 都可以有默认实现的方法(Java 8 可以用 `default` 关键字在接口中定义默认方法)。 +- **实例化**:接口和抽象类都不能直接实例化,只能被实现(接口)或继承(抽象类)后才能创建具体的对象。 +- **抽象方法**:接口和抽象类都可以包含抽象方法。抽象方法没有方法体,必须在子类或实现类中实现。 -**区别**: +#### 接口和抽象类的区别 -- 接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是所属关系。 -- 一个类只能继承一个类,但是可以实现多个接口。 -- 接口中的成员变量只能是 `public static final` 类型的,不能被修改且必须有初始值,而抽象类的成员变量默认 default,可在子类中被重新定义,也可被重新赋值。 +- **设计目的**:接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是所属关系。 +- **继承和实现**:一个类只能继承一个类(包括抽象类),因为 Java 不支持多继承。但一个类可以实现多个接口,一个接口也可以继承多个其他接口。 +- **成员变量**:接口中的成员变量只能是 `public static final` 类型的,不能被修改且必须有初始值。抽象类的成员变量可以有任何修饰符(`private`, `protected`, `public`),可以在子类中被重新定义或赋值。 +- **方法**: + - Java 8 之前,接口中的方法默认是 `public abstract` ,也就是只能有方法声明。自 Java 8 起,可以在接口中定义 `default`(默认) 方法和 `static` (静态)方法。 自 Java 9 起,接口可以包含 `private` 方法。 + - 抽象类可以包含抽象方法和非抽象方法。抽象方法没有方法体,必须在子类中实现。非抽象方法有具体实现,可以直接在抽象类中使用或在子类中重写。 + +在 Java 8 及以上版本中,接口引入了新的方法类型:`default` 方法、`static` 方法和 `private` 方法。这些方法让接口的使用更加灵活。 + +Java 8 引入的`default` 方法用于提供接口方法的默认实现,可以在实现类中被覆盖。 + +```java +public interface MyInterface { + default void defaultMethod() { + System.out.println("This is a default method."); + } +} +``` + +Java 8 引入的`static` 方法无法在实现类中被覆盖,只能通过接口名直接调用( `MyInterface.staticMethod()`),类似于类中的静态方法。 + +```java +public interface MyInterface { + static void staticMethod() { + System.out.println("This is a static method in the interface."); + } +} +``` + +Java 9 允许在接口中使用 `private` 方法。`private`方法可以用于在接口内部共享代码,不对外暴露。 + +```java +public interface MyInterface { + // default 方法 + default void defaultMethod() { + commonMethod(); + } + + // static 方法 + static void staticMethod() { + commonMethod(); + } + + // 私有静态方法,可以被 static 和 default 方法调用 + private static void commonMethod() { + System.out.println("This is a private method used internally."); + } + + // 私有方法,只能被 default 方法调用。 + private void instanceCommonMethod() { + System.out.println("This is a private instance method used internally."); + } +} +``` ### 深拷贝和浅拷贝区别了解吗?什么是引用拷贝?