tags:

views:

278

answers:

4

The usual way of defining main in Scala (as shown below) can be used to run classes with 'scala', but not 'java' (since the created method is not static). How do I write a Scala class/object that can be executed with 'java'?

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}
+1  A: 

The simplest way, and the one I always use, is to define the object (as you did) but not a corresponding "companion" class. In that case, the Scala compiler will create a pair of classes, the one whose name is precisely the same as the object will contain static forwarding methods that, for the purposes of launcher entry points, are precisely what you need. The other class has the name of your object with a $ appended and that's where the code resides. Javap will disclose these things, if you're curious about details.

Thus your HelloWorld example will work as you want, allowing this:

% scala pkg.package.more.HelloWorld args that you will ignore

Randall Schulz

Randall Schulz
I want to be able to do 'java pkg.package.more.HelloWorld'
IttayD
+5  A: 

javap will in fact show you that your main is static.

javap HelloWorld
Compiled from "HelloWorld.scala"
public final class HelloWorld extends java.lang.Object{
    public static final void main(java.lang.String[]);
    public static final int $tag()  throws java.rmi.RemoteException;
}

Perhaps you just need the Scala jars on your classpath?

There is a similar question here on Stack Overflow: "Creating a jar file from a Scala file".

I just verified this works with the instructions (linked) above.

Just run via:

java -jar HelloWorld.jar
Shaun
+4  A: 

You are incorrect. You can run it with "java", and the reason you gave for not being possible is not true. Here, let me show what is inside "scala".

Unix:

#!/bin/sh
...
exec "${JAVACMD:=java}" $JAVA_OPTS -cp "$TOOL_CLASSPATH" -Dscala.home="$SCALA_HOME" -Denv.classpath="$CLASSPATH" -Denv.emacs="$EMACS"  scala.tools.nsc.MainGenericRunner  "$@"

Windows:

@echo off
...
if "%_JAVACMD%"=="" set _JAVACMD=java
...
"%_JAVACMD%" %_JAVA_OPTS% %_PROPS% -cp "%_TOOL_CLASSPATH%" scala.tools.nsc.MainGenericRunner  %_ARGS%

However, if you happen to have a class with the same name defined, then there's a bug that might be affecting you, depending on the Scala version you are using.

Daniel
Well, it indeed works for a toy example, in my code i have an object inside of a class and the resulting .class does not have a static main method.
IttayD
If you have an object inside of a class (as `class Foo{ object Bar{ def main(args: Array[String]) } }`) then I doubt this will work, for other reasons.
Ken Bloom
This is the bug Daniel was pointing to http://www.eishay.com/2009/05/scalas-main-issue.html
Aswin
A: 

Did you happen to also define a class HelloWorld? There's a bug in Scala 2.7.x that prevents the static methods on the HelloWorld class from being generated when both object HelloWorld and class HelloWorld are defined.

Ken Bloom