java字符串不确定参数个数,scala 学习笔记(03) 参数缺省值、不定个数参数、类的属性(Property)...

本文通过对比Scala和Java,揭示了Scala在参数默认值、类属性以及不定个数参数等方面的便利性。Scala允许在方法中直接设定参数默认值,类属性的定义更为简洁,且支持不定个数参数的优雅表示。通过反编译,可以看出这些特性在编译器层面即可实现,但Java并未提供相应的内置支持。这展示了Scala在语言设计上的先进性和灵活性。
摘要由CSDN通过智能技术生成

继续学习,这一篇主要是通过scala来吐槽java的,同样是jvm上的语言,差距咋就这么大呢?

作为一个有.NET开发经验的程序员,当初刚接触java时,相信很多人对java语言有以下不爽(只列了极小一部分):

1. 一堆的setter/getter方法,没有c#中的property属性概念

2. 方法的参数值,不能设置缺省值

3. 不定个数参数的写法太单一

...

然后java的拥护者讲出一堆大道理,说这样设计是如何如何有道理,各种洗脑,时间长了,也就被迫习惯了。要不是遇到scala,我还真就信了,你看看人家scala同学,2003/2004发布的,早就把这些全实现了,而java同学作为jvm上的元老,这些年一直顽固不化,不思进取,已经被jvm上的其它同学远远甩在后面了,java你可长点心吧!进入正题,直接上码:

一、参数缺省值

/**

* 参数缺省值

* @param person

* @param msg

*/

def saySomething(person: String = "somebody", msg: String = "Hello") = {

println(person + " say : " + msg);

}

调用示例:

saySomething()

saySomething("jimmy")

saySomething("jimmy", "hi")

那么,最终编译出来的class,到底是如何实现的呢?可以借助一些反编译工具,比如JD-GUI还原成java一看究竟:

public void saySomething(String person, String msg) {

Predef..MODULE$.println(new StringBuilder().append(person).append(" say : ").append(msg).toString());

}

public String saySomething$default$1() {

return "somebody";

}

public String saySomething$default$2() {

return "Hello";

}

也就是说,scala中的defsaySomething(person: String = "somebody", msg: String = "Hello")如果用java实现的话,可以用3个方法来变相实现,每个缺省参数,相当于一个独立的版本,换言之,在编译器层面,其实java的编译器如果想做,是完全可以做到的,为什么不做?懒!顽!

二、class的property

/**

* 定义一个带参主构造器的类

* @param pReadOnly

*/

class Sample(pReadOnly: String) {

/**

* 可读写的属性

*/

var myProperty: String = _;

private val _readOnly: String = pReadOnly;

/**

* 只读属性

*/

val readOnly: String = _readOnly;

}

调用示例:

val sample = new Sample("test")

println(sample.readOnly)

sample.myProperty = "a new value"

println(sample.myProperty)

没了setter/getter看起来倍儿清爽!还是反编译class看看:

1 public classSample {2 privateString myProperty;3 private finalString _readOnly;4 private finalString readOnly;5

6 publicString myProperty() {7 return this.myProperty;8 }9

10 public void myProperty_$eq(String x$1) {11 this.myProperty = x$1;12 }13

14 privateString _readOnly() {15 return this._readOnly;16 }17

18 publicString readOnly() {19 return this.readOnly;20 }21

22 publicSample(String pReadOnly) {23 this._readOnly =pReadOnly;24

25 this.readOnly =_readOnly();26 }27 }

可以看到,myProperty自动生成了setter/gettter,仍然是在编译器层面,就可以顺手做掉的事情,java编译器依然不肯做。

三、不定个数参数值

这个问题,java中虽然可以xxx(String[] args)用数组传递达到类似的效果,但是就算传一个空数组,也至少也得写一个xxx(null)吧,既然此时参数都为空了,为啥不直接xxx()更直接,看看scala:

/**

* 不固定个数的参数

* @param x

* @return

*/

def add(x: Int*) = {

var i = 0

for (j

i

}

调用:

println(add())

println(add(1, 2, 3, 4, 5))

明显的更高端大气上档次,继续反编译,这个要略复杂点:

先是生成了这么一个类:

public final class DefHello$$anonfun$add$1 extends AbstractFunction1.mcVI.sp

implements Serializable

{

public static final long serialVersionUID = 0L;

private final IntRef i$1;

public final void apply(int j)

{

apply$mcVI$sp(j); }

public void apply$mcVI$sp(int j) { this.i$1.elem += j; }

public DefHello$$anonfun$add$1(IntRef i$1)

{

}

}

然后是:

public void main(String[] args)

{

Predef..MODULE$.println(BoxesRunTime.boxToInteger(add(Nil..MODULE$)));

Predef..MODULE$.println(BoxesRunTime.boxToInteger(add(Predef..MODULE$.wrapIntArray(new int[] { 1, 2, 3, 4, 5 }))));

...

}

public int add(Seq x)

{

IntRef i = IntRef.create(0);

x.foreach(new AbstractFunction1.mcVI.sp() { public static final long serialVersionUID = 0L;

public final void apply(int j) { apply$mcVI$sp(j); }

public void apply$mcVI$sp(int j) { DefHello..this.elem += j; }

});

return i.elem;

}

最终调用时,add()这里虽然scala没有传任何参数,但从反编译结果上看,最终还是变成了add(Nil..MODULE$)),编译器自动加了一个参数,以满足java的规范。

原文:http://www.cnblogs.com/yjmyzz/p/4714558.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我了解了你的问题。以下是Scala定义一个Utils,包含printNames方法的代码: ```scala class Utils { def printNames(names: String*): Unit = { if (names.nonEmpty) { println("打印不定字符串:") names.foreach(println) } else { println("未提供需要打印的字符串!") } } def printNames(numbers: Int, names: String*): Unit = { if (names.nonEmpty) { println(s"打印整数和不定字符串:$numbers") names.foreach(println) } else { println("未提供需要打印的字符串!") } } def printNames[T](names: Iterable[T]): Unit = { if (names.nonEmpty) { println("打印集合中的元素:") names.foreach(println) } else { println("未提供需要打印的元素!") } } def printNames(): Unit = { println("未提供任何参数,无法打印!") } } ``` 现在,我们定义了一个Utils,包含了四个不同的printNames方法: - 接受不定字符串 - 接受一个整型和不定字符串 - 接受集合 - 不传递任何参数 你可以创建一个Utils的实例,并调用其中的一个或多个printNames方法来打印接收到的参数。例如: ```scala val utils = new Utils utils.printNames("张三", "李四", "王五") // 输出: 打印不定字符串: // 张三 // 李四 // 王五 utils.printNames(123, "张三", "李四", "王五") // 输出: 打印整数和不定字符串:123 // 张三 // 李四 // 王五 utils.printNames(List("张三", "李四", "王五")) // 输出: 打印集合中的元素: // 张三 // 李四 // 王五 utils.printNames() // 输出: 未提供任何参数,无法打印! ``` 希望这个回答能够满足你的需求!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值