http://www.developer.com/

Back to article

Java vs Ruby: a Comparison of the Key Elements


December 13, 2007

Ruby is an interpreted scripting language, whereas Java is a compiled programming language. Ruby is similar to Java in that both are object-oriented languages and are strongly typed. But, Ruby is dynamically typed, whereas Java is statically typed. In Ruby, type declarations are not used; in Java, type declarations are required. Both Java and Ruby provide inheritance and have public, private, and protected methods. Ruby is simpler than Java and faster than Java too. Ruby is different from Java in a number of features. I shall compare Ruby and Java on some of the salient features.

Interpreted/Compiled

Ruby is an interpreted scripting language and is run directly without first compiling and generating the byte code. For example, a ruby file helloruby.rb may be run with the following command.

>ruby helloruby.rb

In comparison, Java applications are required to be compiled before running. For example, a Java class hellojava.java is first compiled using the javac compiler with the following command.

>javac hellojava.java

The javac compiler generates the byte code for the Java class. Subsequently, the compiled class may be run with the java.exe application.

>java hellojava

Importing Packages

In Ruby, the require statement is used to import a package or a module. For example, the extensions package/module is imported as follows.

require 'extensions'

External files may be included in a Ruby application by using load or require. For example, to include the external file catalog.rb, add the following require statement.

require "catalog.rb"

The difference between load and require is that load includes the specified Ruby file every time the method is executed and require includes the Ruby file only once.

In Java, the import statement is used to load a package. For example, a Java package java.sql is loaded as follows.

import java.sql.*;

Typed Variables

Both Ruby and Java are strongly typed. But, in Ruby variables are dynamically typed; this implies that variables do not have an explicit type associated with them. For example, a variable with a string value is declared as follows.

str="Hello Ruby"

Because the str variable does not have a type associated with it, the variable may be assigned an integer value or a value of any other type.

str=1

In Java, variables are statically typed; this implies that variables have a type associated with them. For example, a string variable is declared as follows.

String str="Hello Java";

The str variable may not be assigned an integer value.

Null Value

In Ruby, a null value is declared with nil. For example, a variable str may be assigned a nil value as follows.

str=nil

In Java, a null value is declared with null. For example, a variable str is assigned a null value as follows.

str=null;

Object Oriented

In Ruby, everything is an object—including numbers, variables, and methods. In Java, only classes have objects. For example, an object of type Class1 is created as follows.

Class1 class1=new Class1();

Member Variables

In Ruby, all member variables are private. In Java, member variables have the package access by default and may be declared public, private, or protected with the public, private, and protected identifiers. Private members may be accessed only within the class itself. The public members in Java may be accessed by any other class. Protected members in Java may be accessed within the same package as the class declaring them and in the subclasses of the class. The default package access in Java is for access within the same package as the class declaring the members in addition to the class itself.

Casting

In Java, objects may be cast to other objects if the objects being cast are of the type of the objects being cast to. For example, an object of type LinkedHashSet, linkedHashSet, may be cast to HashSet because LinkedHashSet extends HashSet.

HashSet hashSet=(HashSet)linkedHashSet;

In Ruby, no casting is used because variables are dynamically typed and may be assigned to any other type.

Class and Method Definition

Ruby defines a class/method block using the end keyword. Java uses braces to define a class/method block. A class, for example Catalog, in Ruby is defined with the class modifier as follows.

class Catalog

end

A Ruby class is required to begin with a capital letter. A class in Java also is defined using the class modifier and is required to begin with a capital letter as follows.

class Catalog{
}

In Ruby, class definitions do not have an access modifier, whereas in Java a class may have the public access modifier, the default class access being package. For example, the Catalog class in Java may be declared as follows.

public class Catalog{

}

Methods in Ruby begin with def and end with end. For example, a method getCatalogId is defined as follows.

def getCatalogId
return 1
end

By default, Ruby methods are public. Ruby methods may be specified with public, private, and protected modifiers. In Ruby, methods may return a value, but the type of the return value is not specified in the method definition. In Java, methods have package access by default and require a return type. For example, the getCatalogId method in Java may be declared as follows.

int getCatalogId(){return 1;}

Java methods may have the public, private, or protected modifiers. In Ruby, parentheses in method invocation are optional. For example, define a method hello that takes a name argument and returns a Hello message.

class Hello
def hello(name)
   return "Hello " +name
   end
end

The hello method may be invoked with or without parentheses for the argument as follows.

helloObj=Hello.new
helloObj.hello("John")
helloObj.hello "John"

