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