您的位置:首页 > 其它

Scala学习笔记(1)-类-var-val

2015-07-29 17:42 375 查看
开始接触学习Scala,边学边记。

作为参考和对比,首先从Java的POJO开始;

定义一个Person类(为防止和Scala的Person类重名冲突,将该类放在gao.java目录下),如下:

package gao.java;
public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

我们可以使用javap查看一下Person类编译后的Person.class文件:

$ javap -p target/scala-2.11/classes/gao/java/Person.class
Compiled from "Person.java"
public class gao.java.Person {
    private java.lang.String name;
    private int age;
    public gao.java.Person(java.lang.String, int);  // 构造方法
    public java.lang.String getName();  // getter方法
    public void setName(java.lang.String);  // setter方法
    public int getAge();  // getter方法
    public void setAge(int);  // setter方法
}


再来看看Scala如何定义Person类(在gao目录下):

package gao
class Person(var name:String, var age:Int)

哇塞!这就完了?相信大多数人第一次见到都会和我一样好奇。非常的简单!

我们也使用javap查看一下该Scala类编译后的Person.class文件:

$ javap -p target/scala-2.11/classes/gao/Person.class
Compiled from "Person.scala"
public class gao.Person {
  private java.lang.String name;
  private int age;
  public java.lang.String name();  // getter方法
  public void name_$eq(java.lang.String);  // setter方法
  public int age();  // getter方法
  public void age_$eq(int);  // setter方法
  public gao.Person(java.lang.String, int);  // 构造方法
}

(1)在.class文件中,除了getter/setter方法的方法名看起来比较别扭之外,其他没有什么不同;

(2)不过.class文件是给JVM看的,而对JVM来说,只要是有效的方法名,又有什么区别呢。

(3)对于程序员来说,编码效率相对提高了很多(27行=>2行)。

(4)属性的访问修饰符自动编译为private。

(5)getter/setter方法自动编译为public。

Scala的方法调用也非常简单,为了简便,演示如下:

package gao
object Main {
  def main(args: Array[String]) {
    val person = new Person("Jack", 28)
    println(person.name)    // 调用getter方法,然后打印到标准输出
    println(person.age)       // 调用getter方法,然后打印到标准输出
    person.name = "Rose"  // 调用setter方法赋值
    person.age = 27            // 调用setter方法赋值
    println(person.name)   // 再调用getter方法,然后打印到标准输出
    println(person.age)      // 再调用getter方法,然后打印到标准输出
  }
}


输出如下:

Jack
28
Rose
27


再使用javap查看一下这个Main.class文件,发现它只有一个Java的main方法:

$ javap -p target/scala-2.11/classes/gao/Main.class
Compiled from "Main.scala"
public final class gao.Main {
  public static void main(java.lang.String[]);
}

在Scala中,分别使用valvar来声明值和变量。

所谓值就是常量,不可变量。还是使用代码来演示比较清晰,修改Scala的Person类如下:

package gao
class Person(val name:String, var age:Int)

其实这还看不出什么差别,不过通过方法调用就很容易看出不同,如图所示,不能给val修饰的属性赋值;




为什么呢?

这还是要使用javap来的比较清楚:

$ javap -p target/scala-2.11/classes/gao/Person.class
Compiled from "Person.scala"
public class gao.Person {
  private final java.lang.String name;
  private int age;
  public java.lang.String name();
  public int age();
  public void age_$eq(int);
  public gao.Person(java.lang.String, int);
}

原来val修饰的字段被编译成final的,而且不会有setter方法,所以不能赋值。

Scala建议在赋值时,优先选择使用val,在必须使用var的情况下再使用var

从上边示例看出,Scala编译器自动将类字段的访问修饰符编译为private

那如果我们在代码中,显式的类字段标识为private会怎样呢?

package gao
class Person(val name:String, var age:Int) {
private val legs = 4
var brother = 2
}

使用javap查看编译后的.class文件内容:

$ javap -p target/scala-2.11/classes/gao/Person.class
Compiled from "Person.scala"
public class gao.Person {
    private final java.lang.String name;
    private int age;
    private final int legs;
    private int brother;
    public java.lang.String name();
    public int age();
    public void age_$eq(int);
    private int legs();  // getter方法私有,外部不能访问,只能在内部使用,还弄个getter方法干什么用?
    public int brother();  // getter方法
    public void brother_$eq(int);  // setter方法
    public gao.Person(java.lang.String, int);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: