Last update July 15, 2009

Java To D



Difference (last change) (no other diffs, normal page display)

Changed: 1c1
see also NotesForProgrammersUsedTo/JavaLanguage
see also ComingFrom/Java

Added: 18a19,20
[[toc]]


Deleted: 101,102d102
This last form is usually recommended. (Note !== and === are deprecated instead use !is and is)


Changed: 105c105
One-dimensional dynamic arrays are declared and initialised in the same way as Java arrays. It is possible to change the length of a dynamic array without reallocating it:
One-dimensional dynamic arrays are declared and initialised in the same way as Java arrays. It is possible to change the length of a dynamic array and the compiler may resize it in place or reallocate moving the elements:

Changed: 159c159,166
The 'char' data type in Java is called wchar in D, as the D 'char' type is for storing ASCII characters.
D uses a 'char' arrays to represent a string. The Java 'char' is equivalent to D's 'wchar'. For information on UTF and how they are used in D read Text in D.

To store a UTF-32 code point Java uses 'int', as introduced in JDK version 1.5, D uses 'dchar'.

D uses a alias of 'string' to a 'char[]' While wchar is the equivalent to a Java 'char' using 'string' in D is what you want. A 'char[]' is modifiable in D unlike a Java string.



```D2.x```

Changed: 161,162c168,169
Technically the char type in D stores an UTF-8 code unit, and wchar stores an UTF-16 code unit (just like char in Java).
To store *any* Unicode code point, you use UTF-32 encoding: the 'dchar' type in D. Java uses 'int' for this, as introduced in JDK version 1.5.
'string' is an alias to 'immutable(char)[]' which means strings can't be modified.



Changed: 164c171,177
The String class in Java is replaced by a dynamic array wchar[] (UTF-16), in D. The default string type in D is char[] (UTF-8). Strings are concatenated with ~ instead of +. You can only concatenate strings with other strings and characters, not with arbitrary objects. D strings can be modified, unlike Java. To compare strings, use the relational operators <pre>== != < <= > >= </pre>.
Concatenation:

In Java + is used to concatenate strings an other objects. D uses ~ and only allows concatenation with other strings.

Comparison:

Java does comparison with method calls to compareTo and equals. In D comparison is done with relational operators <pre>== != < <= > >= </pre>.

Changed: 208c221
D has built-in associative arrays (also known as "dictionaries" or "maps")
D has built-in associative arrays (also known as "hashtables", "dictionaries" or "maps")

Changed: 230c243
Input and output is defined in the standard library. The default, Phobos, uses the std.stdio or std.stream modules. Many people switch and use Tango, which uses tango.io.Console.
Input and output is defined in the run-time library. The default, Phobos, uses the std.stdio or std.stream modules. Many people switch and use Tango, which uses tango.io.Console.

Changed: 264c277
Note:: D v2.0 has introduces the concept of const and invariant. This causes const to have a slightly different meaning. As this tutorial concentrates on D v1.0 for more information visit Const and Invariant.
Note:: D v2.0 has introduces the concept of const and immutable. This causes const to have a slightly different meaning. As this tutorial concentrates on D v1.0 for more information visit Const and Invariant.

Changed: 423c436
[[code]int main(char[][] args)]
[[code]int main(char[][] args) {}]

Changed: 426c439,441
[[code]public static void main(String[] args)]
[[code]public class ClassName? {
public static void main(String[] args) {}
}]

Changed: 428c443
By convention, the return value of main is zero ("<n>{EXIT SUCCESS}?</n>" constant) if the program completed successfully, a non-zero integer (such as the "{EXIT FAILURE}?" constant) otherwise.
By convention, the return value of main is zero ("<n>{EXIT SUCCESS}?</n>" constant) if the program completed successfully, a non-zero integer (such as the "<n>{EXIT FAILURE}?</n>" constant) otherwise.

see also ComingFrom/Java

Converting Java to D    

Programming in D for Java programmers.

NameVersion
Java(JDK 1.0.2)
Java(JDK 1.1.8)
Java 2(JDK 1.3.1)
Java 2(JDK 1.4.2)
J2SE version 5.0(JDK 1.5.0)
Java SE 6 ("Mustang") 