In Java, parentheses in method invocation are required. For example,define a method hello that returns a Hello message.

public class Hello{

public String hello(String name){

return "Hello "+ name;

}

}

The hello method in the Hello class may be invoked only with parentheses for the argument as follows.

Hello helloObj=new Hello();
helloObj.hello("John");

Class Constructor

In Java, the constructor is the name of the class. For example, define a class Hello and define a constructor for the class.

public class Hello{
String defaultMsg;
public Hello(String msg){
defaultMsg=msg;
}
}

The constructor sets the value of the String defaultMsg. Ruby provides the initialize function for class instantiation. For example, define a class and instantiate a variable in the class using the initialize function as follows.

class Hello
   @defaultMsg
   def initialize(msg)
   @defaultMsg=msg

   end
end

Class Instantiation

In Ruby, a class is instantiated by using the class method new. For example, the Hello class in the previous example may be instantiated as follows.

hello=Hello.new("Hello Ruby")

The arguments passed to the new method are passed to the initialize function. In Java, a class is instantiated using the Java operator new.

Hello hello=new Hello();

The new operator may be used with any of the constructors defined in the class. For example, if the Hello class has the constructor that takes a String argument to set the default Hello message, the class may be instantiated as follows.

Hello hello=new Hello("Hello Java");

In Java, more than one constructors may be declared, but a Ruby class may have only one initialize method. Ruby does not generate an exception if more than one initialize method is declared, but only the last initialize method is used.

Multiple Inheritance

Both Java and Ruby have the provision to extend another class. In Java, a class is extended using the extends keyword as follows.

public class LinkedHashSet extends HashSet{}

In Ruby, a class may extend another class using '<'. For example, the Catalog class extends the ActiveRecord::Base class.

class Catalog < ActiveRecord::Base

   end

In both Ruby and Java, a class may extend only one other class. Java provides multiple inheritance with interfaces that consist of abstract methods that may be implemented by a class implementing the interfaces. Ruby provides multiple inheritance with modules and mixins.

Modules are similar to classes in that they consist of variables and methods. But, modules are different from classes in that instances of a module cannot be created and a module cannot be subclassed. A module is defined with the keyword module as follows.

module Catalog
PI=3.1419
@journal

def setJournal(journal)
@journal=journal
end
end

The Catalog module has a constant PI, an instance variable @journal and a method setJournal.

A module may be included in another class by using mixins. To include a module in a class, first specify a require statement for the module and subsequently include the module using include. For example, mixin the Catalog module in another class CatalogEntry.

require Catalog
class CatalogEntry
include Catalog

end

When a module is included in another class using include, the variables, methods, and classes in the module become available to the class including it.

Exception Handling

In Java, exceptions are handled using the try-catch-finally construct; this consists of one try block, followed by one or more catch blocks, optionally followed by a finally block. In the try block, some statements are run that might generate an exception. Each of the catch blocks handles an Exception. In the optional finally block, some statements may be run to close objects. The finally block is always run after the application exits the try block. An example of a try-catch-finally block is as follows, in which the try block creates a Connection object with a MySQL database, in the catch block SQLException is handled, and in the finally block the Connection object is closed.

try {
   String url="com:mysql:jdbc://localhost:3306/test";
   Connection connection=DriverManager.getConnection(url, "root","");
} catch (SQLException e) {
   System.err.println("Caught: SQLException: "
                      + e.getMessage());
} finally(){
   connection.close();
}

In Ruby, exceptions are handled using begin-rescue-ensure-end construct. The construct consists of one or more rescue clauses that consist of statements to run when a specified exception occurs. The optional ensure clause consists of statements that are always run whether an exception occurs or not. The rescue clause in Ruby is equivalent to the catch clause in Java. The ensure clause in Ruby is equivalent to the finally clause in Java. The begin-rescue-ensure construct is shown below.

begin

rescue RubyException1
Statements to run when RubyException1 occurs.
rescue RubyException2
Statements to run when RubyException2 occurs.
ensure
Statements to run whether an exception occurs or does not occur.

end

Conclusion

Although Ruby is similar to Java and has parallel features, Ruby is not a replacement for Java as implied by an ONJava article Ruby the Rival. Just as Java EE is the enterprise framework for developing Model-View-Controller applications with Java, Ruby on Rails is the Model-View-Controller framework for Ruby.

About the Author

Deepak Vohra, dvohra09@yahoo.com, is a Sun Certified Java Programmer and a Sun Certified Web Component Developer, and has published in devx, FTPOnline, JavaBoutique, ONJava, and java.net.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date