一,FastJson反序列化和lombock注解
1,报错信息:
com.alibaba.fastjson.JSONException: default constructor not found
2,问题描述:
lombock的@Builder注解会自动生成全参构造,从而导致默认的无参数构造丢失,如果此时结合JSON的反序列化JSON.parseObject(jsonString,calss);方法就会报错。
3,解决方式:
使用@Builder注解时,同时添加无参和有参构造
com.alibaba.fastjson.JSONException: default constructor not found
lombock的@Builder注解会自动生成全参构造,从而导致默认的无参数构造丢失,如果此时结合JSON的反序列化JSON.parseObject(jsonString,calss);方法就会报错。
使用@Builder注解时,同时添加无参和有参构造
异常就是有异于常态,和正常情况不一样,有错误出现。在java中,阻止当前方法或作用域的情况,称之为异常。
RuntimeException类极其子类表示JVM在运行期间可能出现的错误。编译器不会检查此类异常,并且不要求处理异常,比如用空值对象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。RuntimeException极其子类之外的异常。编译器会检查此类异常,如果程序中出现此类异常,比如说IOException,必须对该异常进行处理,要么使用try-catch捕获,要么使用throws语句抛出,否则编译不通过。(不能只使用throw并没有处理异常)Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。
虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。
@FunctionalInterface修饰函数式接口的,要求接口中的抽象方法只有一个。 这个注解往往会和 lambda 表达式一起出现。
假设两个人A、B两个情报员,需要通过书信交流情报。AB双方想要真正交流情报,首先需要建立交流渠道、需要确保自己能发(SYN)且别人能收(ACK):
二次握手:
A:“你能收到我写的信吗?”(A:SYN)
B:“我能收到你写的信!你能收到我写的信吗?”(B:ACK-B:SYN)
三次握手:
A:“你能收到我写的信吗?”(A:SYN)
B:“我能收到你写的信!你能收到我写的信吗?”(B:ACK-B:SYN)
A:“我也能收到!”(A:ACK)
四次握手:
A:“你能收到我写的信吗?”(A:SYN)
B:“我能收到你写的信!”(B:ACK)
B:“你能收到我写的信吗?”(B:SYN)
A:“我也能收到!”(A:ACK)
好的,我们现在解释一下常见的问题。
问题1:为什么TCP二次握手不可以?
根据二次握手中A和B的交流、可以发现A可以确定自己能发(SYN)、B能收(ACK),但是B只能确定自己能发(SYN),A能不能收(ACK)到这就不确定了。试想一下你和你朋友写信,一直没收到朋友的回信,你还会继续写下去吗,你会怀疑自己是不是发的地址不对,或者朋友没有收到信,再说写下去也是白写,平白浪费时间。
问题2:为什么不是四次握手?
根据四次握手中A和B的交流、可以发现A可以确定自己能发(SYN)、B能收(ACK),B也能确定自己能发(SYN),A能收(ACK)到。那为什么不采用四次握手?因为B家没钱,为了节省钱,就写了一封信做了两件事,回答朋友的问题并问出自己的问题。
下面所有案例使用的对象和接口:
public interface TestInterface {
}
@Component
public class TestObject implements TestInterface {
private String name;
private String desc;
public TestObject(){
}
public TestObject(String name){
this.name = name;
}
private TestObject(String name,String desc){
this.desc =desc;
this.name = name;
}
private String testPrivate(String v){
return v;
}
public String testPublic(String v){
return v;
}
}
从结构实现来讲,HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下如所示:
从源码可知,HashMap类中有一个非常重要的字段,就是 Node<K,V>[] table,即哈希桶数组
transient Node<K,V>[] table;
将一个对象的引用复制给另一个对象,一共有三种方式。第一种是直接赋值,第二种方式是浅拷贝,第三种是深拷贝,这三种方式实际上都是为了拷贝对象。
直接赋值是通过=进行赋值操作的,直接赋值对于不可变类而言相当于深拷贝,常见的不可变类八个基本类型的包装类和String类都属于不可变类。
案例1,不可变类的赋值操作:
public static void main(String[] args) {
Integer a = 1;
String b = "1";
Integer c = a;
String d = b;
System.out.println("修改前c:"+b); // 输出 1
System.out.println("修改前d:"+bb);// 输出 1
a = 2;
b = "2";
System.out.println("修改前c:"+b);// 输出 2
System.out.println("修改前d:"+bb);// 输出 2
}
| 修饰符 | 当前类(案例1) | 同一包内(案例2) | 子孙类(案例3) | 子孙类(不同包)(案例4) | 其他包(案例5) |
|---|---|---|---|---|---|
| public | Y | Y | Y | Y | Y |
| protected | Y | Y | Y | Y/N(案例4.1) | N |
| default | Y | Y | Y | N | N |
| private | Y | N | N | N | N |
| 优先级 | 运算符 | 结合性 |
|---|---|---|
| 1 | ()、[]、 . |
从左到右 |
| 2 | ! 、+(正)、 -(负)、 ~、 ++ 、— |
从右向左 |
| 3 | * 、/ 、% |
从左向右 |
| 4 | +(加) 、-(减) |
从左向右 |
| 5 | << 、>>、 >>> |
从左向右 |
| 6 | < 、<= 、> 、>= 、 instanceof |
从左向右 |
| 7 | == 、!= |
从左向右 |
| 8 | & |
从左向右 |
| 9 | ^ |
从左向右 |
| 10 | | |
从左向右 |
| 11 | && |
从左向右 |
| 12 | || |
从左向右 |
| 13 | ?: |
从右向左 |
| 14 | = 、+=、-=、*=、/=、%=、&=、|=、^=、~=、<<=、>>=、>>>= |
从右向左 |
由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。
在阿里集团有很强的影响力,同时为了自身不断优化、发扬开源贡献精神,于2012年开源。
QLExpress脚本引擎被广泛应用在阿里的电商业务场景,具有以下的一些特性: