1. 程式人生 > >Cris 的 Scala 筆記整理(九):面向物件高階

Cris 的 Scala 筆記整理(九):面向物件高階

9. 面向物件高階

9.1 靜態屬性和靜態方法

① 回顧 Java 的靜態概念

public static 返回值型別 方法名(引數列表) {方法體}

Java 中靜態方法並不是通過物件呼叫的,而是通過類物件呼叫的,所以靜態操作並不是面向物件的

② Scala 中靜態的概念-伴生物件

Scala 語言是完全面向物件(萬物皆物件)的語言,所以並沒有靜態的操作(即在 Scala 中沒有靜態的概念)。但是為了能夠和 Java 語言互動(因為 Java 中有靜態概念),就產生了一種特殊的物件來模擬類物件,我們稱之為類的伴生物件。這個類的所有靜態內容都可以放置在它的伴生物件中宣告和呼叫

③ Scala 伴生類和伴生物件示例程式碼

object Demo4 {
  def main(args: Array[String]): Unit = {
    println(Woman.sex) // 底層呼叫的是 Woman$.Module$.sex()
    Woman.shopping() // 底層呼叫的是 Woman$.Module$.shopping()
  }
}

/**
  * 當我們吧同名的 class 和 object 放在同一個 .scala 檔案中,class xxx 就是伴生類,object xxx 就是伴生物件
  * 通常開發中會將成員屬性/方法寫在伴生類中,將靜態屬性/方法寫在伴生物件中
  * class xxx 編譯後的檔案 xxx.class 會有對 object xxx 的屬性或方法操作
  * 而 object xxx 編譯後會生成 xxx$.class ;也就是說 class xxx 編譯後的檔案會組合 object xxx 編譯後的 xxx.class
  */
class Woman { var name = "woman" } object Woman { val sex = 'F' def shopping(): Unit = { println("女人天生愛購物") } } 複製程式碼

輸出

我們將位元組碼檔案反編譯後再看看原理

說明

  1. Woman$ 位元組碼檔案先生成 Woman$ 型別的靜態物件
  2. Woman 類中會自動生成 object Woman 中定義的靜態方法和靜態屬性對應的 getter/setter 方法,這些方法的實質都是通過對 Woman$
    靜態物件的相應方法呼叫

圖示

小結

  • Scala 中伴生物件採用 object 關鍵字修飾,伴生物件中宣告的都是靜態內容,可以通過伴生物件名稱直接呼叫

  • 伴生物件對應的伴生類,他們的名字必須一致

  • 從語法的角度,伴生物件其實就是類的靜態方法和靜態屬性的集合

  • 從編譯的角度,伴生物件會生成一個靜態的例項,由伴生類中的靜態方法去呼叫這個靜態例項的方法

  • 伴生物件和伴生類的宣告需要放在同一個 Scala 原始檔中

  • 如果 class xxx 獨立存在一個 Scala 原始檔中,那麼 xxx 就只是一個沒有靜態內容的類;如果 object xxx 獨立存在一個 Scala 原始檔中,那麼 xxx 會編譯生成一個 xxx.classxxx$.classobject xxx 中宣告的方法和屬性可以直接通過 xxx.屬性xxx.方法 直接呼叫

    示例程式碼

object Demo4 {
  def main(args: Array[String]): Unit = {
   add()
  }

  def add(): Unit = {
    println("abc")
  }
}
複製程式碼
  • 如果 Scala 原始檔有一個伴生類及其對應的伴生物件,IDEA 中會如下顯示
object Girl {
  
}
class Girl{
  
}
複製程式碼

④ 練習:小孩子玩遊戲

object Demo5 {
  def main(args: Array[String]): Unit = {
    val c1 = new Child("cris")
    val c2 = new Child("james")
    val c3 = new Child("申惠善")
    Child.add(c1)
    Child.add(c2)
    Child.add(c3)
    Child.showNum()
  }
}

class Child(var name: String) {

}

object Child {
  var num = 0

  def add(c: Child): Unit = {
    println(s"${c.name} 加入了遊戲")
    num += 1
  }

