一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|

服務器之家 - 編程語言 - JAVA教程 - Java和Ceylon對象的構造和驗證

Java和Ceylon對象的構造和驗證

2020-07-05 12:07shanshuiss JAVA教程

這篇文章主要為大家詳細介紹了Java和Ceylon對象的構造和驗證,具有一定的參考價值,感興趣的小伙伴們可以參考一下

當變換Java代碼為Ceylon代碼時,有時候我會遇到一些Java類構造器混淆了驗證與初始化的情形。讓我們使用一個簡單但是人為的代碼例子來說明我想闡述的意思。

一些壞代碼

考慮下面的Java類。(伙計,不要在家里寫這樣的代碼)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Period {
 private final Date startDate;
 private final Date endDate;
 //returns null if the given String
 //does not represent a valid Date
 private Date parseDate(String date) {
  ...
 }
 public Period(String start, String end) {
  startDate = parseDate(start);
  endDate = parseDate(end);
 }
 public boolean isValid() {
  return startDate!=null && endDate!=null;
 }
 public Date getStartDate() {
  if (startDate==null)
   throw new IllegalStateException();
  return startDate;
 }
 public Date getEndDate() {
  if (endDate==null)
   throw new IllegalStateException();
  return endDate;
 }
}

嘿,我之前已經警告過,它是人為的。但是,在實際Java代碼中找個像這樣的東西實際上并非不常見。

這里的問題在于,即使輸入參數(在隱藏的parseDate()方法中)的驗證失敗了,我們還是會獲得一個Period的實例。但是我們獲取的那個Period不是一個“有效的”狀態。嚴格地說,我的意思是什么呢?

好吧,假如一個對象不能有意義地響應公用操作時,我會說它處于一個非有效狀態。在這個例子里,getStartDate() 和getEndDate()會拋出一個IllegalStateException異常,這就是我認為不是“有意義的”一種情況。

從另外一方面來看這個例子,在設計Period時,我們這兒出現了類型安全的失敗。未檢查的異常代表了類型系統中的一個“漏洞”。因此,一個更好的Period的類型安全的設計,會是一個不使用未檢查的異常—在這個例子中意味著不拋出IllegalStateException異常。

(實際上,在真實代碼中,我更有可能遇到一個getStartDate() 方法它不檢查null ,在這個代碼行之后就會導致一個NullPointerException異常,這就更加糟糕了。)

我們能夠很容易地轉換上面的Period類成為Ceylon形式的類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
shared class Period(String start, String end) {
 //returns null if the given String
 //does not represent a valid Date
 Date? parseDate(String date) => ... ;
 value maybeStartDate = parseDate(start);
 value maybeEndDate = parseDate(end);
 shared Boolean valid
  => maybeStartDate exists
  && maybeEndDate exists;
 shared Date startDate {
  assert (exists maybeStartDate);
  return maybeStartDate;
 }
 shared Date endDate {
  assert (exists maybeEndDate);
  return maybeEndDate;
 }
}

當然了,這段代碼也會遇到與原始Java代碼同樣的問題。兩個assert符號沖著我們大喊,在代碼的類型安全中有一個問題。

使Java代碼變得更好

Java里我們怎么改進這段代碼呢?好吧,這兒就是一個例子關于Java飽受詬病的已檢查異常會是一個非常合理的解決方法!我們可以稍微修改下Period來從它的構造器中拋出一個已檢查的異常:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Period {
 private final Date startDate;
 private final Date endDate;
 //throws if the given String
 //does not represent a valid Date
 private Date parseDate(String date)
   throws DateFormatException {
  ...
 }
 public Period(String start, String end)
   throws DateFormatException {
  startDate = parseDate(start);
  endDate = parseDate(end);
 }
 public Date getStartDate() {
  return startDate;
 }
 public Date getEndDate() {
  return endDate;
 }
}

現在,使用這個解決方案,我們就不會獲取一個處于非有效狀態的Period,實例化Period的代碼會由編譯器負責去處理無效輸入的情形,它會捕獲一個DateFormatException異常。

