Scala - Combining Scala and Java
2013-07-07 00:00
169 查看
Scala code is highly compatible with Java, most of time you can combine the languages worrying very much. The chapter will describe two aspects of combining Java and Scala. Firstly, it discussess how Scala is translated to Java which is important if you call Scala code from Java and secondly, it discusss the use of Java annotation in Scala, an important feature if you wan to to use Scala with existing Java framework.
Given a simple example, suppose that you have the followig code.
Additional effects from standard annotations
several annotation cause the compilter to emit extra information when targeting Java platform. It first process it according to the general Scala rules, and then it does something extra for it
@serializable: @SerialVersionUID(1234L)
when it is compiled, you will see that from the javap command.
Scala does not check for exception , unlike the Java language, however, all Scala methods are translated to Java methods that declare no throws exceptions. to interface with Java, you might want to declare the method throw exceptions .. here is what you have .
and how do you instruct java system that you code may throws exceptions that the java code can add handler tro those exceptions.
A note that we may use to build the code is like this:
for java types, you have Iterator<Component> in Java and Iterator<Component> in Scala, but what for the type Iterator<?> or Iterator<? extends Component> or even raw type Iterator.
We have the existential type. as follow.
Java Iterator<?> would be written in Scala as :
Java Iterator<? extends Component> would be written in Scala as :
similarily, you you can write the following placeholder syntax as follow.
to test the placeholder and the existential type, we write the following java code.
When apssing an existential type into a method, move type parameter from the forSome to type parameter of the method, Inside the body of the method. Inside the body of the method, you can use the type parameter to refer to the types that were in the forSome clause.
Instead of returning an existential type from a method, return an object that has abstract for each of the tyeps in the forSome clause.
Using Scala from Java
General rule
Scala feature maps dierectly onto the equivalent java features, scala classes, methods, strings, exception, for examples, are all compiled to te same Java bytes as their Java counterparts. Scala trait does not have equivalent in java, Scala generic is different from Java one.Value types
a value type like Int can be transalted in two different ways to Java, whenever possible, 1. to java int to get better performance, 2. to Wrapper classes java.lang.Integer when it is has to be wrapped to inside a Java object .Singleton object
there is noting like the signleton object in Java, and how does the compiler translate it to java code.Given a simple example, suppose that you have the followig code.
object App { def main(args : Array[String]) { println("hello, world!") } }and if you run some javap command.
// in scala 2.9.1. if you have just the object app, this is what you get the from the javap javap app.class Compiled from "31_1_UsingScalaFromJava.scala" public final class App { public static final void main(java.lang.String[]); } javap app$.class Compiled from "31_1_UsingScalaFromJava.scala" public final class App$ implements scala.ScalaObject { public static final App$ MODULE$; public static {}; public void main(java.lang.String[]); }and if you have a App class, then you compile them to examine the byte code you will get.
class App { }and you run the javap code ,you will get.
// and if you have a App class above, with javap javap App.class Compiled from "31_1_UsingScalaFromJava.scala" public class App implements scala.ScalaObject { public static final void main(java.lang.String[]); public App(); } javap App$.class Compiled from "31_1_UsingScalaFromJava.scala" public final class App$ implements scala.ScalaObject { public static final App$ MODULE$; public static {}; public void main(java.lang.String[]); }
Trait as Interfaces
if the trait has no members, then it will be translated to java interface, while if otherwise.Annotations
we have some standard annotation, and we will introduce on how them apply on the scala code.Additional effects from standard annotations
several annotation cause the compilter to emit extra information when targeting Java platform. It first process it according to the general Scala rules, and then it does something extra for it
Deprecation
@deprecationVolatile fields
@volatile field , scala has the same semantic towards the java semantics@serializable: @SerialVersionUID(1234L)
An example on the SerialVersionUID.
@serializable @SerialVersionUID(1234L) class SeriazableClass {}
when it is compiled, you will see that from the javap command.
// when compiled // the @SerialVersionUID(1234L) will be converted to the following java Field definition /*javap SeriazableClass.class Compiled from "31_2_Annotations.scala" public class SeriazableClass implements scala.ScalaObject,scala.Serializable { public static final long serialVersionUID; public static {}; public SeriazableClass(); }*/Exception throw
Scala does not check for exception , unlike the Java language, however, all Scala methods are translated to Java methods that declare no throws exceptions. to interface with Java, you might want to declare the method throw exceptions .. here is what you have .
and how do you instruct java system that you code may throws exceptions that the java code can add handler tro those exceptions.
import java.io._ class Reader (fname : String) { private val in = new BufferedReader(new FileReader(fname)) @throws (classOf[IOException]) def read = in.read() }and if you check the compiled bytecode.
// you will have this on the compiled code. // /*javap Reader.class Compiled from "31_2_Annotations.scala" public class Reader implements scala.ScalaObject { public int read() throws java.io.IOException; public Reader(java.lang.String); }*/
java annotations
as an example of other java annotation (other than those standard annotation such as @deprecation which is an instruct to compiler), let's take the Junit's @Test annotation for example.// Java annotations // import org.junit.Test import org.junit.Assert.assertEquals class SetTest { @Test def testMultiAdd { val set = Set() + 1 + 2 + 1 + 2 + 3 assertEquals(3, set.size) } }Compile and run it, you get the following.
scalac -cp junit-4.11.jar;.;hamcrest-core-1.3.jar SetTest.scala scala -cp junit-4.11.jar;.;hamcrest-core-1.3.jar SetTest when run it scala -cp junit-4.11.jar;.;hamcrest-core-1.3.jar org.junit.runner.JUnitCore SetTest JUnit version 4.11 . Time: 0.366 OK (1 test)
writing you own annotations
now we are going to create our own annotations, like the below.// file // Ignore.java // description: // show you how you can create a Java annotation import java.lang.annotation.*; import java.lang.annotation.ElementType; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Ignore { }and we write the following scala code.
// suppose we have the Ignore annotation declare in Java object Tests { @Ignore def testData = List(0, 1, 1, 5, -5) def test1 { assert(testData == testData.head :: testData.tail) } def test2 { assert(testData.contains(testData.head)) } }and we write a function that finding the Tests.
object FindTests { def main(args : Array[String]) { for { method <- Tests.getClass.getMethods if method.getName.startsWith("test") if method.getAnnotation(classOf[Ignore]) == null } { println("found a test method : " + method) } } } /*$ scala FindTests found a test method : public void Tests$.test1() found a test method : public void Tests$.test2()*/
A note that we may use to build the code is like this:
$javac Ignore.java $scalac Tests.scala $scalac FindTests.scala $scala FindTests
Existential Types
forewordfor java types, you have Iterator<Component> in Java and Iterator<Component> in Scala, but what for the type Iterator<?> or Iterator<? extends Component> or even raw type Iterator.
We have the existential type. as follow.
// existential type are fully supported in Scala, type forSome { declaration }the {declaration} part is a list of abstract vals and types. the interpretation is that the declared variable and types exist but are unknown, just like abstract members of a class.
Java Iterator<?> would be written in Scala as :
type forSome { type T}
Java Iterator<? extends Component> would be written in Scala as :
type forSome { type T <: Component>}placeholder syntax. it means the same as the type forSome { declaration } (with the type forSome { type T}
Iterator[_]
similarily, you you can write the following placeholder syntax as follow.
Iterator[_ <: Component]for the declaration as follow for the code is as follow. "type forSome { type T <: Component>}"
to test the placeholder and the existential type, we write the following java code.
import java.util.Collection; import java.util.Vector; // FIle // Wild.java // Description: // this show you a java class with Wildcard public class Wild { public Collection<?> contents() { Collection<String> stuff = new Vector<String>(); stuff.add("a"); stuff.add("b"); stuff.add("see"); return stuff; } }and with this, we can test with the following scala code.
// run it with the following commands // scala // :cp . // val contents = (new Wild).contents val contents = (new Wild).contents contents.size()this is a no-brainer. however, let's see a more convoluted example as follow.
// a more complicated examples is as follow. import scala.collection.mutable.Set val iter = (new Wild).contents.iterator val set = Set.empty[???] // quandry here , what we fill in here while (iter.hasMore) set += iter.next()as above, what value we provide in the ??? place? there are two solutions to attack this problem.
When apssing an existential type into a method, move type parameter from the forSome to type parameter of the method, Inside the body of the method. Inside the body of the method, you can use the type parameter to refer to the types that were in the forSome clause.
Instead of returning an existential type from a method, return an object that has abstract for each of the tyeps in the forSome clause.
import scala.collection.mutable.Set import java.util.Collection abstract class SetAndType { type Elem val set : Set[Elem] } def javaSet2ScalaSet[T](jset : Collection[T]): SetAndType = { val sset = Set.empty[T] val iter = jset.iterator while (iter.hasNext) sset += iter.next() return new SetAndType { type Elem = T // not val Elem = T val set = sset } }so in general, when programming against Scala, prefer abstract member instead of existence type.
using synchronized
for compatibility's sake, Scala provides access to Java's concurrency primitives, the wait, notify, and notifyAll methods can be called in Scala, and they have the same meaning as in Java, Scala doesn't technically have a synchronized keyword, but it includes a predefined synchronized method that can be called as follow.var counter = 0 synchronized { // One thread in here at a time counter = counter + 1 }
Compiling Scala and Java together
scalac has support to compile against Java Source code as well as Java calss. scalac compiler won't compile those source code, but it will scan them to see what they contains. later you can compile those java code with those Scala source code.scalac -d bin InventoryAnalysis.scala InventoryItem.java Inventory.java javac -cp bin -d bin Inventory.java InventoryItem.java InventoryManagement.java scala -cp bin InventoryManagement
相关文章推荐
- LeetCode with C++ and Java and little Scala (持续更新)
- Scala, Groovy, Clojure, Jython, JRuby and Java ----我们的工作语言
- Scala, Groovy, Clojure, Jython, JRuby and Java ----我们的工作语言
- Akka Reaches 1.0 Status: Brings the Actor Model to Java and Scala
- Beginning Scala study note(9) Scala and Java Interoperability
- Java Wish List: The Top Differences Between Java, Scala, Groovy, Clojure and Kotlin
- Simple TcpClient and TcpServer in Java
- 《Data Structures and Algorithm Analysis in Java》Second Edition中文版笔记
- Java Reflection(六):Getters and Setters
- java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' 异常处理,及MySQL数据库编码设置
- HDU 1313 Round and Round We Go (Java大数)
- Java string and memory leaks
- Java IO reader and writer
- Fork and Join: Java Can Excel at Painless Parallel Programming Too!---转
- Java theory and practice: Fixing the Java Memory Model, Part 2
- Make sure you have Java JDK or JRE installed and the required ports are free
- Java (J2SE 5.0) and C# 比较
- Microsoft and Java Integration with Eclipse(转载)
- POJO and javaBean
- Reading and writing files in Java (Input/Output) - Tutorial