每日一问

2022-06-21 setter & getter

  1. setter 和 gettter 的实际意义
  • 为什么要有setter & getter, public dot直接使用不是更方便快捷吗? 而且setter和getter最终的效果也是读写

    • 安全:程序可以选择只读或只写或读写
    • 灵活:如果不仅仅只是读写属性值,可以自由变换
    • 封装:隐藏内部实现细节
    • 健壮:便于维护,扩展
  • 由上一问,为什么public是不安全的呢?

    • 如果写sdk的话,那么有些数据是不想对外修改的,这时候public的作用就体现出来了。如果只是业务代码则,权限体现的不太大。
  • 扩展:Java的四大特性 - 直接粘贴

封装

What:隐藏信息,保护数据访问。
How:暴露有限接口和属性,需要编程语言提供访问控制的语法。
Why:提高代码可维护性;降低接口复杂度,提高类的易用性。

抽象

What: 隐藏具体实现,使用者只需关心功能,无需关心实现。
How: 通过接口类或者抽象类实现,特殊语法机制非必须。
Why: 提高代码的扩展性、维护性;降低复杂度,减少细节负担。

继承

What: 表示 is-a 关系,分为单继承和多继承。
How: 需要编程语言提供特殊语法机制。例如 Java 的 “extends”,C++ 的 “:” 。
Why: 解决代码复用问题。

多态

What: 子类替换父类,在运行时调用子类的实现。
How: 需要编程语言提供特殊的语法机制。比如继承、接口类、duck-typing。
Why: 提高代码扩展性和复用性。

2022-06-22 编译&反编译

编译:源码 -> 字节码 反编译:字节码 -> 源码

什么是字节码,采用字节码的好处是什么?

在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

2022-06-23 为什么String不可变

什么是不可变

一旦对象被创建并初始化后,内部的状态数据就会保持不变

为什么String不可变

  1. 最初的设计就是不可变,设计就是遵循一定的规则,基本约定,体现一致性。
  2. final和immutable无关
  3. 如果String可变,那么String就可以在方法之前来回穿梭,最终变成什么无人可知。
  4. 安全性:String作为hashmap的key值的时候,如果发生改变,则很难被发现
  5. 无线程安全问题
  6. 所以声明String为final一劳永逸

2022-06-25 为什么不应该通过类实例访问静态成员

如果使用类的实例来访问静态成员的话,那么IDEA会WARNING,那为什么会有这个WARNING呢?

查了一下网上的说明,模糊不清的说法是实例会被回收。

引申问题1 - 静态为什么叫静态?

静态变量 -> 类变量 是继承类的 所有对象共有的 非静态变量 -> 实例变量 具体对象的具体数据 根据对象的变化而变化 是继承对象的

引申问题2 - 什么时候可以定义静态变量或者方法?

所有的类都拥有的共同的属性 -> 静态变量

方法内部没有使用到非静态数据 -> 静态方法

引申知识点

  1. 静态的特点

    • 通过类的加载而加载 类一旦被加载进内存,静态的变量和方法就被加载进去了,对象还不存在
    • 静态先于对象存在
    • 被所有的对象共享
    • 可以直接被类名调用,也可以被对象调用
  2. 静态使用的注意事项

    • 静态方法只能访问静态成员,不能访问非静态成员
    • 非静态成员可以访问静态成员,也可以访问非静态成员
    • 静态方法中不能出现this,super等关键字
  3. 静态的好处和坏处

    • 优点:对于所有对象都共有的数据,节省空间;可以不新建对象直接使用;
    • 缺点:静态是通过类存在的,访问存在局限性,只能访问静态数据

2022-06-29 HashMap

数据结构

数组(每个Node叫做bucket) + 链表 + 红黑树

主体是一个数组,数组由一个个链表组成,链表由一个个Node组成,Node存储具体的key value

为什么要使用数组+链表的数据结构

解决hash冲突,首先使用hash(key)得出key的hash值,然后通过 (n-1) & hash 得出index,键值对存在该index所在的数组链表中。

不同的key可能产生相同的hash值

  1. 如何解决Hash冲突

遇到hash冲突后,会先判断两个key值是否相同,相同说明是同一个key,则覆盖。如果不相同,会将这个Node插入链表的尾部。

  1. 头插法和尾插法

头插法:每次在头部插入,作者认为后面插入的使用的概率会更大,会造成死锁的问题 尾插法:每次在尾部插入,JDK1.8后更新

为什么要把链表转换为红黑树?

  1. 查找效率