?
1
2
3
4
5
6
7
try {
 Period p = new Period(start, end);
 ...
}
catch (DateFormatException dfe) {
 ...
}

這是一個對已檢查異常不錯的、完美的、正確的使用,不幸的是我幾乎很少看到Java代碼像上面這樣使用已檢查異常。

使Ceylon代碼變得更好

那么Ceylon怎么樣呢?Ceylon沒有已檢查異常,因而我們需要尋找一個不同的解決方式。典型地,在Java調用一個函數會拋出一個已檢查異常的情形中,Ceylon會調用函數返回一個聯合類型。因為,一個類的初始化不返回除了類自己外的任何類型,我們需要提取一些混合的初始化/驗證的邏輯來使其成為一個工廠函數。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//returns DateFormatError if the given
//String does not represent a valid Date
Date|DateFormatError parseDate(String date) => ... ;
shared Period|DateFormatError parsePeriod
  (String start, String end) {
 value startDate = parseDate(start);
 if (is DateFormatError startDate) {
  return startDate;
 }
 value endDate = parseDate(end);
 if (is DateFormatError endDate) {
  return endDate;
 }
 return Period(startDate, endDate);
}
shared class Period(startDate, endDate) {
 shared Date startDate;
 shared Date endDate;
}

根據類型系統,調用者有義務去處理DateFormatError:

?
1
2
3
4
5
6
7
value p = parsePeriod(start, end);
if (is DateFormatError p) {
 ...
}
else {
 ...
}

或者,如果我們不關心給定日期格式的實際問題(這是有可能的,假定我們工作的初始化代碼丟失了那個信息),我們可以使用Null而不是DateFormatError:

?
1
2
3
4
5
6
7
8
9
10
11
12
//returns null if the given String
//does not represent a valid Date
Date? parseDate(String date) => ... ;
shared Period? parsePeriod(String start, String end)
 => if (exists startDate = parseDate(start),
   exists endDate = parseDate(end))
  then Period(startDate, endDate)
  else null;
shared class Period(startDate, endDate) {
 shared Date startDate;
 shared Date endDate;
}

至少可以說,使用工廠函數的方法是優秀的,因為通常來說在驗證邏輯和對象初始化之間它具有更好的隔離。這點在Ceylon中特別有用,在Ceylon中,編譯器在對象初始化邏輯中添加了一些非常嚴厲的限制,以保證對象的所有領域僅被賦值一次。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 美女扒开屁股让我桶免费 | 免费看全黄特黄毛片 | 国产在线麻豆波多野结衣 | 2019男人天堂 | 男人把大ji巴放进男人免费视频 | 护士们的母狗 | 国产精品成人扳一级aa毛片 | 国内精品久久久久影院网站 | 国内在线播放 | 欧美高清videosdesex0 | 成人影院在线观看 | 2014天堂 | 午夜亚洲WWW湿好爽 午夜想想爱午夜剧场 | 欧美福利在线播放 | 被高跟鞋调教丨vk | 国产自产2023最新麻豆 | 特级淫片欧美高清视频蜜桃 | 白丝女榨干蹂躏我 | 俄罗斯大白屁股 | 亚洲 欧美 中文字幕 在线 | 精品国产福利一区二区在线 | 色哟哟观看| 日韩高清在线免费看 | 欧美色青 | 青青青青青操 | 青草热久精品视频在线观看 | 精品亚洲综合在线第一区 | 成人在线日韩 | 国产一区二区三区久久精品小说 | 成人精品免费网站 | 亚洲美女aⅴ久久久91 | 91精品综合久久久久久五月天 | 香蕉久久夜色精品国产小优 | 亚洲国产情侣偷自在线二页 | 韩国美女激情vip | 色屁屁二区| 好湿好紧好大野战 | 色天使亚洲综合在线观看 | 网站在线播放 | 欧美第十页 | 久久三级网站 |