  def showNum(): Unit = {
    println(s"當前共有 $num 個小孩子再玩遊戲")
  }
}
複製程式碼

輸出

總結:可以像類一樣使用 object,只需要記住 object 中定義的內容都是靜態型別的即可;object 還可以當做工具類使用,只需要定義工具方法即可

⑤ apply 方法

通過 objectapply 方法可以直接使用 類名(實參) 的方式來生成新的物件

object Practice {
  def main(args: Array[String]): Unit = {
    //    val bag1 = new Bag("LV")

    //    apply 方法被呼叫...
    //    Bag 的主構造被呼叫
    val bag = Bag("Channel")
  }
}

class Bag(var name: String) {
  println("Bag 的主構造被呼叫")
}

object Bag {
  def apply(name: String): Bag = {
    println("apply 方法被呼叫...")
    new Bag(name)
  }
}
複製程式碼

⑥ 練習

  1. 將程式的執行引數進行倒敘列印,並且引數之間使用 - 隔開
  println(args.toBuffer)
  private val str: String = args.reverse.mkString("-")
  println(str)
}
複製程式碼

執行如下

  1. 編寫一個撲克牌 4 種花色的列舉,讓其 toString 方法分別返回 , , , ,並實現一個函式,檢查某張牌的花色是否為紅色

    先試試 type 關鍵字

object Exer extends App {
  // type 相當於是給資料型別起別名
  type MyString = String
  val name: MyString = "cris"
  println(name) // cris
  println(name.getClass.getName) // java.lang.String
}
複製程式碼

然後再來完成練習

object Exer extends App {
  println(Suits) // ♠,♣,♥,♦
  println(Suits.isDiamond(Suits.Diamond)) // true
  println(Suits.isDiamond(Suits.Heart)) //false
}

object Suits extends Enumeration {
  type Suits = Value
  val Spade = Value("♠")
  val Club = Value("♣")
  val Heart = Value("♥")
  val Diamond = Value("♦")

  override def toString(): String = Suits.values.mkString(",")

  def isDiamond(s: Suits): Boolean = s == Diamond
}
複製程式碼

9.2 單例

單例物件是指:使用單例設計模式保證在整個的軟體系統中,某個類只能存在一個物件例項

① 回顧 Java 單例物件

Java 中,建立單例物件分為餓漢式(載入類資訊就建立單例物件,缺點是可能造成資源浪費,優點是執行緒安全)和懶漢式(使用時再建立單例物件)

通過靜態內部類實現懶漢式單例:

  1. 構造器私有化

  2. 類的內部建立物件

  3. 向外暴露一個靜態的公共方法

  4. 程式碼實現

public class Main {
    public static void main(String[] args) {
        Single instance = Single.getInstance();
        Single instance1 = Single.getInstance();
//      true
        System.out.println("(instance1==instance) = " + (instance1 == instance));
    }
}

class Single {
    private Single() {
    }

    /**
     * 靜態內部類:1. 使用時才載入;2. 載入時,不會中斷(保證執行緒安全)
     */
    private static class SingleInstance {
        private static final Single INSTANCE = new Single();
    }

    public static Single getInstance() {
        return SingleInstance.INSTANCE;
    }
}
複製程式碼

② Scala 中的單例模式

Scala 中實現單例異常簡單~

只需要寫一個 object ,就相當於建立了一個對應的單例物件

object SingletonDemo {
  def main(args: Array[String]): Unit = {
    
  }
}

object Singleton {
  val name = "singleton"

  def init(): Unit = {
    println("init...")
  }
}
複製程式碼

看看反編譯後的程式碼

​ 圖示:

9.3 特質(重點)

① 回顧 Java 的介面

  1. 在Java中, 一個類可以實現多個介面。

  2. 在Java中,介面之間支援多繼承

  3. 介面中屬性都是常量

  4. 介面中的方法都是抽象的(Java 1.8 之前)

② Scala 的特質(trait)

簡介

從面向物件來看,介面並不屬於面向物件的範疇,Scala 是純面向物件的語言,在 Scala 中,沒有介面

