Java, JavaScript and Jython

When I wrote Java, Groovy and (J)Ruby, Owen Densmore and Lawrence Oluyede suggested that I should include Jython as well. Here it is.... JavaScript and Jython for Java programmers. Note that while I am reasonably comfortable with Java and JavaScript, I don't know much about Jython. If you find anything wrong here, please let me know. I used Jython version 2.1. For JavaScript, I used Rhino 1.6R2 that is co-bundled with JDK 6. The jsr-223 script engine for Jython and many other languages are avaiable at http://scripting.dev.java.net

Feature Java JavaScript Jython
Type System Static with few dynamic checks inserted as needed. Dynamic Dynamic
Comments

/\*
 \* multiline comment
 \*/

/\*\*
 \* javadoc comment
 \*/

// single line comment


/\*
 \* multiline comment
 \*/

// single line comment


# single line comment

No multiple line comments. But, Owen Densmore notes that multiline string literals may be used instead.
Control Statements


if (condition) {
  // statements
}

if (condition) {
  // statements
} else if (condition) {
  // statements
} else {
  // statements
}

while (condition) {
  // statements
}


do {
  // statements
} while (condition);

for (Type t : iterable) {
  // statements
}

for (init; condition; increment) {
  // statements
}

switch (target) {
  case constant_expr:
    // statements
    [break]
  ..
  default:
    // statements
}

\* break can be used in loops to break out of loop.
\* continue statement skips the current iteration of a for, while, or do-while loop and valuates the boolean expression that controls the loop.
\* Labeled break and continue

if (condition) {
  // statements
}

if (condition) {
  // statements
} else if (condition) {
  // statements
} else {
  // statements
}

while (condition) {
  // statements
}

do {
  // statements
} while (condition);

for (init; condition; increment) {
  // statements
}

// for-each statement uses 
// "in" keyword unlike Java

