首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Groovy 於 Java 平台實現運算子多載:三大類型完整解析

     編輯:Java 相關知識

背景與動機

Java 為避免 C++ 風格運算子多載造成的語意模糊,刻意移除此功能。Groovy 作為 JVM 動態語言,重新引入運算子多載(即時多態),提供簡潔語法糖,但需謹慎使用並完善文件化。

Groovy 三大可多載運算子類別

類別運算子對應方法說明
比較運算子==equals()物件內容相等(非參考相等)
<=>compareTo()三向比較,衍生出 > >= < <=
算術運算子+plus()加法/串接
-minus()減法/移除
*multiply()乘法
/divide()除法
++/--next()/previous()遞增/遞減
<<leftShift()左移/集合加入
陣列存取運算子a[b]getAt(b)索引讀取
a[b]=cputAt(b,c)索引寫入

比較運算子實戰:LavaLamp 類別

實作 Comparable 介面與 equals()/hashCode(),利用 Apache Commons Lang 建構器簡化:

class LavaLamp implements Comparable {
    @Property String model, baseColor, liquidColor, lavaColor

    boolean equals(obj) {
        if (!(obj instanceof LavaLamp)) return false
        LavaLamp rhs = (LavaLamp) obj
        return new EqualsBuilder()
            .append(this.model, rhs.model)
            .append(this.baseColor, rhs.baseColor)
            .append(this.liquidColor, rhs.liquidColor)
            .append(this.lavaColor, rhs.lavaColor)
            .isEquals()
    }

    int hashCode() {
        return new HashCodeBuilder(17, 37)
            .append(model).append(baseColor)
            .append(liquidColor).append(lavaColor)
            .toHashCode()
    }

    int compareTo(obj) {
        LavaLamp lmp = (LavaLamp) obj
        return new CompareToBuilder()
            .append(lmp.model, this.model)
            .append(lmp.lavaColor, this.lavaColor)
            .append(lmp.baseColor, this.baseColor)
            .append(lmp.liquidColor, this.liquidColor)
            .toComparison()
    }
}

測試比較行為:

lamp1 = new LavaLamp(model:"1341", baseColor:"Black", liquidColor:"Clear", lavaColor:"Red")
lamp2 = new LavaLamp(model:"1341", baseColor:"Blue", liquidColor:"Clear", lavaColor:"Red")
lamp3 = new LavaLamp(model:"1341", baseColor:"Black", liquidColor:"Clear", lavaColor:"Blue")
lamp4 = new LavaLamp(model:"1342", baseColor:"Blue", liquidColor:"Clear", lavaColor:"DarkGreen")
lamp5 = new LavaLamp(model:"1342", baseColor:"Blue", liquidColor:"Clear", lavaColor:"DarkGreen")

println lamp1 <=> lamp2  // 1 (Black < Blue)
println lamp1 <=> lamp3  // -1 (Red < Blue)
println lamp1 < lamp3    // true
println lamp4 <=> lamp5  // 0 (相等)

assert lamp4 == lamp5    // 內容相等
assert lamp3 != lamp4    // 內容不等

參考相等性測試使用 is() 方法:

lamp6 = new LavaLamp(model:"1344", baseColor:"Black", liquidColor:"Clear", lavaColor:"Purple")
lamp7 = lamp6
assert lamp7.is(lamp6)  // 同一物件參考

算術運算子實戰:JukeBox 播放清單

class JukeBox {
    def songs = []

    def plus(song) { songs << song }
    def minus(song) { songs.remove(songs.lastIndexOf(song)) }
    def leftShift(song) { plus(song) }  // 支援 << 語法

    def printPlayList() { songs.each { println it.title } }
}

// 使用範例
jbox = new JukeBox()
jbox + sng1; jbox + sng2; jbox + sng3
jbox.printPlayList()  // Spanish Eyes, Race with the Devil..., Nena
jbox - sng2
jbox.printPlayList()  // Spanish Eyes, Nena
jbox << sng2  // 重新加入

陣列存取運算子實戰

class JukeBox {
    // ... 前述程式碼
    def getAt(pos) { songs[pos] }
    def putAt(pos, song) { songs[pos] = song }
}

// 使用範例
println jbox[0]  // Spanish Eyes
jbox[0] = sng2
println jbox[0]  // Race w/the Devil

JDK 內建類別的 Groovy 強化

Groovy 已為常用 JDK 類別實作運算子多載:

  • Character:支援 <=> 比較
  • StringBuffer:支援 << 追加字串
  • Date:支援 +/- 日期運算
// Character 比較
def a = 'a' as char, b = 'b' as char
println a < b  // true

// StringBuffer 追加
def strbuf = new StringBuffer()
strbuf.append("Error: ")
strbuf << "NullPointerException"
println strbuf.toString()

// 日期運算
def today = new Date()
println today + 1    // 明天
println today - 1    // 昨天

最佳實踐與結語

運算子多載威力強大,但濫用將導致程式碼難以理解。核心原則:

  1. 僅於語意直覺符合領域模型時使用(如數學物件、集合操作、日期運算)
  2. 完整文件化所有多載行為與預期語意
  3. 避免違反最小驚訝原則的非常規實作
  4. 單元測試驗證所有多載運算子的邊界條件

Groovy 讓我們在保持 JVM 相容性的前提下,重獲表達力豐富的運算子語法,關鍵在於審慎抉擇使用時機。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved