scala类参数修饰符浅析
来源:互联网 发布:excel画出数据形状 编辑:程序博客网 时间:2024/05/22 16:48
case类的类参数修饰符
case类的类参数修饰符有两种:val和var,默认是val,比如:
case class User(name:String, pwd:String)
就相当于
case class User(val name:String, val pwd:String)
从翻译的字节码也可看出
{ private final java.lang.String name; descriptor: Ljava/lang/String; flags: ACC_PRIVATE, ACC_FINAL private final java.lang.String pwd; descriptor: Ljava/lang/String; flags: ACC_PRIVATE, ACC_FINAL public java.lang.String name(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #39 // Field name:Ljava/lang/String; 4: areturn public java.lang.String pwd(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #43 // Field pwd:Ljava/lang/String; 4: areturn
所以,默认情况下,case类是不能有成员变量的set方法的。
同时我们也注意到scala编译器自动为User生成了name()和pwd()两个public的get方法。在类之外这样调用:
def testUser = { val u = User("wala", "123") println(u.name + "=>" + u.pwd)}
字节码层面调的其实是name()和pwd()方法,而并非真的在访问类的私有成员:
19: invokespecial #31 // Method scala/collection/mutable/StringBuilder."<init>":()V 22: aload_1 23: invokevirtual #35 // Method com/huawei/test/User.name:()Ljava/lang/String; ...... 34: aload_1 35: invokevirtual #44 // Method com/huawei/test/User.pwd:()Ljava/lang/String; 38: invokevirtual #39 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder; 41: invokevirtual #47 // Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String; 44: invokevirtual #51 // Method scala/Predef$.println:(Ljava/lang/Object;)V 47: return
当然,我们也可以改变默认行为,将类参数设成var:
case class User(var name:String, var pwd:String)
这时,scala编译器就会为我们生成set方法,见以下字节码:
{ private java.lang.String name; descriptor: Ljava/lang/String; flags: ACC_PRIVATE private java.lang.String pwd; descriptor: Ljava/lang/String; flags: ACC_PRIVATE public java.lang.String name(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #39 // Field name:Ljava/lang/String; 4: areturn public void name_$eq(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: putfield #39 // Field name:Ljava/lang/String; 5: return public java.lang.String pwd(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #46 // Field pwd:Ljava/lang/String; 4: areturn public void pwd_$eq(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: putfield #46 // Field pwd:Ljava/lang/String; 5: return
可以看到,在name()和pwd()之外,编译器还为我们生成了name_$eq和pwd_$eq两个set方法。
这样调用:
def testUser = { val u = User("wala", "123") u.name = "chuchu" println(u.name + "=>" + u.pwd) }
相当于调用了name_$eq,而非直接访问成员变量。
非case类的类参数修饰符
非case类的类参数在明确指明了var和val的情形下,行为跟case类是类似的。但若不指明是var还是val,行为比较复杂,有时甚至不会生成成员变量,比如:
class User( name:String, pwd:String)
会为我们生成这样的字节码:
{ public com.huawei.test.User(java.lang.String, java.lang.String); descriptor: (Ljava/lang/String;Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=1, locals=3, args_size=3 0: aload_0 1: invokespecial #13 // Method java/lang/Object."<init>":()V 4: return}
可以看到,没有成员变量,也没有get、set方法,这样的类定义有啥用处?
但也不尽然,看下面的例子:
class User( name:String, pwd:String) { def f = name + "$" def g = pwd + "$"}
生成的字节码如下:
{ private final java.lang.String name; descriptor: Ljava/lang/String; flags: ACC_PRIVATE, ACC_FINAL private final java.lang.String pwd; descriptor: Ljava/lang/String; flags: ACC_PRIVATE, ACC_FINAL public java.lang.String f(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: new #15 // class scala/collection/mutable/StringBuilder 3: dup 4: invokespecial #19 // Method scala/collection/mutable/StringBuilder."<init>":()V 7: aload_0 8: getfield #21 // Field name:Ljava/lang/String; 11: invokevirtual #25 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder; 14: ldc #27 // String $ 16: invokevirtual #25 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder; 19: invokevirtual #30 // Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String; 22: areturn public java.lang.String g(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=2, locals=1, args_size=1 0: new #15 // class scala/collection/mutable/StringBuilder 3: dup 4: invokespecial #19 // Method scala/collection/mutable/StringBuilder."<init>":()V 7: aload_0 8: getfield #35 // Field pwd:Ljava/lang/String; 11: invokevirtual #25 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder; 14: ldc #27 // String $ 16: invokevirtual #25 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder; 19: invokevirtual #30 // Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String; 22: areturn public com.huawei.test.User(java.lang.String, java.lang.String); descriptor: (Ljava/lang/String;Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=3 0: aload_0 1: aload_1 2: putfield #21 // Field name:Ljava/lang/String; 5: aload_0 6: aload_2 7: putfield #35 // Field pwd:Ljava/lang/String; 10: aload_0 11: invokespecial #37 // Method java/lang/Object."<init>":()V 14: return}
scala编译器为我们生成了private final的成员变量,但并未生成任何get、set方法,只是在f、g这样的成员函数里才能访问name和pwd。所以,非case类的类参数未指定var和val时,所起的作用相当于仅生成private成员变量,而无任何的get、set方法。其实,这样的做法在某些场景下更符合数据封装的概念。
- scala类参数修饰符浅析
- Scala访问修饰符
- Scala 访问修饰符
- Scala 访问修饰符
- scala 访问修饰符
- Scala 访问修饰符
- scala修饰符
- scala访问修饰符
- abstract修饰符浅析
- const修饰符浅析
- scala的访问修饰符
- Scala访问控制修饰符
- 六.Scala 访问修饰符
- scala基础-访问修饰符
- C# abstract修饰符浅析
- 浅析java一些修饰符
- 参数修饰符
- .net 参数修饰符
- 洛谷P3383 线性筛素数(线性筛)
- STL(十六)hash_map哈希映照容器
- netty(十七)源码分析之客户端创建
- 插入排序及归并排序java代码实现及详细注释
- Git命令上传和克隆工程
- scala类参数修饰符浅析
- MyBatis 01
- FreeType之字形分析(一)
- 堆
- POJ1700Crossing River(过河问题)
- AsyncTask基本使用
- scala类型系统:1) 类型与类
- 单点登录
- [Android-ARCore开发]ARCore从入门到放弃2-Demo介绍和扩展