Scala 語言中,採用特質 trait(特徵)來代替介面的概念,也就是說,多個類具有相同的特徵(特徵)時,就可以將這個特質(特徵)獨立出來,採用關鍵字 trait 宣告

特質的宣告

trait 特質名{
	trait 
}
複製程式碼

特質的基礎語法

說明

  1. 類和特質關係,使用繼承的關係;因為 Scala 的特質,有傳統 interface 特點,同時又有抽象類特點

  2. 當一個類去繼承特質時,第一個連線詞是 extends ,後面是 with

  3. 如果一個類在繼承特質和父類時,應當把父類寫在 extends

③ trait 傳統使用案例

可以將 trait 當做傳統的介面使用

請根據以下圖示,使用 trait 完成需求

程式碼如下:

object Demo {
  def main(args: Array[String]): Unit = {
    val c = new C
    val f = new F
    c.getConnection()
    f.getConnection()
  }
}

trait Connection {
  def getConnection()
}

class A {}

class B extends A {}

class C extends A with Connection {
  override def getConnection(): Unit = println("連線 MySQL 資料庫")
}

class D {}

class E extends D {}

class F extends D with Connection {
  override def getConnection(): Unit = println("連線 HBase 資料庫")
}
複製程式碼

我們看看反編譯後的程式碼

程式碼說明

  1. 如果我們建立了一個 trait , 該 trait 只有抽象的方法,那麼在底層就只會生成一個 interface

  2. 繼承了 trait 的類,必須實現 trait 的抽象方法(這點和 Java 一樣)

特質的進一步說明

  1. Scala 提供了特質(trait),特質可以同時擁有抽象方法和具體方法,一個類可以實現/繼承多個特質

    程式碼演示

object Demo2 {
  def main(args: Array[String]): Unit = {
    val account: Account = new BankAccount
    account.check
    account.info
  }

}

trait Account {
  def check

  def info: Unit = {
    println("account info")
  }
}

class BankAccount extends Account {
  override def check: Unit = {
    println("需要提供銀行賬號和密碼進行驗證")
  }
}
複製程式碼

看看編譯後的程式碼,Scala 是如何實現的?

再看看 trait 的編譯圖示

  1. 特質中沒有實現的方法就是抽象方法;類通過 extends 繼承特質,通過 with 可以繼承多個特質;也可以針對特質生成匿名類
val account2 = new Account {
  override def check(): Unit = {
    println("需要提供指紋進行驗證")
  }
}
//    需要提供指紋進行驗證
account2.check()
複製程式碼
  1. 所有的 Java 介面都可以當做 Scala 特質使用
class MyClass extends Serializable{
  
}
複製程式碼

實質上這個 Serializable 特質繼承了 JavaSerializable

④ 特質的動態混入(MixIn)機制

首先,Scala 允許匿名子類動態的增加方法(Java 同樣也支援),示例程式碼如下

object MixInDemo {
  def main(args: Array[String]): Unit = {
    val car = new Car {
      def run(): Unit = {
        println("什麼路都能開")
      }
    }
    //    什麼路都能開
    car.run()
  }

}

class Car {}
複製程式碼

然後看看 Scala 的特質混入機制如何實現的

object MixInDemo {
  def main(args: Array[String]): Unit = {
    val car = new Car with Transform {
      override def speed(): Unit = println("加速300km/h")
    }
    car.speed()
  }
}

trait Transform {
  def speed()
}

class Car {}
複製程式碼

實質還是通過匿名子類的方式來實現的,看看編譯後的位元組碼

總結

  • 除了可以在類宣告時繼承特質以外,還可以在構建物件時混入特質,擴充套件目標類的功能
  • 此種方式也可以應用於對抽象類功能進行擴充套件、
object MixInDemo {
  def main(args: Array[String]): Unit = {
    val p = new Plain with Transform
    p.speed()
  }
}
abstract class Plain