Table of contents of this page
Converting Java to D   
Data Types   
Numbers   
Booleans   
Arrays   
Strings   
Associative Arrays   
Input and Output   
Variables   
Classes   
Properties   
Null Pointers   
Casting   
Pointers   
References   
Functions   
Structs and Unions   
Conditional Compilation   
Aliases and Typedefs   
Enumerated Types   
Templates and Mixins   
Assertions   
Contracts   
JavaDoc   
Unit Testing   
Field Initialization   
Inner Classes   
Synchronization   
Related Projects   

Data Types    

D 1.x, D 2.x

Numbers    

The data types in D are similar to those in Java, and : byte, short, int, long, float, double are identical

byte
short
int
long

float
double

Integers are also found in unsigned (u) alternatives: (all integer types in Java are signed)

ubyte
ushort
uint
ulong

There is also support for imaginary (i) and also complex (c) numbers:

float  // real
double
ifloat // imaginary
idouble
cfloat // complex (= real + imaginary)
cdouble

There is an 'extended' floating point data type, which can store 80-bit floats (if the hardware allows it) 'real' represents the largest available hardware floating point type: usually double (64) or extended (80) but can also be quad (128) which stands for quadruple precision as per the IEEE specifications.

Booleans    

The boolean data type is called 'bool' in D.

In boolean contexts, zero and null have the value of false, and not-zero and not-null have the boolean value of true.

This means that the integer types (e.g. byte, int) can also be used for storing boolean values in D.

This D code:

bool b;
int i;
Object o;

if (b) ...
if (i) ...
if (o) ...

Means the same as the Java code:

boolean b;
int i;
Object o;

if (b) ...
if (i != 0) ...
if (o != null) ...

This similar code will also work in D:

bool b;
int i;
Object o;

if (b) ...
if (i != 0) ...
if (o !is null) ...

Arrays    

One-dimensional dynamic arrays are declared and initialised in the same way as Java arrays. It is possible to change the length of a dynamic array and the compiler may resize it in place or reallocate moving the elements:

int[] list = new int[3];
list.length = 4;
list[3] = 42;

Missing feature: Nested dynamic arrays cannot be fully allocated in a single statement. Thus the Java code

int[][] matrix = new int[3][4];
matrix[2][3] = 69;

must be rewritten in D to allocate each row individually:

int[][] matrix = new int[][3];
foreach (inout row; matrix) row = new int[4];
matrix[2][3] = 69;

Only arrays with type "static" can be initialized, not runtime arrays.

int[] list = [ 1, 2, 3 ];

These "array literals" will come in a later version of D.

A static array has a length known at compile time, is not resizeable, and is pre-allocated on the stack (or within the object of which it is a member). For example:

int[4] vector;
vector[2] = 105;

When declaring a multidimensional array, the array dimensions read from right to left. The above multidimensional example can be rewritten to use a D static array:

int[4][3] matrix;   // an array of 3 int[4]s
matrix[2][3] = 69;  // indexes into an array still read from left to right,
                    // so matrix[3][2] would be out of bounds

All arrays in Java are objects, including the ones declared with []. For dynamic arrays, one normally uses java.util.Vector or java.util.List (Java 2).

Strings    

D uses a 'char' arrays to represent a string. The Java 'char' is equivalent to D's 'wchar'. For information on UTF and how they are used in D read Text in D.

To store a UTF-32 code point Java uses 'int', as introduced in JDK version 1.5, D uses 'dchar'.

D uses a alias of 'string' to a 'char[]' While wchar is the equivalent to a Java 'char' using 'string' in D is what you want. A 'char[]' is modifiable in D unlike a Java string.


```D2.x```

'string' is an alias to 'immutable(char)[]' which means strings can't be modified.


Concatenation:

In Java + is used to concatenate strings an other objects. D uses ~ and only allows concatenation with other strings.

Comparison:

Java does comparison with method calls to compareTo and equals. In D comparison is done with relational operators

