1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-08-01 16:28:03 +08:00

Compare commits

..

No commits in common. "1ba08ab91f48e0f2207e38066d64d222afcbabf3" and "58696c742be4e8e895450bed474ca03d6ef65083" have entirely different histories.

5 changed files with 3 additions and 87 deletions

View File

@ -599,12 +599,6 @@ Node{data=21, maxLevel=3}
Node{data=23, maxLevel=1} Node{data=23, maxLevel=1}
``` ```
**Redis 跳表的特点**
1. 采用**双向链表**,不同于上面的示例,存在一个回退指针。主要用于简化操作,例如删除某个元素时,还需要找到该元素的前驱节点,使用回退指针会非常方便。
2. `score` 值可以重复,如果 `score` 值一样,则按照 ele节点存储的值为 sds字典排序
3. Redis 跳跃表默认允许最大的层数是32被源码中 `ZSKIPLIST_MAXLEVEL` 定义。
## 和其余三种数据结构的比较 ## 和其余三种数据结构的比较
最后,我们再来回答一下文章开头的那道面试题: “Redis 的有序集合底层为什么要用跳表,而不用平衡树、红黑树或者 B+树?”。 最后,我们再来回答一下文章开头的那道面试题: “Redis 的有序集合底层为什么要用跳表,而不用平衡树、红黑树或者 B+树?”。

View File

@ -24,7 +24,7 @@ head:
负载均衡可以简单分为 **服务端负载均衡****客户端负载均衡** 这两种。 负载均衡可以简单分为 **服务端负载均衡****客户端负载均衡** 这两种。
服务端负载均衡涉及到的知识点更多,工作中遇到的也比较多,因,我会花更多时间来介绍。 服务端负载均衡涉及到的知识点更多,工作中遇到的也比较多,因,我会花更多时间来介绍。
### 服务端负载均衡 ### 服务端负载均衡

View File

@ -379,84 +379,6 @@ public class OutterClass
} }
``` ```
**为什么内部类可以使用外部类的private属性**
我们在InnerClass中增加一个方法打印外部类的userName属性
```java
//省略其他属性
public class OutterClass {
private String userName;
......
class InnerClass{
......
public void printOut(){
System.out.println("Username from OutterClass:"+userName);
}
}
}
// 此时使用javap -p命令对OutterClass反编译结果
public classOutterClass {
private String userName;
......
static String access$000(OutterClass);
}
// 此时InnerClass的反编译结果
class OutterClass$InnerClass {
final OutterClass this$0;
......
public void printOut();
}
```
实际上在编译完成之后inner实例内部会有指向outer实例的引用`this$0`,但是简单的`outer.name`是无法访问private属性的。从反编译的结果可以看到outer中会有一个桥方法`static String access$000(OutterClass)`恰好返回String类型即userName属性。正是通过这个方法实现内部类访问外部类私有属性。所以反编译后的`printOut()`方法大致如下:
```java
public void printOut() {
System.out.println("Username from OutterClass:" + OutterClass.access$000(this.this$0));
}
```
补充:
1. 匿名内部类、局部内部类、静态内部类也是通过桥方法来获取private属性。
2. 静态内部类没有`this$0`的引用
3. 匿名内部类、局部内部类通过复制使用局部变量,该变量初始化之后就不能被修改。以下是一个案例:
```java
public class OutterClass {
private String userName;
public void test(){
//这里i初始化为1后就不能再被修改
int i=1;
class Inner{
public void printName(){
System.out.println(userName);
System.out.println(i);
}
}
}
}
```
反编译后:
```java
//javap命令反编译Inner的结果
//i被复制进内部类且为final
class OutterClass$1Inner {
final int val$i;
final OutterClass this$0;
OutterClass$1Inner();
public void printName();
}
```
### 条件编译 ### 条件编译
—般情况下,程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译。 —般情况下,程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译。

View File

@ -258,7 +258,7 @@ public V get(Object key) {
```java ```java
void afterNodeAccess(Node < K, V > e) { // move node to last void afterNodeAccess(Node < K, V > e) { // move node to last
LinkedHashMap.Entry < K, V > last; LinkedHashMap.Entry < K, V > last;
//如果accessOrder 且当前节点不链表尾节点 //如果accessOrder 且当前节点不链表尾节点
if (accessOrder && (last = tail) != e) { if (accessOrder && (last = tail) != e) {
//获取当前节点、以及前驱节点和后继节点 //获取当前节点、以及前驱节点和后继节点

View File

@ -162,7 +162,7 @@ HMACSHA256(
3. JWT 存放在 localStorage 中而不是 Cookie 中,避免 CSRF 风险。 3. JWT 存放在 localStorage 中而不是 Cookie 中,避免 CSRF 风险。
4. 一定不要将隐私信息存放在 Payload 当中。 4. 一定不要将隐私信息存放在 Payload 当中。
5. 密钥一定保管好一定不要泄露出去。JWT 安全的核心在于签名,签名安全的核心在密钥。 5. 密钥一定保管好一定不要泄露出去。JWT 安全的核心在于签名,签名安全的核心在密钥。
6. Payload 要加入 `exp` JWT 的过期时间),永久有效的 JWT 不合理。并且JWT 的过期时间不过长。 6. Payload 要加入 `exp` JWT 的过期时间),永久有效的 JWT 不合理。并且JWT 的过期时间不过长。
7. …… 7. ……
<!-- @include: @article-footer.snippet.md --> <!-- @include: @article-footer.snippet.md -->