第一題
請問以下代碼輸出的結(jié)果是什么心剥?
a. true true
b. false false
c. true false
d. false true
import com.google.common.collect.Sets;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.util.Set;
public class Demo {
@Getter
@Setter
public static class Father {
private Long id;
}
@Data
public static class Son extends Father {
private String name;
}
public static void main(String[] args) {
Set<Father> set = Sets.newHashSet();
Son s1 = new Son();
s1.setId(1L);
s1.setName("1");
System.out.println(set.add(s1));
Son s2 = new Son();
s2.setId(2L);
s2.setName("1");
System.out.println(set.add(s2));
}
}
答案:c. true false
第一個(gè)輸出為true無需多言
第二個(gè)輸出為何為false第股?
認(rèn)知中倦踢,s1和s2的id屬性值不同
先查下@Data的注釋
/**
* Generates getters for all fields, a useful toString method, and hashCode and equals implementations that check
* all non-transient fields. Will also generate setters for all non-final fields, as well as a constructor.
* <p>
* Equivalent to {@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
* <p>
* Complete documentation is found at <a >the project lombok features page for @Data</a>.
*
* @see Getter
* @see Setter
* @see RequiredArgsConstructor
* @see ToString
* @see EqualsAndHashCode
* @see lombok.Value
*/
@Data等價(jià)于組合使用
@Setter @Getter @RequiredArgsConstructor @ToString @EqualsAndHashCode
來看下@EqualsAndHashCode的源碼中的callSuper()方法
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {
/**
* Call on the superclass's implementations of {@code equals} and {@code hashCode} before calculating
* for the fields in this class.
* <strong>default: false</strong>
*/
boolean callSuper() default false;
}
可以知道,只添加@Data注解的類翻默,默認(rèn)不會調(diào)用父類的equals/hashCode方法
上面的例子中辆童,在比較s1和s2的時(shí)候,只比較了name字段飒责,發(fā)現(xiàn)相同赘娄,故s2不會被加入Set中。
使用IDEA的小伙伴宏蛉,當(dāng)在子類使用了@Data后遣臼,應(yīng)該會看到這個(gè)提示
提示說明了,@Data帶來的@EqualsAndHashCode拾并,在生成equals/hashCode方法時(shí)揍堰,默認(rèn)不調(diào)用其父類的equals/hashCode方法
即使它的父類不是java.lang.Object
并且建議你顯示添加@EqualsAndHashCode(callSuper = false)鹏浅,證明你確實(shí)不打算調(diào)用父類的方法是(intentional,故意的)屏歹,以消除這個(gè)泛黃的提示
至于為什么@EqualsAndHashCode要這么做隐砸?
你想啊,當(dāng)你寫一個(gè)類西采,默認(rèn)繼承java.lang.Object
當(dāng)你加了@EqualsAndHashCode注解凰萨,若是默認(rèn)調(diào)用了父類(java.lang.Object)的equals/hashCode方法,那還有意義嗎械馆?
Lombok不會幫你去判斷這個(gè)類的父類是不是java.lang.Object胖眷,直接默認(rèn)不調(diào)用父類完事兒
當(dāng)然這也延伸出一種使用標(biāo)準(zhǔn),就是使用@Data的類霹崎,不要有繼承關(guān)系
但本質(zhì)上珊搀,是要學(xué)會自己用
——魯迅(并沒有說過)
第二題
接下來,手動(dòng)在Son類加上@EqualsAndHashCode(callSuper = true)尾菇,示意要調(diào)用父類的方法境析,并稍微修改了屬性值
請問以下代碼輸出的結(jié)果是什么?
a. true true
b. false false
c. true false
d. false true
import com.google.common.collect.Sets;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import java.util.Set;
public class Demo2 {
@Getter
@Setter
public static class Father {
private Long id;
}
@EqualsAndHashCode(callSuper = true)
@Data
public static class Son extends Father {
private String name;
}
public static void main(String[] args) {
Set<Father> set = Sets.newHashSet();
Son s1 = new Son();
s1.setId(1L);
s1.setName("1");
System.out.println(set.add(s1));
Son s2 = new Son();
s2.setId(1L);
s2.setName("1");
System.out.println(set.add(s2));
}
}
答案:a. true true
第一個(gè)輸出true無需多言
第二個(gè)派诬,為何是true劳淆?兩個(gè)對象的id和name屬性都相同,不是調(diào)用父類的equals/hashCode方法了嗎默赂?
嗯沛鸵,問題就在這,你看父類的equals/hashCode方法重寫了嗎缆八?
沒重寫曲掰,所以父類調(diào)用的實(shí)際是java.lang.Object的equals/hashCode方法
public class Object {
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();
}
總結(jié):
Lombok確實(shí)很好用,但也有不少大佬說Lombok帶來了很多坑奈辰。
使用Lombok栏妖,代碼雖然簡化了,但肯定會隱藏一些細(xì)節(jié)奖恰。這些細(xì)節(jié)對于有一定資歷的程序員來說是爛熟于心的吊趾,但對于新入行的同學(xué),以及剛接觸Lombok的同僚來說確實(shí)不太友好瑟啃。
像我目前的項(xiàng)目趾徽,如果沒有l(wèi)ombok,每寫/改一個(gè)字段就要連帶一個(gè)getter和setter翰守,相當(dāng)于工作量直接翻三倍。
另一方面疲酌,Lombok的@Builder方法我個(gè)人就覺得很雞肋
不僅影響了這個(gè)類的構(gòu)造方法(@Builder的實(shí)現(xiàn)需要依賴于這個(gè)類必須有個(gè)全參構(gòu)造方法蜡峰,而類的構(gòu)造方法有可能會影響到其他的一些中間件使用)
而且跟一行行的Set屬性沒什么本質(zhì)區(qū)別了袁,并不能節(jié)約多少代碼
(當(dāng)然業(yè)務(wù)不同吧,也不否認(rèn)首次用@Builder敲代碼會很爽湿颅,但爽過之后是要還債的)
看了下@Builder實(shí)現(xiàn)载绿,還多用了個(gè)中間類去承載屬性值,之后統(tǒng)一通過構(gòu)造方法注入油航,站在執(zhí)行方法棧的角度看也會覺得是多此一舉
個(gè)人認(rèn)為崭庸,輪子坑不坑,好不好用是一方面谊囚,自己對這些輪子的了解程度如何也占很大比重怕享。