trait Transform {
  def speed(): Unit = println("加速")
}
複製程式碼
  • 動態混入是 Scala 特有的方式( Java 沒有動態混入),可在不修改類宣告/定義的情況下,擴充套件類的功能,非常的靈活,耦合性低

  • 動態混入可以在不影響原有的繼承關係的基礎上,給指定的類擴充套件功能

思考:如果抽象類中有沒有實現的方法,如何動態混入特質?

動態混入特質的同時實現抽象方法即可

問題:Scala 中建立物件一共 有幾種方式?

  1. new
  2. apply
  3. 動態混入
  4. 匿名子類

⑤ 疊加特質

  1. 構建物件的同時如果混入多個特質,稱之為疊加特質

  2. 特質宣告順序從左到右方法執行順序從右到左

示例如下

請根據以下圖示寫出一個關於疊加特質的案例

object MixInDemo {
  def main(args: Array[String]): Unit = {
    // 混入物件的構建順序和特質宣告順序一致
    val e = new EE with CC with DD
  }
}

trait AA {
  println("AAAA")

  def func()
}

trait BB extends AA {
  println("BBB")

  override def func(): Unit = println("BBB's func")

}

trait CC extends BB {
  println("CCC")

  override def func(): Unit = {
    println("CC's func")
    super.func()
  }
}

trait DD extends BB {
  println("DD")

  override def func(): Unit = {
    println("CC's func")
    super.func()
  }
}

class EE
複製程式碼

輸出

如果我們呼叫 efunc 方法

輸出

總結

  1. 當構建一個混入物件時,構建順序和 宣告的順序一致(從左到右),機制和類的繼承一致

  2. 執行方法時,是從右到左執行(按特質)

  3. Scala 中特質的方法中如果呼叫 super ,並不是表示呼叫父特質的方法而是向前面(左邊)繼續查詢特質,如果找不到,才會去父特質查詢

疊加特質細節

  1. 特質宣告順序從左到右。

  2. Scala 在執行疊加物件的方法時,會首先從後面的特質(從右向左)開始執行

  3. Scala 中特質中如果呼叫 super,並不是表示呼叫父特質的方法,而是向前面(左邊)繼續查詢特質,如果找不到,才會去父特質查詢

  4. 如果想要呼叫具體特質的方法,可以指定:super[特質].xxx(…);其中的泛型必須是該特質的直接超類型別

示例程式碼

trait DD extends BB {
  println("DD")

  override def func(): Unit = {
    println("DD's func")
    super[BB].func()
  }
}
  def main(args: Array[String]): Unit = {
        val e = new EE with CC with DD
        e.func()
  }
複製程式碼

此時輸出如下

⑥ 特質中重寫抽象方法

如果執行以下程式碼

就會報錯

修改方式如下:

  1. 去掉 super.xxx
  2. 因為呼叫父特質的抽象方法,實際使用時,卻沒有具體的實現,就無法執行成功,為了避免這種情況的發生,可以抽象重寫方法,這樣在使用時,可能其他特質實現了這個抽象方法
trait A2 {
  def func()
}

trait B2 extends A2 {
  abstract override def func(): Unit = {
    println("B2")
    super.func()
  }
}
複製程式碼

如此重寫就不會再報錯了(相當詭異的語法~)

改造之前的程式碼

object Main3 {
  def main(args: Array[String]): Unit = {
    val e = new E2 with C2 with B2
    e.func()
  }
}

trait A2 {
  println("A2")

  def func()
}

trait B2 extends A2 {
  println("B2")

  abstract override def func(): Unit = {
    println("B2's func")
    super.func()
  }
}

trait C2 extends A2 {
  println("C2")

  override def func(): Unit = {
    println("C2's func")
  }
}

class E2
複製程式碼

解釋:

物件 e 執行 func() 將會從 B2 開始執行對應的 func()B2func() 將會呼叫 super.func(),指向的就是 C2func();而 C2func() 是對父特質 A2 的抽象方法 func() 的完整實現

示意圖

⑦ 富介面

既有抽象方法,又有非抽象方法的特質

trait A2 {
  def func()
  def func2(): Unit = println("A2")
}
複製程式碼

⑧ 特質的欄位