链表:时间复杂度O(n) 红黑树:时间复杂度O(log(n))

链表较短的时候差距不大,较长的时候可以提升效率

  1. 为什么不直接使用红黑树的数据结构

红黑树的空间复杂度是链表的2倍

2022-06-30 反射

反射是什么?

反射可以在运行时检查类、接口、方法和变量等信息,无需知道类的名字,方法名等。还可以在运行时实例化新对象,调用方法以及设置和获取变量值。

2022-07-04 - 07-05 红黑树

6.29日看了hashmap的原理,那么红黑树到底是什么呢?

二叉查找树 BST(Binary Search Tree)

任何一个节点的左子树上的点,都必须小于当前节点。 任何一个节点的右子树上的点,都必须大于当前节点。 任何一颗子树,也都满足上面两个条件。

2-3-4树

4阶的B树,Balance Tree

所有的叶子节点都拥有相同的深度 叶节点只能是2-节点、3-节点、4-节点 元素使用保持排序顺序,父节点大于左子节点,小于右子节点,如果节点有多个元素,则每个元素必须大于它左边的和它左子树中的元素

2022-07-07

为什么https协议调用接口需要SSL认证

  1. SSL: Secure Sockets Layer, 安全套接字层,为了解决HTTP协议是明文,避免传输的数据被窃取,篡改,劫持。
  2. TSL: Transport Layer Security, 传输层安全协议。TSL是SSL标准化的产物。
  3. HTTPS: 兼容HTTP,HTTP over TSL,HTTPS = HTTP + TSL

总之,就是为了安全

Java里面怎么做?

  1. 如果是Resttemplate的话需要跳过,具体代码如下, 在RestTemplateConfig中加入下面代码:
1
2
3
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, (X509Certificate[] chain, String authType) -> true).build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, (s, sslSession) -> true);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).setMaxConnPerRoute(1000).setMaxConnTotal(1000).build();
  1. X509Certificate

X.509是公钥基础设施(PKI)的标准格式。X.509证书就是基于国际电信联盟(ITU)制定的X.509标准的数字证书。

2022-07-11

@Controller & @RestController

@ResponseBody

该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。使用此注解此次请求将不再走视图处理器,而是直接将此响应结果写入到输入流中,其效果等同于使用response对象输出指定格式的数据。

@Controller @Service @Compoent

spring在启动时,有一个非常核心的类ConfigurationClassPostProcessor会对类路径下的所以类进行扫描,将符合条件的bean扫描出来添加到beanDefinitionMap集合中,方便接下来的实例化。

@Controller

如果不使用springMVC时,三者使用其实是没有什么差别的,但如果使用了springMVC,@Controller就被赋予了特殊的含义。

spring会遍历上面扫描出来的所有bean,过滤出那些添加了注解@Controller的bean,将Controller中所有添加了注解@RequestMapping的方法解析出来封装成RequestMappingInfo存储到RequestMappingHandlerMapping中的mappingRegistry。后续请求到达时,会从mappingRegistry中查找能够处理该请求的方法。

@RestController

@Controller + @ResponseBody

2022-07-15

net.sf.ezmorph.bean.MorphDynaBean是什么?

net.sf.json就是一个类似于fastjson的一个json解析框架,这个库有点老了,现在应该没有人推荐了,所以其实今天这个问题就没必要记录了。但是还是看一下这个问题。

2022-07-27

2022-07-28

依赖的版本不一致

一般都是因为自定义版本导致的,而有些依赖会使用spring中写好的版本,所以一般这种情况就更改spring定制的版本号即可,更改就是重新写个全局版本号,会覆盖掉之前的。

2022-07-29 设计模式六大基本原则

单一职责原则 Single Responsibility Principle

There should never be more than one reason for a class to change。应该有且仅有一个原因引起类的变更。

意思也很明显,一个类应该有且只有一个引起它变化的原因。

实际案例: 手机Class V1:MobileClass, 包含了所有功能,charge(), ringUp(), GPU(), CPU(), RAM(), ROM() V2: BasicProperty, GPU(), CPU(), RAM(), ROM(); BasicFunction, charge(), ringUp() V3: BasicProperty, GPU(), CPU(), RAM(), ROM(); ExtendProperty(), Pixel(); BasicFunction, charge(), ringUp(); ExtendFunction, playGame();

没有最好的设计,只有最适合的设计。

2022-07-30 设计模式六大基本原则

里氏替换原则 Liskov Substitution Principle

子类对象能够替换父类对象,而程序逻辑不变。