for ([var t in iterable) {
  // statements
}

switch (target) {
  case constant_expr:
    // statements
    [break]
  ..
  default:
    // statements
}
\* null is treated as false.
\* undefined is treated as false.
\* Unlike Java, switch statement works for arbitrary expressions (not just for integral expressions and enums as in Java).
\* break can be used in loops to break out of loop.
\* continue statement skips the current iteration of a for, while, or do-while loop and valuates the boolean expression that controls the loop.
\* Labeled break and continue as in Java are supported.

if expression:
  # statements
elif expression:
  # statements
elif expression:
  # statements
else:
  # statements

\* There can be zero or more 
  elif parts
\* The else part is optional
\* The keyword `elif' is short 
  for `else if'


while expression:
  # statements

Example:
while 1:
  print("hello")

for item in seq:
  # statements

Example:
a = ["Java", "JavaScript", "Jython"]
for x in a:
   print(x)

\* for statement iterates over the items of any sequence (a list or a string)
\* Note that statement grouping is done by indentation. No explicit "{" "}" around group of statements.
\* The break statement, like in Java, breaks out of the smallest enclosing for or while loop.
\* The continue statement, like in Java, continues with the next iteration.
\* do..while is not supported.
\* Loop statements may have an else clause which is executed when the loop terminates normally (i.e., not when "break")

Example:

a = [ "Java", "JavaScript", "Jython"]
for x in a:
   print(x)
else:
   print("done")

String Literals "hello world"

// double-quoted
"hello, world"

// single-quotes are okay too
'hello, world'

\* Need not escape " within single-quoted string
\* Need not escape ' within double-quoted string

"String with double-quotes"

// single-quotes are okay too
'hello, world'

""" A multiple
line string
literals like this
"""

\* Need not escape " within single-quoted string
\* Need not escape ' within double-quoted string
\* Thanks to Owen Densmore for the info. about multi-line string literals
Defining functions Not supported. Everything has to be inside a class. Use static methods instead.

function name(arg1, arg2) {
  // code here
}

function(arg1, arg2) {
  // code here
}

\* functions may be unnamed (anonymous functions)
\* functions are first-class values - can be passed, assigned and returned as values.
\* functions may be nested inside other functions
\* nested function can refer to local variables of the enclosing functions
Examples:

function hello(name) {
   alert("hello, " + name);
}

var greet = function(name) {
   alert("hello, " + name);
}

// call unnamed function
greet("Sundar");

// or even

(function() { alert("hello "); })();

// nested function refers to local of
// enclosing function
function addWith(x) {
  return function(y) { return x + y; }
}

// returned function stored as value
var addTwo = addWith(2);

alert(addTwo(3));

def name(arg1, arg2):
   # code here

# anonymous functions
lambda arg1, arg2: expression

\* functions are first-class values - can be passed, assigned and returned as values.
\* functions may be nested inside other functions
\* nested function can refer to local variables of the enclosing functions [closures]
\* functions may be unnamed (anonymous functions called "lambdas")
\* lambdas are restricted -- the body of lambdas can only be expressions. lambda definition does not include a "return" statement -- it always contains an expression which is returned

def hello():
  print("hello")

# unnamed lambdas
square = lambda x: x\*x
square(10)
print("hello")
Without the "from __future__ import nested_scopes", nested scopes don't work as "expected" normally. This behaviour depends on Python version - refer to What's New in Python 2.1 by A.M. Kuchling and Back to the __future__

# nested function
from __future__ import nested_scopes

def func(x):
    def j(y):
       return x + y
    return j

addTwo = func(2)
print(addTwo(10))

Class Declaration

class Foo {
    // methods
    // fields
}


JavaScript supports prototype-based object orientation. No direct support for classes. JavaScript supports first -class functions. Any function can serve as object constructor.

An object is an associative array - with keys being either string or integer. The values could be strings, numbers, object or even function (which then becomes a "method" of the object).


// a constructor function "Person"
// to create Person objects
function Person(name, age) {
   // this.foo introduces
   // new object fields.
   this.name = name;
   this.age = age;
}

There is JavaScript framework called "Prototype" that supports class based object orientation with JavaScript.

// create a new Class with Class.create
var Person = Class.create();

// add methods to the new Class created
Person.prototype = {
   initialize: function(name) {
      this.name = name;
   },
   greet: function() {
      println("Hello from " + this.name);
   }
};	


class Name:    
    # methods here

Example:

class Person:
  print("class Person")


class Person:
  def greet(self):
    print("hello world")   

Classes can have executable statements (like print call in above example).
Instance Variables

int i;
float f;
double d;
String s;

No need to declare instance variables. No special syntax for instance variable names. Just introduce instance variable by

obj.fieldName = Expression

Typically, constructor functions initialize instance variables. All fields are "public". If you want private instance variables and methods, you may want to read Private Members in JavaScript
No need to declare instance variables. No special syntax for instance variable names.

obj.fieldName = Expression

Example:

class Person:
  def setName(self, name):
    print("setting name as " +name);
    self.name = name

Static Variables

static int i;
static float f;

static double d;
static String s;

There are no classes in JavaScript. But, every object has a prototype -- identified by a special property (or field) called __proto__. The prototype property is set when the object is created and this property can be changed later if needed. The "static" fields can be stored in the prototype object.

function Person(name, age) {
  this.name = name;
  this.age = age;
  // increment the "static" count field
  this.__proto__.count++;
}

// introduce a static "count" field
Person.prototype.count = 0;

// create two Person objects
p1 = new Person()
p2 = new Person()

// now check the Person count
println(Person.prototype.count);

// or equivalently - because 
// prototype is searched if a field 
// is not found in
// object!
println(p1.count);
You may want to read Private Static Members in Javascript as well.
Class variables are declared within the "class".

class Person:
  # "static" field
  count = 0
  def __init__(self):
    Person.count += 1

# print static field value
print(Person.count)

# create two Person objects
p1 = Person()
p2 = Person()

# now print the count
print(Person.count)

Note: Unlike Java, all variables declared inside class declaration are class variables. Instance variables are initialized only within the instance methods.
Global Variables Not supported. Use public static final variables in a class or use enum as appropriate. Top-level variables are supported. No special naming enforced. No need to declare and can be "defined" by initialization. Actually, the "globals" are contained in "Global" object - which contains all "global" definitions - variables and (global) functions. "this" in glabal scope refers to Global object. Top-level variables are supported. No special syntax for global variable names.
Method Definition
class Person {
  public void greet() {
    System.out.println("hello");
  }
}
To define an instance method: add a function valued property to prototype [of the constructor function]
function Person(name) {
  this.name = name;
}

Person.prototype.greet =
  function() {
    println("hello from " + this.name);
  }
class Person:  
  # additional "self" 
  # parameter for 'this'
  def greet(self):
    print("hello world")
Note: Unlike Java and JavaScript, you have to specify special "self" parameter explicitly.
Static Method Definition
class Person {
  public static void greet() {
    System.out.println("hello");
  }
}
There are no classes in JavaScript. But, every object has a prototype -- identified by a special property (or field) called __proto__. You may want to read Private Static Members in Javascript for variety of way to code static members. You may want to read The Static Method Thing
Returning from a method

return expression;
return;


return expression;
return;


return expression;
return;

Object Creation
Person p = new Person();
var p = new Person();
Use class name like as a function name.
class Person:
  # statements

# create a new Person object
p = Person();
Method Call
obj.foo(param1, param2);
p.greet();
obj.foo(param1, param2);
p.greet();
obj.foo(param1, param2);
p.greet();
Referring to the current object this this self
Object Initialization
class Person {
  // declare constructor method
  // same as class name
  public Person() {
    // initialize new object here
  }
}
Objects are created by constructor functions!
function Person(name, age) {
  this.name = name;
  this.age = age;
}

var p = new Person();
class Person:
  # declare constructor method 
  # with the name __init__
  def __init__(self):
    # initialize new object here
    self.name = name;
    # initialize new object here
    print("I'm " + self.name);

p = Person("Sundar")
Extending another class

class Employee extends Person {
}

Every JavaScript has a prototype. This can be accessed via __proto__ field. When a property is not found in an object, it's prototype is searched. If not, prototype of the prototype is searched and so on - till prototype chain ends with an object with null __proto__. You can have Classical Inheritance in JavaScript or use JavaScript "Prototype" framework.

class Name(Base1, Base2):
  # code here

\* Jython supports multiple inheritance. User specifies zero or more superclasses within the parans just after the class name.
Null null null None
Arrays
int a[] = new int[10];
String[] s = new String[2];
a[0] = 3;
s[0] = "hello";

var a = new Array(10);
a[0] = 3;
a[1] = "hello";
println(a[0]);
println(a[1]);

# use lists
x = []
x.append(3)
x.append("hello")
print(x[0])
print(x[1])

Array Literals
int a[] = { 10, 4354, 432 }
String[] s = { "dsjfhsd", "sdfsd"}
a[0] = 3;
s[0] = "hello";

a = [2, 3, 4354]
s = ["hello", "world"]

print(a[2]);
print(s[0]);

a = [3, 4, 546]
a[0] = 3
a[1] = "hello"
print(a[0])
print(a[1])

Array length arr.length

arr.length
// but length can be assigned as well!
arr.length = 10
// array "index" can be strings -- 
// objects are associative arrays.
// arrays are objects with (mostly)
// "integer" property names
var arr = []
arr["Sun"] = "Network"
println(arr["Sun"])
println(arr.Sun)

len(arr)
Hash Literals Not supported Use JavaScript Object Literals. Objects are associative arrays.

var o = { key: value, key1: value1 }

Examples:

o = { 
      hello: "world", 
      Sun: "Network"
   }

println(o["Sun"]);

// field access syntax
println(o.Sun);


o = { key: value,
      key1: value1 }

Examples:

o = { 
      'hello': "world", 
      'Sun': "Network"
   }

print(o['hello'])
print(o['Sun'])

varargs methods Use JDK 1.5+. The "..." after the last formal argument means this is a vararg method.
class Person {
 public void greet(Object...args) {
  // access the "args" array here
 }
}
JavaScript functions can accept any number of arguments. "arguments" object is filled with all arguments.
function vararg() {  
 var i = 0
 for (i < arguments; i++) {
  println(arguments[i]);
 }
}
def greet(\*args):
  print args

greet("hello")
greet("hello", "world")
The "excess" args are packed as tuple and passed.
Keyword arguments (a.k.a Named Parameters Not supported Not supported. You can accept Object but pass Object literals from caller.

// function that accepts an object
function greet(arg) {
  println(arg.msg + 
          ", " + arg.name);
}

// caller passes object 
// literals with matching 
// "properties"
greet({ msg: "Hello", 
        name: "Sundar" })
greet({ name: "Sundar", 
        msg: "Hello" })

Functions can be called with keyword arguments of the form "keyword = value"

def greet(name, msg):
  print msg + ", " + name

greet(name="Sundar",msg="Hello");

Operator Overloading Not supported - except for built-in String + operator Not supported - except for built-in String + operator Specially named operator methods are defined by class author.

class Complex:
  def __init__(self, x, y):
    self.real = x
    self.imag = y

  def __add__(self, other):
    return Complex(
      self.real + other.real,   
      self.imag + other.imag)

  def print(self):
    print "real = ", self.real
    print "imag = ", self.imag

c1 = Complex(2, 3)
c2 = Complex(3, 2)
c = c1 + c2
c.print()

Referring to super class method super.foo(); JavaScript supports prototypes for objects. It is possible to get any method anywhere in the prototype chain (for example: obj.__proto__.__proto__.func where "func" is a function valued property defined in the prototype of prototype of obj) and then explicitly apply that on "this" object.

class Person:
  def greet(self):
    print "Person's greet"

class Employee(Person):
  def greet(self):
    print "Employee's greet"
    Person.greet(self)

e = Employee()
e.greet()

Exception Handling

try {
  // statements
} catch(Exception e) {
  // statements
} finally {
  // statements
}


Exception handling is similar as Java - except that anything (including string, number) can be thrown. Also, catch clause cannot specify "exception type". But as lopex comments, there may be multiple catch clauses (which seems to be an extension of the ECMAScript-262 standard).

try {
  // statements
} catch(e) {
  // statements
} finally {
  // statements
}

try {
   // code that could throw three exceptions
} catch (e if e == "IOException") {
   // handler for IOException
} catch (e if e == "EOFException") {
   // handler for EOFException
}

Thanks to lopex for notifying the multiple catch clauses.

try:
  # code that could throw exceptions
except IOError, (errno, strerror):
  # hadler for IOError
except ValueError:
  # handler for ValueError
except:  
  # handler for any-other Error
else:
  # code that will be executed if
  # exception was not thrown

Thanks to Lawrence Oluyede for clarifying the "else:" usage. So "else:" clause code is executed only if exception was not thrown in try block. There is also finally: clause -- similar to finally in Java. See Lawrence Oluyede's comment in this entry for CPython/Jython version specific behaviour. Also, you may want to refer to Errors and Exceptions section of the Python tutorial as well.
Modules, Namespaces

package com.acme.foo;

import java.net.\*;

// or import a specific class
import java.net.URL;

There may be future improvements in this area.
No explicit support for modules/packages. Use objects for everything. For example, you may use this idea. Or similar to the package system of Dojo. Similarly, Phobos webapp framework has it's own namespace support for JavaScript.

A Python module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended. Within a module, the module's name is available as the value of the global variable __name__.


# importing a module
import mymodule

# or import only specific stuff
from mymodule import func, func2

Refer Modules section of Python tutorial.
Comments:

[Trackback] i wonder how many j\* languages are out there… a.sundararajan, who wrote the syntax comparision between java, groovy and jruby, i’ve suggested you before (and before), came up with a jython companion today. additionally he also compares java...

Posted by stotti.blog() on September 26, 2006 at 10:56 AM IST #

using javascript one can specify exception type (there is a special syntax for that): try{ throw 1; }catch(e if typeof(e)=="number"){ print("got ya"); }

Posted by lopex on September 26, 2006 at 08:34 PM IST #

Python/Jython allow multiline strings to be comments. And when the first entry in a class or function, become doc-comments.
So adding

"""
This is a multi-
line comment
"""

to a jython program should work just fine.
.. And thanks for adding the new entry for Jython!
Owen

Posted by Owen Densmore on September 27, 2006 at 01:34 AM IST #

Great Mr. Sundararajan, only a small thing. The try...except construct is a little wrong. The "else:" part is not the finally in Java/C#/whatever but it's executed only when no exception are raised. So if an exception is raised "else:" won't be executed. There's a "finally" keyword for that. The oddness is in Jython (and CPython < 2.5) you can't use try...except...finally in a single construct but you have to embed the try...except in a try...finally to be sure the finally gets always executed no matter what. Since Python 2.5 (released a few days ago) this has been finally fixed and try...except...finally can be used in a single construct like every other language I know of. Jython does not support that anyway. HTH Lawrence Oluyede

Posted by Lawrence Oluyede on September 27, 2006 at 07:37 AM IST #

Is there an official jsr-223-api.jar that one can use as a JDK extension for Java 5?

Posted by Mike Norman on September 27, 2006 at 11:43 AM IST #

Hi Mike Norman: There will soon be a script-api.jar in JSR-223 site (http://jcp.org/en/jsr/detail?id=223).

Posted by A. Sundararajan on September 27, 2006 at 11:50 AM IST #

Post a Comment:
Comments are closed for this entry.
About

sundararajan

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Bookmarks
Links

No bookmarks in folder

Blogroll

No bookmarks in folder

News

No bookmarks in folder