解釋:特質中可以定義欄位,如果初始化該欄位就成為具體欄位;如果不初始化就是抽象欄位。混入該特質的類具有該欄位,欄位不是繼承,而是直接加入類,成為自己的欄位

object Main3 {
  def main(args: Array[String]): Unit = {
    val e2 = new E2 with D2
    println(e2.name) // cris
  }
}

trait C2 {
  var name: String
}

trait D2 extends C2 {
  var name = "cris"
}

class E2
複製程式碼

反編譯後的程式碼

⑨ 多個特質的初始化順序

我們除了在建立物件的時候使用 with 來繼承特質,還可以在宣告類的時候使用 with 來繼承特質

一個類又繼承超類又繼承多個特質的時候,請問初始化該類的順序?

object Main3 {
  def main(args: Array[String]): Unit = {
    val e2 = new E2
  }
}
trait A2{
  println("A2")
}
trait B2 extends A2{
  println("B2")
}
trait C2 extends A2{
  println("C2")
}
class D2{
  println("D2")
}
class E2 extends D2 with C2 with B2{
  println("E2")
}
複製程式碼

輸出

總結

  1. 先初始化超類

  2. 超類初始化完畢後按照順序初始化特質

  3. 初始化特質前先初始化該特質的父特質

  4. 多個特質具有相同的父特質只初始化一次

  5. 最後執行子類的初始化程式碼

如果是動態混入,那麼類的初始化順序又是怎麼樣的?

class F extends D2 {
  println("F")
}
  def main(args: Array[String]): Unit = {
    var f = new F with C2 with B2
  }
複製程式碼

輸出

總結

  1. 先初始化超類
  2. 然後初始化子類
  3. 最後初始化特質,初始化順序和上面一致

兩種初始化流程的理解

  1. 宣告類並繼承特質的方式可以理解為在初始化物件之前需要初始化必須的所有超類和特質
  2. 建立類再繼承特質的方式可以理解為混入特質之前就已經建立好了匿名類

⑩ 擴充套件類的特質

  • 特質可以繼承類,以用來拓展該類的一些功能
object Main4 {
  def main(args: Array[String]): Unit = {
    val e = new MyException {}
    e.func()
  }
}

trait MyException extends Exception {
  def func(): Unit = {
    println(getMessage) // getMessage 方法來自 Exception 類(java.lang.Exception)
  }
}
複製程式碼
  • 所有混入擴充套件特質的類,會自動成為那個特質所繼承的超類的子類
object Main4 {
  def main(args: Array[String]): Unit = {
    val e = new MyException2
    println(e.getMessage) // this is my exception!
  }
}

trait MyException extends Exception {
  def func(): Unit = {
    println(getMessage) // getMessage 方法來自 Exception 類(java.lang.Exception)
  }
}

// MyException2 就是 Exception 的子類,所以可以重寫 Exception 的 getMessage 方法
class MyException2 extends MyException {
  override def getMessage: String = "this is my exception!"
}
複製程式碼
  • 如果混入該特質的類,已經繼承了另一個類( A 類),則要求 A 類是特質超類的子類,否則就會出現了多繼承現象,發生錯誤

    為了便於理解,修改上面的程式碼

class A {}

class MyException2 extends A with MyException {
  override def getMessage: String = "this is my exception!"
}
複製程式碼

執行出錯

如果將 A 繼承 Exception

class A extends Exception{}
複製程式碼

那麼執行成功~

⑩① 訪問特質自身型別

主要是為了解決特質的迴圈依賴問題,同時可以確保特質在不擴充套件某個類的情況下,依然可以做到限制混入該特質的類的型別

示例程式碼

執行程式碼如下

def main(args: Array[String]): Unit = {
  val e = new MyException2
  println(e.getMessage) // exception
}
複製程式碼

9.4 巢狀類

Scala 中,你幾乎可以在任何語法結構內嵌任何語法結構。如在類中可以再定義一個類,這樣的類是巢狀類,其他語法結構也是一樣

巢狀類類似於 Java 中的內部類

① 回顧 Java 的內部類

