Scala primary && secondary constructor

Scala primary && secondary constructorjava

Scala定義的類git

package com.usoft

/**
 * 不使用var 和 val 進行屬性字段的聲明
 */
class Person(name: String, age: Int) {
  def sayHi(): String = {
    "my name is " + name + ",my age is " + age;
  }
}

/**
 * 使用var 進行屬性字段的聲明
 * @param name
 * @param age
 */
class Person0(var name: String, var age: Int) {
  def sayHi(): String = {
    "my name is " + name + ",my age is " + age;
  }
}

/**
 * 使用 val
 * @param name
 * @param age
 * @param address
 */
class Person1(val name: String, val age: Int, val address: String) {
  def sayHi(): String = {
    "my name is " + name + ",my age is " + age;
  }
}

/**
 * 使用val 和 private var
 * @param name
 * @param age
 */
class Person2(name: String, private var age: Int) {
  def sayHi(): String = {
    "my name is " + name + ",my age is " + age;
  }
}

class Person3(name: String, var age: Int, private var address: String) {
  def sayHi(): String = {
    "hello world,scala"
  }
}

class Person4(name: String, var age: Int, private var address: String) {
  def this(name: String) {
    this(name, 0, "UNKNOW")
  }

  def this(name: String, age: Int) {
    this(name, age, "UNKNOW");
  }

  def sayHi(): String = {
    "hello world,scala"
  }
}

object Main {
  def main(args: Array[String]) {
    val p = new Person("lyx", 12);
    println(p.sayHi())

    val p3 = new Person3("liyanxin", 23, "unknow");
    println(p3.sayHi())
    //println(p3.name);
    println(p3.age);
    //println(p3.address); // not accessable
  }
}

其中 構造函數跟在類聲明的後面。函數

用法: javap <options> <classes>                                                                                                                                ui

其中, 可能的選項包括:                                                                                                                                          this

  -help  --help  -?        輸出此用法消息                                                                                                                      spa

  -version                 版本信息                                                                                                                            scala

  -v  -verbose             輸出附加信息                                                                                                                        code

  -l                       輸出行號和本地變量表                                                                                                                          ci

  -public                  僅顯示公共類和成員                                                                                                                  get

  -protected               顯示受保護的/公共類和成員                                                                                                           

  -package                 顯示程序包/受保護的/公共類                                                                                                          

                           和成員 (默認)                                                                                                                       

  -p  -private             顯示全部類和成員                                                                                                                    

  -c                       對代碼進行反彙編                                                                                                                            

  -s                       輸出內部類型簽名                                                                                                                    

  -sysinfo                 顯示正在處理的類的                                                                                                                  

                           系統信息 (路徑, 大小, 日期, MD5 散列)                                                                                               

  -constants               顯示最終常量                                                                                                                        

  -classpath <path>        指定查找用戶類文件的位置                                                                                                            

  -cp <path>               指定查找用戶類文件的位置                                                                                                                        

  -bootclasspath <path>    覆蓋引導類文件的位置                                           

編譯後 咱們經過javap來反編譯看一下類的內部究竟是什麼樣。


class Person(name: String, age: Int)

先看Person類,class Person(name: String, age: Int) 反編譯以下,

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft>javap -p Person.class
Compiled from "Person.scala"
public class com.usoft.Person {
  private final java.lang.String name;
  private final int age;
  public java.lang.String sayHi();
  public com.usoft.Person(java.lang.String, int);
}

經過反編譯結果咱們知道像這樣不用val聲明的屬性字段在生成的類裏都會聲明爲private final類型,並無相應的get和set方法,因此是不能用點屬性的方式直接獲得屬性字段的值,可是在方法內部,能夠直接獲得屬性字段的值。好比以下的代碼,

val p = new Person("lyx", 12);
println(p.sayHi())
println(p.name)
println(p.age)

運行則報錯,

Error:(70, 19) value name is not a member of com.usoft.Person
        println(p.name)
                  ^

name不是類Person的成員屬性。


class Person0(var name: String, var age: Int)

Person0 類的構造方式是class Person0(var name: String, var age: Int) ,反編譯

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft>javap -p Person0.class
Compiled from "Person.scala"
public class com.usoft.Person0 {
  private java.lang.String name;
  private int age;
  public java.lang.String name();
  public void name_$eq(java.lang.String);
  public int age();
  public void age_$eq(int);
  public java.lang.String sayHi();
  public com.usoft.Person0(java.lang.String, int);
}

