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====================

相关文章
相关标签/搜索