java實(shí)戰(zhàn)技巧之if-else代碼優(yōu)化技巧大全
前言
在實(shí)際的業(yè)務(wù)開發(fā)當(dāng)中,經(jīng)常會(huì)遇到復(fù)雜的業(yè)務(wù)邏輯,可能部分同學(xué)實(shí)現(xiàn)出來的代碼并沒有什么問題,但是代碼的可讀性很差。本篇文章主要總結(jié)一下自己在實(shí)際開發(fā)中如何避免大面積的 if-else 代碼塊的問題。補(bǔ)充說明一點(diǎn),不是說 if-else 不好,而是多層嵌套的 if-else 導(dǎo)致代碼可讀性差、維護(hù)成本高等問題。
現(xiàn)有如下一段示例代碼,部分優(yōu)化技巧是根據(jù)這段代碼進(jìn)行的
public class BadCodeDemo {
private void getBadCodeBiz(Integer city, List<TestCodeData> newDataList, List<TestCodeData> oldDataList) {
if (city != null) {
if (newDataList != null && newDataList.size() > 0) {
TestCodeData newData = newDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).findFirst().orElse(null);
if (newData != null) {
newData.setCity(city);
}
}
} else {
if (oldDataList != null && newDataList != null) {
List<TestCodeData> oldCollect = oldDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).collect(Collectors.toList());
List<TestCodeData> newCollect = newDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).collect(Collectors.toList());
if (newCollect != null && newCollect.size() > 0 && oldCollect != null && oldCollect.size() > 0) {
for (TestCodeData newPO : newCollect) {
if (newPO.getStartTime() == 0 && newPO.getEndTime() == 12) {
TestCodeData po = oldCollect.stream().filter(p -> p.getStartTime() == 0
&& (p.getEndTime() == 12 || p.getEndTime() == 24)).findFirst().orElse(null);
if (po != null) {
newPO.setCity(po.getCity());
}
} else if (newPO.getStartTime() == 12 && newPO.getEndTime() == 24) {
TestCodeData po = oldCollect.stream().filter(
p -> (p.getStartTime() == 12 || p.getStartTime() == 0)
&& p.getEndTime() == 24).findFirst().orElse(null);
if (po != null) {
newPO.setCity(po.getCity());
}
} else if (newPO.getStartTime() == 0 && newPO.getEndTime() == 24) {
TestCodeData po = oldCollect.stream().filter(
p -> p.getStartTime() == 0 && p.getEndTime() == 24).findFirst().orElse(null);
if (po == null) {
po = oldCollect.stream().filter(
p -> p.getStartTime() == 0 && p.getEndTime() == 12).findFirst().orElse(null);
}
if (po == null) {
po = oldCollect.stream().filter(
p -> p.getStartTime() == 12 && p.getEndTime() == 24).findFirst().orElse(null);
}
if (po != null) {
newPO.setCity(po.getCity());
}
} else if (newPO.getTimeUnit().equals(Integer.valueOf(1))) {
TestCodeData po = oldCollect.stream().filter(
e -> e.getTimeUnit().equals(Integer.valueOf(1))).findFirst().orElse(null);
if (po != null) {
newPO.setCity(po.getCity());
}
}
}
}
}
}
}
}技巧一:提取方法,拆分邏輯
比如上面這段代碼中
if(null != city) {
} else {
}這里可以拆分成兩段邏輯,核心思想就是邏輯單元最小化,然后合并邏輯單元。
private void getCityNotNull(Integer city, List<TestCodeData> newDataList) {
if (newDataList != null && newDataList.size() > 0) {
TestCodeData newData = newDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).findFirst().orElse(null);
if (newData != null) {
newData.setCity(city);
}
}
}
// 合并邏輯流程
private void getBadCodeBiz(Integer city, List<TestCodeData> newDataList, List<TestCodeData> oldDataList) {
if (city != null) {
this.getCityNull(city, newDataList);
} else {
//此處代碼省略
}
}技巧二:分支邏輯提前return
比如 技巧一 中的 getCityNull 方法,我們可以這樣寫
public void getCityNotNull(Integer city, List<TestCodeData> newDataList) {
if (CollectionUtils.isEmpty(newDataList)) {
// 提前判斷,返回業(yè)務(wù)邏輯
return;
}
TestCodeData newData = newDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).findFirst().orElse(null);
if (null != newData) {
newData.setCity(city);
}
}技巧三:枚舉
經(jīng)過 技巧一 和 技巧二 的優(yōu)化,文章開頭的這段代碼被優(yōu)化成如下所示:
public class BadCodeDemo {
public void getBadCodeBiz(Integer city, List<TestCodeData> newDataList, List<TestCodeData> oldDataList) {
if (city != null) {
this.getCityNotNull(city, newDataList);
} else {
this.getCityNull(newDataList, oldDataList);
}
}
private void getCityNotNull(Integer city, List<TestCodeData> newDataList) {
if (CollectionUtils.isEmpty(newDataList)) {
// 提前判斷,返回業(yè)務(wù)邏輯
return;
}
TestCodeData newData = newDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).findFirst().orElse(null);
if (null != newData) {
newData.setCity(city);
}
}
private void getCityNull(List<TestCodeData> newDataList, List<TestCodeData> oldDataList) {
// 提前判斷,返回業(yè)務(wù)邏輯
if (CollectionUtils.isEmpty(oldDataList) && CollectionUtils.isEmpty(newDataList)) {
return;
}
List<TestCodeData> oldCollect = oldDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).collect(Collectors.toList());
List<TestCodeData> newCollect = newDataList.stream().filter(p -> {
if (p.getIsHoliday() == 1) {
return true;
}
return false;
}).collect(Collectors.toList());
// 提前判斷,返回業(yè)務(wù)邏輯
if (CollectionUtils.isEmpty(newCollect) && CollectionUtils.isEmpty(oldCollect)) {
return;
}
for (TestCodeData newPO : newCollect) {
if (newPO.getStartTime() == 0 && newPO.getEndTime() == 12) {
TestCodeData po = oldCollect.stream().filter(p -> p.getStartTime() == 0
&& (p.getEndTime() == 12 || p.getEndTime() == 24)).findFirst().orElse(null);
if (po != null) {
newPO.setCity(po.getCity());
}
} else if (newPO.getStartTime() == 12 && newPO.getEndTime() == 24) {
TestCodeData po = oldCollect.stream().filter(
p -> (p.getStartTime() == 12 || p.getStartTime() == 0)
&& p.getEndTime() == 24).findFirst().orElse(null);
if (po != null) {
newPO.setCity(po.getCity());
}
} else if (newPO.getStartTime() == 0 && newPO.getEndTime() == 24) {
TestCodeData po = oldCollect.stream().filter(
p -> p.getStartTime() == 0 && p.getEndTime() == 24).findFirst().orElse(null);
if (po == null) {
po = oldCollect.stream().filter(
p -> p.getStartTime() == 0 && p.getEndTime() == 12).findFirst().orElse(null);
}
if (po == null) {
po = oldCollect.stream().filter(
p -> p.getStartTime() == 12 && p.getEndTime() == 24).findFirst().orElse(null);
}
if (po != null) {
newPO.setCity(po.getCity());
}
} else if (newPO.getTimeUnit().equals(Integer.valueOf(1))) {
TestCodeData po = oldCollect.stream().filter(
e -> e.getTimeUnit().equals(Integer.valueOf(1))).findFirst().orElse(null);
if (po != null) {
newPO.setCity(po.getCity());
}
}
}
}
}現(xiàn)在利用 枚舉 來優(yōu)化 getCityNull 方法中的 for 循環(huán)部分代碼,我們可以看到這段代碼中有4段邏輯,總體形式如下:
if (newPO.getStartTime() == 0 && newPO.getEndTime() == 12) {
//第一段邏輯
} else if (newPO.getStartTime() == 12 && newPO.getEndTime() == 24) {
//第二段邏輯
} else if (newPO.getStartTime() == 0 && newPO.getEndTime() == 24) {
//第三段邏輯
} else if (newPO.getTimeUnit().equals(Integer.valueOf(1))) {
//第四段邏輯
} 按照這個(gè)思路利用枚舉進(jìn)行二次優(yōu)化,將其中的邏輯封裝到枚舉類中:
public enum TimeEnum {
AM("am", "上午") {
@Override
public void setCity(TestCodeData data, List<TestCodeData> oldDataList) {
TestCodeData po = oldDataList.stream().filter(p -> p.getStartTime() == 0
&& (p.getEndTime() == 12 || p.getEndTime() == 24)).findFirst().orElse(null);
if (null != po) {
data.setCity(po.getCity());
}
}
},
PM("pm", "下午") {
@Override
public void setCity(TestCodeData data, List<TestCodeData> oldCollect) {
TestCodeData po = oldCollect.stream().filter(
p -> (p.getStartTime() == 12 || p.getStartTime() == 0)
&& p.getEndTime() == 24).findFirst().orElse(null);
if (po != null) {
data.setCity(po.getCity());
}
}
},
DAY("day", "全天") {
@Override
public void setCity(TestCodeData data, List<TestCodeData> oldCollect) {
TestCodeData po = oldCollect.stream().filter(
p -> p.getStartTime() == 0 && p.getEndTime() == 24).findFirst().orElse(null);
if (po == null) {
po = oldCollect.stream().filter(
p -> p.getStartTime() == 0 && p.getEndTime() == 12).findFirst().orElse(null);
}
if (po == null) {
po = oldCollect.stream().filter(
p -> p.getStartTime() == 12 && p.getEndTime() == 24).findFirst().orElse(null);
}
if (po != null) {
data.setCity(po.getCity());
}
}
},
HOUR("hour", "小時(shí)") {
@Override
public void setCity(TestCodeData data, List<TestCodeData> oldCollect) {
TestCodeData po = oldCollect.stream().filter(
e -> e.getTimeUnit().equals(Integer.valueOf(1))).findFirst().orElse(null);
if (po != null) {
data.setCity(po.getCity());
}
}
};
public abstract void setCity(TestCodeData data, List<TestCodeData> oldCollect);
private String code;
private String desc;
TimeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}然后 getCityNull 方法中 for 循環(huán)部分邏輯如下:
for (TestCodeData data : newCollect) {
if (data.getStartTime() == 0 && data.getEndTime() == 12) {
TimeEnum.AM.setCity(data, oldCollect);
} else if (data.getStartTime() == 12 && data.getEndTime() == 24) {
TimeEnum.PM.setCity(data, oldCollect);
} else if (data.getStartTime() == 0 && data.getEndTime() == 24) {
TimeEnum.DAY.setCity(data, oldCollect);
} else if (data.getTimeUnit().equals(Integer.valueOf(1))) {
TimeEnum.HOUR.setCity(data, oldCollect);
}
}其實(shí)在這個(gè)業(yè)務(wù)場(chǎng)景中使用枚舉并不是特別合適,如果在遍歷對(duì)象時(shí),我們就知道要執(zhí)行哪個(gè)枚舉類型,此時(shí)最合適,偽代碼如下:
for (TestCodeData data : newCollect) {
String code = "am"; // 這里假設(shè) code 變量是從 data 中獲取的
TimeEnum.valueOf(code).setCity(data, oldCollect);
}技巧四:函數(shù)式接口
業(yè)務(wù)場(chǎng)景描述:比如讓你做一個(gè)簡單的營銷拉新活動(dòng),這個(gè)活動(dòng)投放到不同的渠道,不同渠道過來的用戶獎(jiǎng)勵(lì)不一樣。現(xiàn)假設(shè)在 頭條、微信 等渠道都投放了該活動(dòng)。此時(shí)你的代碼可能會(huì)寫出如下形式:
@RestController
@RequestMapping("/activity")
public class ActivityController {
@Resource
private AwardService awardService;
@PostMapping("/reward")
public void reward(String userId, String source) {
if ("toutiao".equals(source)) {
awardService.toutiaoReward(userId);
} else if ("wx".equals(source)) {
awardService.wxReward(userId);
}
}
}
@Service
public class AwardService {
private static final Logger log = LoggerFactory.getLogger(AwardService.class);
public Boolean toutiaoReward(String userId) {
log.info("頭條渠道用戶{}獎(jiǎng)勵(lì)50元紅包!", userId);
return Boolean.TRUE;
}
public Boolean wxReward(String userId) {
log.info("微信渠道用戶{}獎(jiǎng)勵(lì)100元紅包!", userId);
return Boolean.TRUE;
}
}看完這段代碼,邏輯上是沒有什么問題的。但它有一個(gè)隱藏的缺陷,如果后期又增加很多渠道的時(shí)候,你該怎么辦?繼續(xù) else if 嗎?其實(shí)我們可以利用函數(shù)式接口優(yōu)化,當(dāng)然設(shè)計(jì)模式也可以優(yōu)化。這里我只是舉例使用一下函數(shù)式接口的使用方式。
@RestController
@RequestMapping("/activity")
public class ActivityController {
@Resource
private AwardService awardService;
@PostMapping("/reward")
public void reward(String userId, String source) {
awardService.getRewardResult(userId, source);
}
}
@Service
public class AwardService {
private static final Logger log = LoggerFactory.getLogger(AwardService.class);
private Map<String, BiFunction<String, String, Boolean>> sourceMap = new HashMap<>();
@PostConstruct
private void dispatcher() {
sourceMap.put("wx", (userId, source) -> this.wxReward(userId));
sourceMap.put("toutiao", (userId, source) -> this.toutiaoReward(userId));
}
public Boolean getRewardResult(String userId, String source) {
BiFunction<String, String, Boolean> result = sourceMap.get(source);
if (null != result) {
return result.apply(userId, source);
}
return Boolean.FALSE;
}
private Boolean toutiaoReward(String userId) {
log.info("頭條渠道用戶{}獎(jiǎng)勵(lì)50元紅包!", userId);
return Boolean.TRUE;
}
private Boolean wxReward(String userId) {
log.info("微信渠道用戶{}獎(jiǎng)勵(lì)100元紅包!", userId);
return Boolean.TRUE;
}
}針對(duì)一些復(fù)雜的業(yè)務(wù)場(chǎng)景,業(yè)務(wù)參數(shù)很多時(shí),可以利用 @FunctionalInterface 自定義函數(shù)式接口來滿足你的業(yè)務(wù)需求,使用原理和本例并無差別。
技巧五:設(shè)計(jì)模式
設(shè)計(jì)模式對(duì)于if-else的優(yōu)化,我個(gè)人覺得有些重,但是也是一種優(yōu)化方式。設(shè)計(jì)模式適合使用在大的業(yè)務(wù)流程和場(chǎng)景中使用,針對(duì)代碼塊中的if-else邏輯優(yōu)化不推薦使用。
常用的設(shè)計(jì)模式有:
- 策略模式
- 模板方法
- 工廠模式
- 單例模式
還是以上面的營銷拉新活動(dòng)為例來說明如何使用。
使用技巧一:工廠模式+抽象類
- 定義抽象業(yè)務(wù)接口
public abstract class AwardAbstract {
public abstract Boolean award(String userId);
}- 定義具體業(yè)務(wù)實(shí)現(xiàn)類
// 頭條渠道發(fā)放獎(jiǎng)勵(lì)業(yè)務(wù)
public class TouTiaoAwardService extends AwardAbstract {
@Override
public Boolean award(String userId) {
log.info("頭條渠道用戶{}獎(jiǎng)勵(lì)50元紅包!", userId);
return Boolean.TRUE;
}
}
// 微信渠道發(fā)放獎(jiǎng)勵(lì)業(yè)務(wù)
public class WeChatAwardService extends AwardAbstract {
@Override
public Boolean award(String userId) {
log.info("微信渠道用戶{}獎(jiǎng)勵(lì)100元紅包!", userId);
return Boolean.TRUE;
}
}- 利用工廠模式獲取實(shí)例對(duì)象
public class AwardFactory {
public static AwardAbstract getAwardInstance(String source) {
if ("toutiao".equals(source)) {
return new TouTiaoAwardService();
} else if ("wx".equals(source)) {
return new WeChatAwardService();
}
return null;
}
}- 業(yè)務(wù)入口處根據(jù)不同渠道執(zhí)行不同的發(fā)放邏輯
@PostMapping("/reward2")
public void reward2(String userId, String source) {
AwardAbstract instance = AwardFactory.getAwardInstance(source);
if (null != instance) {
instance.award(userId);
}
}使用技巧二:策略模式+模板方法+工廠模式+單例模式
還是以營銷拉新為業(yè)務(wù)場(chǎng)景來說明,這個(gè)業(yè)務(wù)流程再增加一些復(fù)雜度,比如發(fā)放獎(jiǎng)勵(lì)之前要進(jìn)行 身份驗(yàn)證、風(fēng)控驗(yàn)證 等一些列的校驗(yàn),此時(shí)你的業(yè)務(wù)流程該如何實(shí)現(xiàn)更清晰簡潔呢!
- 定義業(yè)務(wù)策略接口
/** 策略業(yè)務(wù)接口 */
public interface AwardStrategy {
/**
* 獎(jiǎng)勵(lì)發(fā)放接口
*/
Map<String, Boolean> awardStrategy(String userId);
/**
* 獲取策略標(biāo)識(shí),即不同渠道的來源標(biāo)識(shí)
*/
String getSource();
}- 定義獎(jiǎng)勵(lì)發(fā)放模板流程
public abstract class BaseAwardTemplate {
private static final Logger log = LoggerFactory.getLogger(BaseAwardTemplate.class);
//獎(jiǎng)勵(lì)發(fā)放模板方法
public Boolean awardTemplate(String userId) {
this.authentication(userId);
this.risk(userId);
return this.awardRecord(userId);
}
//身份驗(yàn)證
protected void authentication(String userId) {
log.info("{} 執(zhí)行身份驗(yàn)證!", userId);
}
//風(fēng)控
protected void risk(String userId) {
log.info("{} 執(zhí)行風(fēng)控校驗(yàn)!", userId);
}
//執(zhí)行獎(jiǎng)勵(lì)發(fā)放
protected abstract Boolean awardRecord(String userId);
}- 實(shí)現(xiàn)不同渠道的獎(jiǎng)勵(lì)業(yè)務(wù)
@Slf4j
@Service
public class ToutiaoAwardStrategyService extends BaseAwardTemplate implements AwardStrategy {
/**
* 獎(jiǎng)勵(lì)發(fā)放接口
*/
@Override
public Boolean awardStrategy(String userId) {
return super.awardTemplate(userId);
}
@Override
public String getSource() {
return "toutiao";
}
/**
* 具體的業(yè)務(wù)獎(jiǎng)勵(lì)發(fā)放實(shí)現(xiàn)
*/
@Override
protected Boolean awardRecord(String userId) {
log.info("頭條渠道用戶{}獎(jiǎng)勵(lì)50元紅包!", userId);
return Boolean.TRUE;
}
}
@Slf4j
@Service
public class WeChatAwardStrategyService extends BaseAwardTemplate implements AwardStrategy {
/**
* 獎(jiǎng)勵(lì)發(fā)放接口
*/
@Override
public Boolean awardStrategy(String userId) {
return super.awardTemplate(userId);
}
@Override
public String getSource() {
return "wx";
}
/***
* 具體的業(yè)務(wù)獎(jiǎng)勵(lì)發(fā)放實(shí)現(xiàn)
*/
@Override
protected Boolean awardRecord(String userId) {
log.info("微信渠道用戶{}獎(jiǎng)勵(lì)100元紅包!", userId);
return Boolean.TRUE;
}
}- 定義工廠方法,對(duì)外統(tǒng)一暴露業(yè)務(wù)調(diào)用入口
@Component
public class AwardStrategyFactory implements ApplicationContextAware {
private final static Map<String, AwardStrategy> MAP = new HashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, AwardStrategy> beanTypeMap = applicationContext.getBeansOfType(AwardStrategy.class);
beanTypeMap.values().forEach(strategyObj -> MAP.put(strategyObj.getSource(), strategyObj));
}
/**
* 對(duì)外統(tǒng)一暴露的工廠方法
*/
public Boolean getAwardResult(String userId, String source) {
AwardStrategy strategy = MAP.get(source);
if (Objects.isNull(strategy)) {
throw new RuntimeException("渠道異常!");
}
return strategy.awardStrategy(userId);
}
/**
* 靜態(tài)內(nèi)部類創(chuàng)建單例工廠對(duì)象
*/
private static class CreateFactorySingleton {
private static AwardStrategyFactory factory = new AwardStrategyFactory();
}
public static AwardStrategyFactory getInstance() {
return CreateFactorySingleton.factory;
}
}- 業(yè)務(wù)入口方法
@RestController
@RequestMapping("/activity")
public class ActivityController {
@PostMapping("/reward3")
public void reward3(String userId, String source) {
AwardStrategyFactory.getInstance().getAwardResult(userId, source);
}
}假如發(fā)起請(qǐng)求: POST http://localhost:8080/activity/reward3?userId=fei&source=wx
2022-02-20 12:23:27.716 INFO 20769 --- [nio-8080-exec-1] c.a.c.e.o.c.p.s.BaseAwardTemplate : fei 執(zhí)行身份驗(yàn)證! 2022-02-20 12:23:27.719 INFO 20769 --- [nio-8080-exec-1] c.a.c.e.o.c.p.s.BaseAwardTemplate : fei 執(zhí)行風(fēng)控校驗(yàn)! 2022-02-20 12:23:27.719 INFO 20769 --- [nio-8080-exec-1] a.c.e.o.c.p.s.WeChatAwardStrategyService : 微信渠道用戶fei獎(jiǎng)勵(lì)100元紅包!
其他技巧
- 使用三目運(yùn)算符
- 相同業(yè)務(wù)邏輯提取復(fù)用
寫在最后
不論使用那種技巧,首先是我們?cè)跇I(yè)務(wù)代碼開發(fā)過程中一定要多思考,將復(fù)雜的業(yè)務(wù)邏輯能通過簡潔的代碼表現(xiàn)出來,這才是你的核心能力之一,而不是一個(gè) curd boy。與君共勉,共同進(jìn)步!
到此這篇關(guān)于java實(shí)戰(zhàn)技巧之if-else代碼優(yōu)化技巧的文章就介紹到這了,更多相關(guān)java if-else代碼優(yōu)化技巧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis-Plus updateById不更新null值的方法解決
用Mybatis-Plus的updateById()來更新數(shù)據(jù)時(shí),無法將字段設(shè)置為null值,更新后數(shù)據(jù)還是原來的值,本文就來詳細(xì)的介紹一下解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
mybatis?plus樂觀鎖及實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了mybatis?plus樂觀鎖及實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
java語言描述Redis分布式鎖的正確實(shí)現(xiàn)方式
這篇文章主要介紹了java語言描述Redis分布式鎖的正確實(shí)現(xiàn)方式,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12
SpringBoot 錯(cuò)誤處理機(jī)制與自定義錯(cuò)誤處理實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringBoot 錯(cuò)誤處理機(jī)制與自定義錯(cuò)誤處理實(shí)現(xiàn)詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
java中實(shí)體類實(shí)現(xiàn)時(shí)間日期自動(dòng)轉(zhuǎn)換方式
這篇文章主要介紹了java中實(shí)體類實(shí)現(xiàn)時(shí)間日期自動(dòng)轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06