== != < <= > >= 
.

Sample Java code:

String text = "Hello, world!";
String slice = text.substring(7, 12);
String newText = "Welcome to the " + slice + "!";

String str1 = "foo";
String str2 = "bar";
boolean same = str1.equals(str2);

StringBuffer temp = new StringBuffer(str2);
temp.setCharAt(2, 'z');
String str3 = temp.toString();

Equivalent in D:

char[] text = "Hello, world!";
char[] slice = text[7..12];
char[] newText = "Welcome to the " ~ slice ~ "!";

char[] str1 = "foo";
char[] str2 = "bar";
bool same = (str1 == str2);

// Assuming ASCII characters only. See '''note''' below.
char[] temp = str2.dup;
temp[2] = 'z';
char[] str3 = temp;

Note: see the StringsInD page for a fuller explanation.

Thus, the string representation for an Object is returned by method:

public:
  char[] toString();

Associative Arrays    

D has built-in associative arrays (also known as "hashtables", "dictionaries" or "maps") These use a data type for keys, to calculate a hash code for each entry.

char[][char[]] dictionary;

char[] key;
char[] value;

dictionary[key] = value; // put
value = dictionary[key]; // get

To override the hash calculation for custom structs and classes, implement:

public:
  uint toHash();

To make dictionaries in Java, one uses java.util.Dictionary or java.util.Map (Java 2).

Input and Output    

Input and output is defined in the run-time library. The default, Phobos, uses the std.stdio or std.stream modules. Many people switch and use Tango, which uses tango.io.Console.

Phobos Example:

import std.stdio;

void main() {
   writefln("Hi There!");
   writef("What's your name? ");

   auto str = readln();

   writefln("Well, hello, %s", str);
}

Tango Example:

import	tango.io.Console;

void	main()
{
   Cout("Hi There!").newline;
   Cout(" What's your name? ").flush;

   auto str = Cin.get();

   Cout("Well, hello, ")(str).newline;
}

Variables    

As in Java, classes can have data fields and static variables. Furthermore, variables can be declared outside functions and classes. These so-called global variables can be accessed from any function in a program. That makes them difficult to manage. D programs should avoid global variables.

In D, constants can be declared anywhere. (In Java, they have to be static data of a class.) D uses the 'const' keyword instead of 'final'.

Note:: D v2.0 has introduces the concept of const and immutable. This causes const to have a slightly different meaning. As this tutorial concentrates on D v1.0 for more information visit Const and Invariant.

Classes    

In D, there are public and private sections, started by the keywords public and private. In Java, each individual item must be tagged with public or private.

The constructor is called 'this' in D, not the same as the class name like it is in Java. Destructors, equivalent to the finalize method in Java, are called '~this' in D.

Java code:

class Example
{
  public Example(Object x) { this.x = x; }
  public void finalize() {}

  private Object x;
}

D code:

class Example
{
public:
  this(Object x) { this.x = x; }
  ~this() {}

private:
  Object x;
}

You can create classes with "new", but also explicitly destroy them with "delete". With some classes that uses manual memory management instead of Garbage Collection, this is important. But usually it's enough to just set the object reference to null.

Properties    

Java code:

class Example
{
  public int getValue() { return value; }
  public void setValue(int v) { value = v; }

  private int value;
}

Example e = new Example();
e.setValue(42);
int answer = e.getValue();

D code:

class Example
{
public:
  int value() { return m_value; }
  void value(int v) { m_value = v; }

private:
  int m_value;
}

Example e = new Example;
e.value = 42;
int answer = e.value;

Null Pointers    

There is no NullPointerException like in Java. Instead, using a null reference/pointer will either cause a program termination (access violation, segmentation fault, bus error, etc) or maybe throw a runtime Exception.

Comparing an object with null must be written as "if (object is null)", and not like "if (object == null)". The Java operator '==' is called "is" in D, since Java's equals() method is called "==" in D instead.

Casting    

Casting in D is written as: "cast(Class)" and not just "(Class)" like in Java