Java 中,一個類的內部又完整的嵌套了另一個類,這樣的結構稱為巢狀類;其中被巢狀的類稱為內部類,巢狀的類稱為外部類。

內部類最大的特點就是可以直接訪問私有屬性,並且可以體現類與類之間的包含關係

Java 內部類的分類

從定義在外部類的成員位置上區分:

  1. 成員內部類(無 static 修飾)
  2. 靜態內部類(有 static 修飾)

從定義在外部類的區域性位置上區分:

  1. 區域性內部類(有類名)
  2. 匿名內部類(無類名)

② Scala 的內部類

示例程式碼

object InnerClassDemo {
  def main(args: Array[String]): Unit = {
    // 建立成員內部類例項      
    val outer1 = new Outer
    val inner1 = new outer1.Inner

    // 建立靜態內部類例項
    val staticInner = new Outer.StaticInnerClass
  }

}

class Outer {
// 成員內部類
  class Inner {}

}

object Outer {
// 靜態內部類
  class StaticInnerClass {}

}

            
           

相關推薦

CrisScala 筆記整理面向物件高階

9. 面向物件高階 9.1 靜態屬性和靜態方法 ① 回顧 Java 的靜態概念 public static 返回值型別 方法名(引數列表) {方法體} Java 中靜態方法並不是通過物件呼叫的,而是通過類物件呼叫的,所以靜態操作並不是面向物件的 ② Scala 中靜態的概念-伴生物件 Scala

CrisScala 筆記整理面向物件

7. 面向物件(重點) 7.1 Scala 面向物件基礎 類 [修飾符] class 類名 { 類體 } scala語法中,類並不宣告為public,所有這些類都具有公有可見性(即預設就是public) 一個Scala原始檔可以包含多個類 定義一個最簡單的類 object

Scala筆記整理Actor和AKKA

大數據 Scala [TOC] 概述 ? Scala的Actor有點類似於Java中的多線程編程。但是不同的是,Scala的Actor提供的模型與多線程有所不同。Scala的Actor盡可能地避免鎖和共享狀態,從而避免多線程並發時出現資源爭用的情況,進而提升多線程編程的性能。 Spark中使用

CrisScala 筆記整理隱式轉換

10. 隱式轉換 隱式轉換函式是以implicit關鍵字宣告的帶有單個引數的函式。這種函式將會自動應用,將值從一種型別轉換為另一種型別 ① 隱式轉換最佳入門案例 首先看下面的程式碼 如果想要轉換成功,就需要藉助隱式轉換函式 為了更好的理解,我們看看反編譯後的位元組

Scala筆記整理scala基本知識

大數據 Scala [TOC] Scala簡介 Scala是一門多範式(multi-paradigm)的編程語言,設計初衷是要集成面向對象編程和函數式編程的各種特性。 Scala運行在Java虛擬機上,並兼容現有的Java程序。 Scala源代碼被編譯成Java字節碼,所以它可以運行於JVM之上,並

Scala筆記整理Scala數據結構—數組、map與tuple

大數據 Scala [TOC] 數組 定長數組 如果你需要一個長度不變的數組,可以用Scala中的Array。例如: val numsArray = new Array[Int] (30) //長度為30的整數數組,所有元素初始化為0 val stringArrays = new Array [St

Scala筆記整理Scala面向對象—類詳解1

大數據 Scala [TOC] getter和setter 簡單類和無參方法 需要說明的是,官方給出的參考資料對於這方面講解得十分詳細,目前入門來說,不需要達到這樣的理解,只需要可以進行開發即可,這一部分我給出的是官方的一些文檔說明,但是後面的定制和註解,就直接簡單說明能用就好了。 class

Scala筆記整理Scala面向對象—類詳解2繼承相關

