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來反編譯看一下類的內部究竟是什麼樣。
先看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的成員屬性。
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.
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。
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) ^
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 類型的變量無論用到沒用到,在反編譯的類裏都有相應的屬性字段。
反編譯,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====================