有两种情况,使用共享方法或者是为了多态。

  1. 共享方法:子类继承父类为了方法重用,则子类不应该去改变父类中的共享方法。子类和父类都可以实例化,如果子类复写父类的共享类,则违反了LSP,子类对象不能够替换父类对象,逻辑有可能不一致。
  2. 多态:如果继承为了多态,则应该将父类方法设为抽象类或者接口,这样子类重新定义父类的方法,父类不能实例化,替换的时候不会造成逻辑上的不一致。

如何符合LSP:尽量不要从可实例化的父类中继承,而是要使用基于抽象类和接口的继承。

2022-07-31

多态

2023-04-10 三次握手

重启每日一问的问题,同步更新微信

首先先明确一下三次握手的流程:


shake hands1: client send [SYN, SEQ=X] -> server
shake hands2: server send [SYN, ACK=X+1, SEQ=Y] -> client
shake hands3: client send [ACK=Y+1, SEQ=Z] -> server


接下来开始使用wireshark进行抓包,查看抓包中的交互信息,下面以www.baidu.com为目标进行抓包。通过ping查看www.baidu.com的真正ip为110.242.68.4,通过wireshark的过滤条件src host 110.242.68.4 or dst host 110.242.68.4 来过滤数据包。

three_hands_all

Shake hands 1

可以看到前三个请求都为TCP的请求,就是我们所说的握手过程,只有在握手之后才能进行真正的http的请求。

three_hands_1

可以看到第一次握手中客户端源端口61539向服务器目标端口443端口进行SYN的请求,SYN=1,ACK=0表示连接请求报文段。

Shake hands 2

在第二次握手的时候可以看到SYN=1,ACK=1表示服务器同意客户端的连接请求。我们也可以看到seq+1。

three_hands_3

Shake hands 3

第三次握手,客户端发送ACK=1给服务端,此时TCP连接成功,开始发送和接收数据。

2023-04-11 四次挥手

上面的三次握手学完之后,相信对整个TCP的连接和wireshark的使用有了基本的了解。下面简单看一下四次挥手的过程即可。


four waves 1: client send [FIN, ACK, Seq=X, ACK=Y] to server
four waves 2: server send [ACK, Seq=Y, Ack=X+1] to client four waves 3: server send [FIN, ACK, Seq=Z, Ack=X+1] to client four waves 4: client send [ACK, Seq=X+1, Ack=Z+1] to server


2023-04-13 IOC - Inversion of Control

资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

2023-04-14 Nginx 配置项

  1. tcp_nodelay

Nagle Algorithm: John Nagle的名字来命名的,John Nagle在1984年首次用这个算法来尝试解决福特汽车公司的网络拥塞问题(RFC 896)。如果每次发送一个1 byte的数据包,实际大小需要40(20ip header bytes + 20 tcp header bytes) + 1 byte = 41bytes,Nagle算法解决了该问题,如果包的大小满足MSS,那么可以立即发送,否则放入缓冲区,等到已经发送的包被确认了之后继续发送。

DelayedAcknowledgment: 如果需要单独确认每个包的大小的话,那么整个网络当中将充斥着无数的ACK,降低网络性能,DelayedAcknowledgment规定: 不再针对单个包发送ACK确认,而是一次确认两个包,或者在发送相应数据的时候捎带这发送ACK,又或者出发超时时间后再发送ACK。

上述的两个解决网络性能问题的方法如果在一起使用,会触发延迟问题,如果TCP client端启用了Nagle Algorithm, Server启用 Delayed ACK,并且发送的数据包比较小,Client端需要等待Server端对上一个packet的Ack才能发送当前Packet,Server延迟发送Ack,那整个通信将会被延迟。

  • 数据量小,交互多的情况需禁用Nagle算法和Delay,TCP_NODELAY: on
  • 数据量大,交互少需要开启,这种情况典型的应用是文件服务器
  • 仅长连接使用
  1. tcp_nopush

tcp_nopush就是开启linux中的TCP_CORK(塞子), 类似于在发送数据管道处插一个cork,阻塞所有数据,直到取消cork,全部发送阻塞数据。

tcp_nopush和sendfile一起使用。

  1. sendfile

正常网络文件传输过程:

file -> 硬盘 -> kernel buffer -> user buffer -> kernel socket buffer -> 协议栈

senfile网络文件传输过程:

file -> 硬盘 -> kernel buffer(快速拷贝到kernel socket buffer) -> 协议栈

性能提升

https://www.cnblogs.com/wajika/p/6573014.html

  1. lua_shared_dict access 10m