1. scala编译后的文件是以什么结尾
scala编译后的文件是以.class结尾。
开头包含类似package声明的scala代码直接在scala命令行用:load指令加载会出错。如果在scala命令行想调用自己在ide写好的类时(大多数情况下你的类会用到外部包,比如spark之类的),有三种方法:
将你在ide写好的project在scala下进行编译,之后通过Main调用。
打包整个项目为jar,通过scala -classpath加载后,在scala中import进行调用。
去掉package声明,并且将依赖包通过scala -classpath加载后,再使用:load 加载你的内容。
2. 大家都用什么scala开发工具
现在的比较流行的scala开发工具都是以前的java IDE添加插件来实现的,比如IntelliJ IDEA或者Eclipse或者NetBean, 我平时用的最多的还是Intellij的,感觉用起来比较舒服,Bug比较少一点,Eclipse的问题还是太多,很多时候会出现莫名其妙的编译错误,但是Eclipse好像是有个scala的官方团队在进行开发,毕竟之前做java开发还是用eclipse的时候多。希望以后eclipse的插件能够更完善吧,2.8.0final之后scala的eclipse插件已经更新到最新版本了,但是Intellij的插件不用更新就能直接用2.8的scala,感觉还是很舒服的,specs和scalatest都能良好运行。
3. java反编译后是scala吗
javap是JDK提供的一个反编译工具。常用的选项有-c -l -s。如果仅仅是想查看编译的得到的字节码文件中函数与变量,不需要带选项。使用javap很容易发现源文件与编译后得到的字节码文件有什么不同,可以加深对编译器的理解。
javap -help
Usage: javap <options> <classes>...
where options include:
-c Disassemble the code
-classpath <pathlist> Specify where to find user class files
-extdirs <dirs> Override location of installed extensions
-help Print this usage message
-J<flag> Pass <flag> directly to the runtime system
-l Print line number and local variable tables
-public Show only public classes and members
-protected Show protected/public classes and members
-package Show package/protected/public classes and members (default)
-private Show all classes and members
-s Print internal type signatures
-bootclasspath <pathlist> Override location of class files loaded by the bootstrap class loader
-verbose Print stack size, number of locals and args for methods If verifying, print reasons for failure
Scala是基于JVM的,所有其字节码和Java编译得到的字节码应该是一致的。首先从Hello World开始
object Main {
def main(args: Array[String]) = {
println("Hello, " + args(0))
}
}
使用scalac编译都得到两个字节码文件:Main.class和Main$.class。
在class文件所在的目录分别运行javap Main和javap Main$得到如下结果:
Compiled from "Main.scala"
public final class Main extends java.lang.Object{
public static final void main(java.lang.String[]);
}
Compiled from "Main.scala"
public final class Main$ extends java.lang.Object implements scala.ScalaObject{
public static final Main$ MODULE$;
public static {};
public void main(java.lang.String[]);
}
Scala的object是单例模式。上面的反编译结果给了我们Scala实现原理的提示。MODULE$指向类的实例,相当于this。而方法也是被声明为静态的。做了一个测试,更加直观。http://stackoverflow.com/questions/2347107/what-is-scala-equivalent-of-javas-static-block说如果不是去发射火箭,Object的代码跟Java的静态代码可以认为是等价的。
把上面的代码稍作修改:
case class Main {
def main(args: Array[String]) = {
println("Hello, " + args(0))
}
}
在class文件所在的目录分别运行javap Main和javap Main$得到如下结果:
Compiled from "Main.scala"
public class Main extends java.lang.Object implements scala.ScalaObject,scala.Proct,scala.Serializable{
public scala.collection.Iterator proctIterator();
public scala.collection.Iterator proctElements();
public void main(java.lang.String[]);
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public java.lang.String proctPrefix();
public int proctArity();
public java.lang.Object proctElement(int);
public boolean canEqual(java.lang.Object);
public Main();
}
Compiled from "Main.scala"
public final class Main$ extends scala.runtime.AbstractFunction0 implements scala.ScalaObject,scala.Serializable{
public static final Main$ MODULE$;
public static {};
public final java.lang.String toString();
public boolean unapply(Main);
public Main apply();
public java.lang.Object readResolve();
public java.lang.Object apply();
}
与输入的文件相比,Scala添加了许多东西:
1. Scala自动帮助Case类生成toString, equals,hashCode等方法。
2. Scala自动帮助Case类生成apply方法,不需要new就可以直接创建类的实例或引用。
3. 对于类的成员,Scala自动生成成员的Getter和Setter。
4. Case类提供对模式匹配的支持。
下面来看Scala对类和隐式转换的处理,有一个Rational类:
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def +(that: Rational): Rational =
new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
def +(i: Int): Rational = new Rational(numer + i * denom, denom)
def -(that: Rational): Rational =
new Rational(numer * that.denom - that.numer * denom, denom * that.denom)
def -(i: Int): Rational = new Rational(numer - i * denom, denom)
def *(that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
def *(i: Int): Rational = new Rational(numer * i, denom)
def /(that: Rational): Rational = new Rational(numer * that.denom, denom * that.numer)
def /(i: Int): Rational = new Rational(numer, denom * i)
override def toString = numer + "/" + denom
private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
}
object Rational{
implicit def intToRational(x: Int) = new Rational(x)
}
javap得到:
Compiled from "Rational.scala"
public class Rational extends java.lang.Object implements scala.ScalaObject{
public static final Rational intToRational(int);
public int numer();
public int denom();
public Rational(int);
public Rational $plus(Rational);
public Rational $plus(int);
public Rational $minus(Rational);
public Rational $minus(int);
public Rational $times(Rational);
public Rational $times(int);
public Rational $div(Rational);
public Rational $div(int);
public java.lang.String toString();
public Rational(int, int);
}
Compiled from "Rational.scala"
public final class Rational$ extends java.lang.Object implements scala.ScalaObje
ct{
public static final Rational$ MODULE$;
public static {};
public Rational intToRational(int);
}
对于普通类,Scala自动添加的东西稍微少一些。一直出现的还有一个特别的函数:public static {};通过带参数-c的javap可以看到其汇编代码:
public static {};
Code:
0: new #9; //class Rational$
3: invokespecial #12; //Method "<init>":()V
6: return
new创建一个对象并将其引用值压入栈顶,invokespecial调用父类的构造方法,return从当前方法返回void。该方法实际上就是一个创建自身的静态方法。Java虚拟机指令参考http://blog.csdn.net/noonlyandroid/article/details/6117470
Rational$中的intToRational是我们提供的隐式类型转换,将一个Int转换为Rational。其汇编代码如下:
public Rational intToRational(int);
Code:
0: new #16; //class Rational
3: p
4: iload_1
5: invokespecial #20; //Method Rational."<init>":(I)V
8: areturn
new首先创建一个Rational对象并将其引用值压入栈顶,p复制栈顶数值并将复制值压入栈顶,iload_1将第二个int型本地变量推送至栈顶,invokespecial调用Rational的构造方法,最后areturn从当前方法返回对象引用。
我们用如下代码来测试隐式类型转换:
import Rational._
object RationalTest {
def main(args: Array[String]) {
val r = new Rational(2,3)
println(2 * r)
}
}
2 * r本身不合法的,因为Int不存在*(Rational)的方法,由于隐式转换的存在,Scala将做一些转换工作。上面程序的汇编代码如下:
Compiled from "RationalTest.scala"
public final class RationalTest$ extends java.lang.Object implements scala.Scala
Object{
public static final RationalTest$ MODULE$;
public static {};
Code:
0: new #9; //class RationalTest$
3: invokespecial #12; //Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
0: new #16; //class Rational
3: p
4: iconst_2
5: iconst_3
6: invokespecial #20; //Method Rational."<init>":(II)V
9: astore_2
10: getstatic #25; //Field Rational$.MODULE$:LRational$;
13: iconst_2
14: invokevirtual #29; //Method Rational$.intToRational:(I)LRational;
17: aload_2
18: invokevirtual #33; //Method Rational.$times:(LRational;)LRational;
21: astore_3
22: getstatic #38; //Field scala/Console$.MODULE$:Lscala/Console$;
25: aload_3
26: invokevirtual #42; //Method scala/Console$.println:(Ljava/lang/Object;
)V
29: return
}
在做乘法($times)之前调用了 intToRational,返回一个Rational对象, 调用Rational对象的*方法已经合法化了。
4. scala 编译完生成两个class文件有何不同
有$符的里边是伴生对象的内容(静态),没$符的里边是类定义的内容(成员)
5. scala命令是怎么编译运行scala程序的
scala命令是怎么编译运行scala程序的
所以既要使用到Unicode的大的字库表,又要节省存储空间,就需要对Unicode再编码,且是根据(Unicode编码.n)内容 不定长编码 --- UTF-8是一种对(Unicode编码.n)的不定长字符编码方案。
UTF-8字符编码方案决定了(Unicode编码.n)在计算机内的存储方式。
(Unicode编码.n)经过UTF-8字符编码方案编码之后也可以看做是一个新的二进制数字,(通常用十六进制数字字符表示这个新的二进制的值,它们直接的关系是这个十六进制字符表示的值 等于 这个二进制数字的值)。
6. scala是编程语言还是脚本语言
按传统,程序语言分编译语言和解释语言。编译语言要把源程序编译成2进制可执行程序再运行。而解释性语言,即所谓脚本语言,不需预先编译,而可在解释器的解释下,直接解释执行。
我不熟悉scala,看上去scala像似 是一种封装式的东西,例如,封装的 java 式的东西 要编译成 bytecode 后执行。 类似 ruby, python 之类的东西也许可以解释执行。scala 好像没有自己的虚拟机,对 scala 的争论 不少。
7. Eclipse中如何实现scala开发环境的构建
1)新建一个目录叫 test
2)在test目录中新建文件build.sbt
3)在test目录新建project目录,进入project目录,并新建plugins.sbt,在其中添加
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.4.0")
4)在build.sbt中配置工程的name,scala编译环境,依赖等等。如:
import sbt._
import Process._
import Keys._
EclipseKeys.createSrc := EclipseCreateSrc.Default + EclipseCreateSrc.Resource
lazy val commonSettings = Seq(
name := "test",
organization := "com.marsyoung",
version := "0.0.1-SNAPSHOT",
scalaVersion := "2.11.7"
)
lazy val root = (project in file(".")).
settings(commonSettings: _*).
settings(
libraryDependencies ++= Seq(
"junit" % "junit" % "4.4",
"javax.ws.rs" % "jsr311-api" % "1.1.1"
)
)
5)在cmd中进入对应的project目录,即test目录。运行sbt。
6)执行eclipse命令,将对应的项目转化成可以引入eclipse开发工具并且目录结构类似maven的项目。
7)打开已经安装了scala ide的eclipse,导入对应的project,会自动的编译成scala peoject.