在這裏的構造方法的參數使用var聲明的,而在生成的類中的類型倒是private類型的屬性字段,有相應的getter和setter方法。這裏的age_$eq就至關於set方法(沒有驗證)。

In Scala, a getter and setter will be implicitly defined for all non-private vars in a object. 

val p0 = new Person0("liyanxin", 890);
println(p0.name)
println(p0.age)
p0.name = "hello"
p0.age = 12
println(p0.name)
println(p0.age)

在scala裏,咱們就能夠直接經過點屬性字段的方法get和set相應的值。

Actually, Scala just does implicitly what Java code does explicitly. There is a private field created internal to the class and the equivalent of 「getter」 and 「setter」 accessor methods are generated. 


class Person1(val name: String, val age: Int, val address: String)

Person1 類的構造方法,class Person1(val name: String, val age: Int, val address: String),反編譯,

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft>javap -p Person1.class
Compiled from "Person.scala"
public class com.usoft.Person1 {
  private final java.lang.String name;
  private final int age;
  private final java.lang.String address;
  public java.lang.String name();
  public int age();
  public java.lang.String address();
  public java.lang.String sayHi();
  public com.usoft.Person1(java.lang.String, int, java.lang.String);
}

一樣的 和 class Person(name: String, age: Int) 反編譯結果同樣,相應的屬性字段在Java類裏都是private final。


class Person2(name: String, private var age: Int) 

Person2 類的構造方法,class Person2(name: String, private var age: Int) 

一個屬性用沒有用var和val(默認爲val類型的屬性字段) ,另外一個用private var,反編譯結果,

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft>javap -p Person2.class
Compiled from "Person.scala"
public class com.usoft.Person2 {
  private final java.lang.String name;
  private int age;
  private int age();
  private void age_$eq(int);
  public java.lang.String sayHi();
  public com.usoft.Person2(java.lang.String, int);
}

age屬性字段private var聲明的,生成的類的getter方法則是private int age();因此雖然是var聲明的,可是同時聲明瞭private,因此也不能經過點屬性的方式獲得值。

好比像這樣,

val p2 = new Person2("xxggy",12)
println(p2.age)

則報錯,

Error:(89, 16) variable age in class Person2 cannot be accessed in com.usoft.Person2
    println(p2.age)
               ^


class Person3(name: String, var age: Int, private var address: String)

Person3 類class Person3(name: String, var age: Int, private var address: String),其中address顯式的用private 聲明,這會有什麼效果,反編譯以下,

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft>javap -p Person3.class
Compiled from "Person.scala"
public class com.usoft.Person3 {
  private int age;
  private java.lang.String address;
  public int age();
  public void age_$eq(int);
  private java.lang.String address();
  private void address_$eq(java.lang.String);
  public java.lang.String sayHi();
  public com.usoft.Person3(java.lang.String, int, java.lang.String);
}

問題來了,反編譯後的類只有兩個private 變量,

private int age;

private java.lang.String address;

那麼name屬性字段去哪了?要注意到Person3 是這樣定義的,

class Person3(name: String, var age: Int, private var address: String) {
  def sayHi(): String = {
    "hello world,scala"
  }
}

也就是說name屬性在類內部沒有用的,scala編譯後的class文件就沒有name屬性。var 類型的變量無論用到沒用到,在反編譯的類裏都有相應的屬性字段。


class Person4(name: String, var age: Int, private var address: String) 

反編譯,Person4 有一個 主構造函數(public com.usoft.Person4(java.lang.String, int, java.lang.String))和多個輔助構造函數。

C:\WorkSpace5-gitosc\scala-sample\out\production\scala-sample\com\usoft>javap -p Person4.class
Compiled from "Person.scala"
public class com.usoft.Person4 {
  private int age;
  private java.lang.String address;
  public int age();
  public void age_$eq(int);
  private java.lang.String address();
  private void address_$eq(java.lang.String);
  public java.lang.String sayHi();
  public com.usoft.Person4(java.lang.String, int, java.lang.String);
  public com.usoft.Person4(java.lang.String);
  public com.usoft.Person4(java.lang.String, int);
}

以上就是scala的構造函數多種定義方法,以及在scala類中的屬性字段的狀況。

====================END====================

相關文章
相關標籤/搜索