大數據 Scala [TOC] 單例 希望某個類只存在一個使用的對象,而不管有多少個調用者在使用它,就是單例的概念。 Java中的單例 package cn.xpleaf.single; /** * 單例模式-餓漢式(在屬性中先創建好對象,不管是否調用getInstance方法) * @auth

Scala筆記整理函數式編程

大數據 Scala [TOC] 作為值傳遞的函數 測試代碼如下: package cn.xpleaf.bigdata.p4.function /** * scala中關於函數的操作 */ object _01FunctionOps { def main(args: Array[Stri

Scala筆記整理Scala集合庫

大數據 Scala [TOC] Scala主要集合結構 1、Scala中的集合體系主要包括:Iterable、Seq(IndexSeq)、Set(SortedSet)、Map(SortedMap)。其中Iterable是所有集合trait的根trait。實際上Seq、Set、和Map都是子trait

Scala筆記整理類型參數泛型與隱士轉換

大數據 Scala [TOC] 概述 類型參數是什麽?類型參數其實就是Java中的泛型。大家對Java中的泛型應該有所了解,比如我們有List list = new ArrayList(),接著list.add(1),沒問題,list.add("2"),然後我們list.get(

Scala筆記整理模式匹配和樣例類

大數據 Scala [TOC] 可以用到switch語句 1、Scala強大的模式匹配機制,可以應用在switch語句、類型檢查以及“析構”等場合。 def swithOps: Unit ={ var sign = 0 val ch: Char = ‘+‘ ch match

Python基礎14面向物件高階多重繼承,定製類,列舉類,元類

一,多重繼承 定義:一個子類可以繼承自多個父類 目的:同時擁有多個父類的所有功能,且減少設計層次。 Mixln:某子類中,需要混入額外功能,可以通過多重繼承實現,這種設計,被叫做Mixln 二,定製類 解釋:通過魔術方法的定義,是自定義的類滿足某些特性。 __str__:

Kafka筆記整理Kafka Java API使用

大數據 Kafka Java [TOC] Kafka筆記整理(二):Kafka Java API使用 下面的測試代碼使用的都是下面的topic: $ kafka-topics.sh --describe hadoop --zookeeper uplooking01:2181,uplooking0

Kafka筆記整理消費形式驗證與性能測試

大數據 Kafka 性能測試 [TOC] Kafka筆記整理(三):消費形式驗證與性能測試 Kafka消費形式驗證 前面的《Kafka筆記整理(一)》中有提到消費者的消費形式,說明如下: 1、每個consumer屬於一個consumer group,可以指定組id。group.id 2、消費形

Redis筆記整理Redis安裝配置與數據類型操作

數據庫 NoSQL Redis [TOC] Redis筆記整理(一):Redis安裝配置與數據類型操作 Redis簡介 Redis是一個開源(BSD許可),內存存儲的數據結構服務器,可用作數據庫,高速緩存和消息隊列代理。 它支持字符串、哈希表、列表、集合、有序集合,位圖,hyperloglo

Redis筆記整理Java API使用與Redis分布式集群環境搭建

數據庫 NoSQL Redis [TOC] Redis筆記整理(二):Java API使用與Redis分布式集群環境搭建 Redis Java API使用(一):單機版本Redis API使用 Redis的Java API通過Jedis來進行操作,因此首先需要Jedis的第三方庫,因為使用的是M

Redis筆記整理進階操作與高級部分

數據庫 NoSQL Redis [TOC] Redis筆記整理(三):進階操作與高級部分 Redis發布訂閱 Redis發布訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。 Redis客戶端可以訂閱任意數量的頻道。 下圖展示了頻道channel1,以

ElasticSearch筆記整理簡介、REST與安裝配置

大數據 ElasticSearch ELK [TOC] ElasticSearch簡介 ElasticSearch是一款基於Apache Lucene構建的開源搜索引擎,它采用Java編寫並使用Lucene構建索引、提供搜索功能,ElasticSearch的目標是讓全文搜索變得簡單,開發者可以通

ElasticSearch筆記整理CURL操作、ES插件、集群安裝與核心概念

大數據 ElasticSearch ELK [TOC] CURL操作 CURL簡介 curl是利用URL語法在命令行方式下工作的開源文件傳輸工具,使用curl可以簡單實現常見的get/post請求。簡單的認為是可以在命令行下面訪問url的一個工具。在centos的默認庫裏面是有curl工具的,如