There is no ClassCastException like in Java. Instead, the cast operator silently returns null if the class cast could not be performed. This also means that the Java 'instanceof' operator is written as a cast expression in D.

Java:

Fruit fruit;

if (fruit instanceof Apple) {
    Apple apple = (Apple) fruit;
    ...
}

D:

Fruit fruit;

Apple apple = cast(Apple) fruit;
if (apple) { ... }

Pointers    

Like Java, D also have primitive types (int, float, etc) and object references (Object, etc).

But D also have pointers, which are like references but can be manipulated with pointer arithmetic.

Using pointers in D is not encouraged, references are usually to be preferred instead.

You can get a pointer to the address of a primitive type (or function) by using the & operator:

int i,j;
int* pi; // pi is a "pointer to int"

pi = &i;
j = *pi;

This is (somewhat, at least...) similar to "boxing" and "unboxing" in Java:

int i,j;
Integer wi; // wi is a "int wrapper"

wi = new Integer(i);
j = wi.intValue();

Using wrapper classes in D is not encouraged, as they add significant overhead. Templates can be used to make generic methods, instead of using Object and wrappers.

References    

The default parameters to a function are called "in" (as they can't be modified, but passed by value). If you want to modify the parameters, you can can declare them as "out" instead (pass by reference).

Using "out" will set the value of the parameter to the default initializer when the method starts, if you want to keep the current value it had when entering you use the "ref" declaration instead.

void swap(ref int i, ref int j)
{
  int temp;

  temp = i;
  i = j;
  j = temp;
}

Functions    

In Java, every function must be an instance method or a static function of a class. D supports instance methods and static functions of classes, but it also permits functions that are not a part of any class. Such functions are called global functions.

In particular, every D program starts with the global function main:

int main(char[][] args) {}

This similar to the method that Java calls when starting a program:

public class ClassName {
    public static void main(String[] args) {}
}

By convention, the return value of main is zero ("EXIT_SUCCESS" constant) if the program completed successfully, a non-zero integer (such as the "EXIT_FAILURE" constant) otherwise.

In Java, this return value is used by the System.exit function.

Structs and Unions    

Structs (also known as "records") can be used to store data, instead of classes.

struct Person
{
  float bodyTemp;
  int age;
}

Person p;

It's similar to a class with all fields declared "public" (no access methods), and you access the fields using "p.bodyTemp" or "p.age" as usual. One difference is that you do not need to allocate a struct using the "new" syntax, like a class. Instead it is allocated on the stack, like the primitive types are. (int, char, etc)

If you want to dynamically allocate a struct on the heap (almost like a Class), you can simply use a pointer to the structure and "new/delete" instead - like:

Person* p = new Person;

Unions are a way to make the same memory stored different types at different times.

union IntOrChar
{
  char c;
  ubyte i;
}

IntOrChar u;

Now "c" and "i" will use the same memory byte location, and if you call "u.c" you get a cast(char) and "u.i" gets a cast(ubyte) result.

Conditional Compilation    

D supports conditional compilation with versions. They make it possible to build several versions from one single source file.

There are two major types of versions:

  • debug
  • version()
Debug is used to specify debugging code that is not intended for release builds, such as printouts. Some predefined versions are also used to support different platforms and compilers, for portability.

  debug printf("The value of foo is: %D\n", foo);


  version(LittleEndian)
  {
    bar = buffer[0] | buffer[1]<<8;
  }
  version(BigEndian)
  {
    bar = buffer[0]<<8 | buffer[1];
  }

Aliases and Typedefs    

Aliases are a way of referring to one type or method using another name. It can be used for portability, to resolve conflicts, or just for fun...

alias char[] str;

void main(str[] args);

Typedefs are a way to declare separate subtypes, that can't readily be mixed with other instances of the main type (like when using alias)

typedef int odd;
typedef int even;

Enumerated Types    

enum
{
  ONE = 1,
  TWO = 2,
  THREE = 3,
}

Enumerations can be unnamed or named, and they can also have different types. Named enumerations form a subtype (like typedef), and the default type is "int".

Note: enum was added to Java in JDK 1.5, as java.lang.Enum class

Templates and Mixins    

TODO

Note: Parametrized types were added to Java in JDK 1.5, as Generics

Assertions    

Assertions are used to verify various assumptions implicitly made in the code:

assert(i >= 0);

They are removed from the final release, and are intended for debugging and testing. Therefore, the code being used in assertions must not have any other side-effects.

Note: assert was added to Java in JDK 1.4

Contracts    

D 1.x, D 2.x

Contracts originate in the Eiffel language, but implementations for Java exists.

in
{
    ...contract preconditions...
}
out
{
    ...contract postconditions...
}
body
{
    ...function implementation...
}

invariant
{
}

JavaDoc    

DMD has Ddoc build in as of Sep. `05 for generating documentation. You may also use the Doxygen program instead.

Comments can still be written in the traditional JavaDoc syntax,

/** frobnicates the foo
 * @return the result
 */
int frobnicate();


/** stores the current bar value */
int bar;

there is a convenient documentation short format available too:

/// frobnicates the foo
/// @return the result
int frobnicate();


int bar; ///< stores the current bar value 

TODO: mention DDOC

Unit Testing    

Unit testing in D does not use a separate library, like JUnit for Java, but is built-in into the language itself with the "unittest { } " blocks.

They use assertions to verify that each test completes as intended, and are compiled in using the conditional compilation flag "-unittest"

Since Java doesn't have conditional compilation, the unit tests are usually put in separate classes or even separate packages.

Compiling unit tests in D needs that a main method is declared somewhere, and this "main" needs to make sure it references all classes to be tested.

Field Initialization    

In Java fields can be initialized with expressions evaluated when the object is constructed. In D field initializers must be compile-time constants. To initialize a field at run-time you need to move the initialization to a constructor. For example in Java

public class X {
  Object x = new Object();
  ...
}

becomes in D

class X {
  Object x;
  this() {
    x = new Object();
  }
  ...
}

To initialize static objects or global variables, use a "static this" block:

Object x;

static this()
{
  x = new Object();
}

This is similar to the (not very well-known) "static {}" construct in Java:

static Object x;

static
{
  x = new Object();
}

Inner Classes    

D allows a class or struct to be defined inside another class or struct scope but it does not implicitly store a reference to an instance of the enclosing class like Java does. Instead if that is the desired behavior you have to manage the reference explicitly. For example the Java code

public class X {
  public class Y {
  } 
  ...
  Y y = new Y();
}

becomes

class X {
  class Y {
    X outer;
    this(X outer) {
      this.outer = outer;
    }
  } 
  ...
  Y y = new Y(this);
}

Synchronization    

D has a synchronized keyword and a lock associated with each object like Java but D does not have the equivalents to wait(), notify() or notifyAll(). D's synchronized statements can also be used without any supplied object, which Java cannot do. In D such a synchronized statement creates a lock not associated with any object. To port code that uses wait/notify constructs get the Locks library and use the ReentrantLock? and Condition classes. For example the Java code

class X {
  X obj;
  ...
  synchronized (obj) {
    while (<cond>) {
      obj.wait();
    }
  }
  ...
  synchronized (obj) {
    obj.notify();
  }
}

becomes

class X {
  X obj;
  Lock lock;
  Condition cond;
  this() {
    lock = new ReentrantLock;
    cond = lock.newCondition;
  }
  ...
  lock.lock(); 
  try {
    while (<cond>) {
      cond.wait();
    }
  } finally {
    lock.unlock();
  }
  ...
  lock.lock();
  try {
    cond.notify();
  } finally {
    lock.unlock();
  }
}

Related Projects    

  • molt - A Java to D source-code converter (project may have been abandoned in 2005)
  • TioPort - A Java to D source-code converter (being tested with SWT)
  • Locks - A port of Doug Lea's Java library for locks, conditions, barriers, latches, semaphores, etc.

FrontPage | News | TestPage | MessageBoard | Search | Contributors | Folders | Index | Help | Preferences | Edit

Edit text of this page (date of last change: July 15, 2009 23:32 (diff))