Vala for Java Programmers
Contents
- Vala for Java Programmers
- Source Files
- Compilation
- Using Libraries
- Naming Conventions
- Code Organization
- Main Entry Point
- Basic Types
- Strings
- Arrays
- Type Inference
- Foreach
- Inheritance
- Object Base Class
- Method Overloading
- Multiple Constructors
- Constructor Chaining
- Overriding
- Access Modifiers
- Interfaces
- Enums
- Run-Time Type Information
- Object Destruction
- Annotations
- Properties
- Delegates, Closures
- Notification
- Property Change Notification
- Exceptions
- Parameter Directions
- Nullability
- Argument Checking
- Structs
- Synchronizing
- Conditional Compilation
- Memory Management
- Static Initialization
- Varargs
- Native Methods
- Not Available
- Features Not Covered In This Tutorial
- Collections
- IO, Network Sockets
- Console Input / Output
- From Swing to GTK+
Source Files
Java: *.java
Vala: *.vala
Compilation
Java: compiled to JVM byte code (.class files)
$ javac SourceFile1.java SourceFile2.java
Vala: compiled to native code via C code as intermediate code
$ valac source1.vala source2.vala -o program
Vala's standard object system is GObject, compiled Vala libraries are valid C libraries.
Using Libraries
Java: .jar files
$ javac -classpath foo-1.0.jar;bar-3.0.jar SourceFile.java
Vala: packages (C libraries with .vapi files)
$ valac --pkg foo-1.0 --pkg bar-3.0 source.vala
Naming Conventions
Java
-
classes, interfaces, enums: CamelCase
-
methods, local variables, fields: mixedCamelCase
-
constants, enum values: UPPER_CASE
Vala
-
classes, interfaces, structs, enums, delegate types, namespaces: CamelCase
-
methods, local variables, fields, properties, signals: lower_case
-
constants, enum values: UPPER_CASE
No non-ASCII letters for identifiers allowed. You can use Vala keywords as identifiers if you prefix them with @. The at sign is not considered as part of the name.
Code Organization
Files
Java: one toplevel class per file, file name resembles class name
Vala: a Vala source file may contain multiple classes, file name doesn't need to resemble a class name
Hierarchy
Java: packages, represented by directory hierarchy, reverse domain name scheme
import javax.swing.*;
package org.foo.bar;
// ...
Vala: namespaces, not related to directory hierarchy, no reverse domain name scheme
using Gtk;
namespace Foo.Bar {
// ...
}
Vala namespaces may contain methods without classes. They are implicitly static.
Default Import
Java: package java.lang.* imported by default
Vala: namespace GLib imported by default
Main Entry Point
Java: public static void main(String[] args)
Vala: static int main (string[] args)
May be outside a class, may be private, may return int (exit code), args argument is optional
Basic Types
-
sizes of standard types (int, long, ...) are architecture dependent. Get size of a type in bytes with sizeof (), e.g. sizeof (int)
-
additional Vala types int8, int16, int32, int64 (signed), uint8, uint16, uint32, uint64 (unsigned) with architecture independent guaranteed sizes
-
no byte (use uint8, int8 instead)
-
bool instead of boolean
-
additional basic type: unichar, representing a Unicode character
Constant modifier: const instead of final.
Vala's basic types have methods, e.g.
int a = -4.abs ();
string s = a.to_string ();
int b = int.max (5, 7); // static method call on 'int'
Strings
Java
Data type: String
Equality test: str1.equals(str2)
Vala
Data type: string (lower case)
Equality test: str1 == str2
String comparisons compare content, not reference. You can compare strings lexicographically with <, >, <=, >= etc. Strings can be used with switch.
Vala strings are UTF-8 encoded.
Additional Vala String Features
Vala supports verbatim strings: """..."""
string verbatim = """Verbatim strings don't evaluate escape sequences like \n, \t, ... and may span multiple lines. The line breaks are part of the string. You can use quotation marks (") and backslashes (\) inside a verbatim string without escaping them."""
Vala supports string templates: @"...". String templates may contain expressions, prefixed by a $ sign.
string name = "John";
stdout.printf (@"Welcome, $name!");
stdout.printf (@"3 + 2 = $(3 + 2)");
Arrays
Dynamic Growth
You can add elements to arrays dynamically by using the += operator. The array will be reallocated with sizes of powers of two:
int[] squares = {};
for (int i = 0; i < 100; i++) {
squares += i * i;
}
No Boundary Checking
However, there is no runtime boundary checking for arrays in Vala:
int[] a = new int[10];
a[20] = 1; // not safe!
(Optional boundary checking is planned for a future version of Vala.)
Multi-Dimensional Arrays
Java: jagged multi-dimensional arrays [][] (arrays of arrays)
int[][] matrix = new int[3][];
for (int[] row : matrix) {
row = new int[4];
}
Vala: rectangular multi-dimensional arrays [,], [,,], etc. (allocated as one contiguous memory block), jagged array support planned
int[,] matrix = new int[3,4];
Illustration: rectangular vs. jagged multi-dimensional array
Type Inference
Vala supports a mechanism called type inference (implicit typing) for local variables: Local variables may be declared using the var keyword instead of the type name if the compiler can deduce (infer) the type from the initial assignment. This helps avoiding unnecessary redundancy and is especially useful for generic types. Examples:
var obj = new Object ();
var map = new HashMap<string, int> ();
var str = "hello, world";
var arr = new int[10];
instead of
Object obj = new Object ();
HashMap<string, int> map = new HashMap<string, int> ();
string str = "hello, world";
int[] arr = new int[10];
Still, everything is statically typed.
Foreach
Java: for (int i : numbers) { }
Vala: foreach (int i in numbers) { }
Inheritance
Java: extends, implements
public class Demo extends Foo implements Bar {
public Demo() {
super();
}
}
Vala: colon followed by comma separated list, both for super class and interfaces
public class Demo : Foo, Bar {
public Demo () {
base ();
}
}
super is called base in Vala.
Object Base Class
Java: implicit inheritance from Object (java.lang.Object)
public class Foo {
// ...
}
Vala: no implicit inheritance from Object (GLib.Object)
public class Foo : Object {
// ...
}
What happens if you don't inherit from Object? Nothing terrible. These classes will be slightly more lightweight, however, they will lack some features such as property change notifications, and your objects won't have a common base class. Usually inheriting from Object is what you want.
Method Overloading
Java
public class Demo {
public void draw(String text) { }
public void draw(Shape shape) { }
/* Method overloading + chaining for convenience methods with less arguments */
void f(int x, String s, double z) { }
void f(int x, String s) {
f(x, s, 0.5);
}
void f(int x) {
f(x, "hello");
}
}
Vala: no method overloading, use different names instead or default values for arguments
public class Demo : Object {
public void draw_text (string text) {
}
public void draw_shape (Shape shape) {
}
/* Method with argument default values */
void f (int x, string s = "hello", double z = 0.5) {
}
}
Vala does not support method overloading because libraries written in Vala are intended to be usable by C programmers as well with meaningful function names.
Multiple Constructors
Java: constructor overloading
public class Foo {
public Foo() { }
public Foo(int foo) { }
public Foo(String bar) { }
}
new Foo();
new Foo(42);
new Foo("hello");
Vala: named constructors instead of constructor overloading
public class Foo : Object {
public Foo () { }
public Foo.with_foo (int foo) { }
public Foo.from_bar (string bar) { }
}
new Foo ();
new Foo.with_foo (42);
new Foo.from_bar ("hello");
Constructor Chaining
Java: this()
class Foo {
public Foo() {
this("bar");
}
public Foo(string bar) {
}
}
Vala: this() or this.name_addition()
class Foo : Object {
public Foo () {
this.with_bar ("bar");
}
public Foo.with_bar (string bar) {
}
}
Overriding
Java: all methods are virtual (overridable) by default, final prevents overriding
public class Super {
public int myMethod(int x, int y) { }
public final void anotherMethod() { }
}
public class Sub extends Super {
@Override
public int myMethod(int x, int y) {
super.myMethod(x, y);
// ...
}
}
Vala: all methods are non-virtual (not overridable) by default, overriding must be explicitly allowed with virtual. So it's the other way round. Vala has override keyword instead of @Override annotation, and it's not optional
public class Super : Object {
public virtual int my_method (int x, int y) { }
public void another_method () { }
}
public class Sub : Super {
public override int my_method (int x, int y) {
base.my_method (x, y);
// ...
}
}
Access Modifiers
Java | Vala |
public | public |
protected | protected |
package-private (default) | internal |
private | private (default) |
Although private is default you may use it explicitly for symmetry reasons with regard to public.
Interfaces
Java: interface methods are implicitly abstract
public interface Foo {
public void foo(int i);
public int bar(String s, double d);
}
Vala: abstract explicitly necessary
public interface Foo {
public abstract void foo (int i);
public abstract int bar (string s, double d);
}
Why? Because Vala interfaces may have non-abstract methods (i.e. methods with implementations)! This means Vala interfaces can be used as mixins (restricted form of multiple inheritance).
Vala interfaces may have static methods, e.g. factory methods.
Java: interface inheritance
public interface IfaceA {
public void methodA();
}
public interface IfaceB extends IfaceA {
public void methodB();
}
public class Demo implements IfaceB {
public void methodA() { }
public void methodB() { }
}
Vala: interface prerequisites
interface IfaceA : Object {
public abstract void method_a ();
}
interface IfaceB : Object, IfaceA {
public abstract void method_b ();
}
class Demo : Object, IfaceA, IfaceB {
public void method_a () { }
public void method_b () { }
}
Interfaces in Vala may not inherit from other interfaces, but they may declare other interfaces to be prerequisites, which works in roughly the same way. Interfaces may also have a class as a prerequisite. This is often used to ensure that an instance of an interface is also an Object subclass. The fact that interfaces can not inherit from other interfaces is mostly only a technical distinction - in practice Vala's system works the same as Java in this area, but with the extra feature of prerequsite classes.
Enums
Java: enums are class based
Vala: enums are integer based. Methods allowed, however no constructors, fields, etc.
enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER;
public bool is_hot () {
return this == SUMMER;
}
}
Run-Time Type Information
Dynamic Type Check
Java: obj instanceof Foo
Vala: obj is Foo
Dynamic Type Casting
Java: Foo foo = (obj instanceof Foo) ? (Foo) obj : null
Vala: Foo foo = obj as Foo
Of course, "(obj is Foo) ? (Foo) obj : null" would do as well.
Getting Type Information
Java
Class c = Foo.class;
System.out.println(c.getName());
Foo = (Foo) c.newInstance();
Vala: typeof () operator
Type t = typeof (Foo);
stdout.printf ("%s\n", t.name ());
Foo o = (Foo) Object.new (t);
Object Destruction
Java: finalizers, not deterministic
public class Foo {
@Override
protected void finalize() {
}
}
Vala: destructors, deterministic
public class Foo : Object {
~Foo () {
}
}
Annotations
Java: @Annotations, self-definable
Vala: attributes, built into the compiler. Syntax: [AttributeName (param1 = value, param2 = value)]. Mostly used for bindings or D-Bus interfaces. The most prominent attribute for bindings is [CCode (...)]
Properties
Java: Bean convention, getX() and setX() methods
public class Person {
private int age = 32;
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
Person p = new Person();
p.setAge(p.getAge() + 1);
}
}
Vala: language support for properties, get {} and set {} blocks, can be accessed like fields
public class Person : Object {
private int _age = 32;
public int age {
get { return _age; }
set { _age = value; }
}
}
void main () {
var p = new Person ();
p.age++;
}
Or even shorter for the standard implementation:
public class Person : Object {
public int age { get; set; default = 32; }
}
Delegates, Closures
Java: implement delegate pattern, use anonymous inner classes
public interface MyDelegateType {
public void invoke(int a, double b);
}
public class Demo {
private static void foo(MyDelegateType deleg) {
deleg.invoke(32, 0.25);
}
public static void main(String[] args) {
MyDelegateType deleg = new MyDelegateType () {
public void invoke(int a, double b) {
System.out.println("a = " + a + "; b = " + b);
}
};
deleg.invoke(42, 0.75);
foo(deleg);
}
}
Vala: language support for delegates and closures
delegate void MyDelegateType (int a, double b);
void foo (MyDelegateType deleg) {
deleg (32, 0.25); // invoke delegate
}
void main () {
MyDelegateType deleg = (a, b) => {
stdout.printf ("a = %d; b = %g\n", a, b);
};
deleg (42, 0.75); // invoke delegate
foo (deleg); // pass delegate to a method
}
Closures are anonymous methods that capture the variables of the outer scope. They can be assigned to delegate variables or be passed as delegate parameters to methods.
In Java closures can be simulated with anonymous inner classes. However, anonymous inner classes can only capture final variables of the outer scope, whereas Vala closures can capture any variable. Closure support is potentially planned for Java 7.
You can assign methods directly to delegate variables:
delegate int MyDelegateType (int a, double b);
int add (int a, int b) {
return a + b;
}
int sub (int a, int b) {
return a - b;
}
void main () {
MyDelegateType deleg = add;
int sum = deleg (2, 3);
deleg = sub;
int diff = deleg (8, 4);
}
This means methods can be stored in variables and be passed around like objects.
Notification
Java: listeners (implement observer pattern)
public interface ClickListener {
public void clicked(Clickable source);
}
public interface Clickable {
public void addClickListener(ClickListener l);
public void removeClickListener(ClickListener l);
}
public class MyButton implements Clickable {
private List<ClickListener> clickListeners;
public MyButton() {
this.clickListeners = new ArrayList<ClickListener>();
}
private void fireClickListeners() {
for (ClickListener listener : this.clickListeners) {
listener.clicked(this);
}
}
public void addClickListener(ClickListener l) {
if (l != null) {
this.listeners.add(l);
}
}
public void removeClickListener(ClickListener l) {
if (l != null) {
this.listeners.remove(l);
}
}
public void test() {
fireClickListeners(); // fire listeners
}
}
public class Demo {
private class MyClickListener implements ClickListener {
public void clicked(Clickable s) {
System.out.println("handler C");
}
}
public static void main(String[] args) {
MyButton b = new MyButton();
b.addClickListener(new ClickListener() {
public void clicked(Clickable s) {
System.out.println("handler A");
}
});
b.addClickListener(new ClickListener() {
public void clicked(Clickable s) {
System.out.println("handler B");
}
});
MyClickListener handlerC = new MyClickListener();
b.addClickListener(handlerC);
b.test();
b.removeClickListener(handlerC);
}
}
Vala: signals (signal keyword, .connect() and .disconnect())
public class MyButton : Object {
public signal void clicked ();
public void test () {
clicked (); // emit signal
}
}
void handler_c (MyButton source) {
stdout.printf ("handler C\n");
}
void main () {
var b = new MyButton ();
b.clicked.connect ((s) => stdout.printf ("handler A\n"));
b.clicked.connect ((s) => {
stdout.printf ("handler B\n");
});
b.clicked.connect (handler_c);
b.test ();
b.clicked.disconnect (handler_c);
}
Property Change Notification
Java
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class DemoBean {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private String title;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
String old = this.title;
this.title = title;
this.pcs.firePropertyChange("title", old, title);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.pcs.removePropertyChangeListener(listener);
}
public static void main(String[] args) {
DemoBean demo = new DemoBean();
demo.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("Property " + evt.getPropertyName() + " changed");
}
});
demo.setTitle("hello");
demo.setTitle("world");
}
}
Vala: Subclasses of Object have a notify signal
public class Demo : Object {
public string title { get; set; }
}
void main () {
var demo = new Demo ();
demo.notify.connect ((s, p) => stdout.printf ("Property %s changed\n", p.name));
demo.title = "hello";
demo.title = "world";
}
However, you can't get the old value.
If you're only interested in change notifications of a single property you can use this syntax:
demo.notify["title"].connect ((s, p) => stdout.printf ("title changed\n"));
Change notifications can be disabled with a CCode attribute tag immedietely before the declaration of the property:
class MyObject : Object {
// notify signal is NOT emitted upon changes in the property
[CCode (notify = false)]
public int without_notification { get; set; }
// notify signal is emitted upon changes in the property
public int with_notification { get; set; }
}
Exceptions
Java: class-based exceptions
public class TemperatureException extends Exception {
}
public class TooColdException extends TemperatureException {
}
public class TooHotException extends TemperatureException {
}
public class ExceptionDemo {
private void method() throws TemperatureException {
throw new TooColdException("It's too cold!");
}
public static void main(String[] args) {
try {
method();
} catch (TemperatureException e) {
System.out.println(e.getMessage());
}
}
}
Vala: exceptions are called errors, not class-based, no wrapping
// error domain with multiple error codes instead of exception classes
errordomain TemperatureError {
TOO_HOT,
TOO_COLD
}
void method () throws TemperatureError {
// error domain, error code, error message
throw new TemperatureError.TOO_COLD ("It's too cold!");
}
// must be caught or propagated, compiler warning if ignored
try {
method ();
} catch (TemperatureError e) {
stderr.printf ("Error: %s\n", e.message);
}
Although the compiler emits warnings for ignored errors it does not abort the compilation process. This allows prototyping without proper error handling and will hopefully prevent forgotten empty catch blocks.
You can check the error code with is:
if (e is TemperatureError.TOO_COLD) {
// ...
}
Parameter Directions
Vala methods can have so-called out or ref arguments. If a method argument is marked as out or ref argument in the method signature it means that the method can change the value of the passed variable (only variables can be passed as out or ref arguments) and the change is still in effect after the method returns. If the passed variable is of a reference type the method can change the reference itself (assign a whole new object to the variable instead of just changing the state of the passed object).
The difference between out and ref is that a variable passed as ref argument must be initialized before it is passed to the method, while a variable passed as out argument can be uninitialized and is expected to be initialized by the method.
The keywords must be used both at the method definition and when calling the method.
/*
* This method takes a normal argument, an 'out' argument
* and a 'ref' argument.
*/
void my_method (int a, out int b, ref int c) {
a = 20; // will have no effect outside of this method
// until now 'b' is considered uninitialized
b = 30; // initialize 'b', will affect the passed variable
c = 40; // will affect the passed variable
}
void main () {
int x = 2
int y; // may be uninitialized
int z = 4; // must be initialized before it is passed as 'ref' argument
my_method (x, out y, ref z);
stdout.printf ("%d %d %d\n", x, y, z); // => "2 30 40"
// 'x' is still the same, 'y' and 'z' have changed
}
Nullability
In Vala you must mark reference type parameters of methods as nullable with a question mark (?) if it should be allowed to pass null, e.g.
void my_method (Object? a, Object b) { }
void main () {
my_method (null, new Object()); // allowed (first argument may be null)
my_method (null, null); // not allowed (second argument must not be null)
}
This is checked both at run-time and partially at compile time and helps preventing null pointer dereferencing.
You can enable (experimental) strict nullability checking with --enable-experimental-non-null. Then Vala will check all reference type variables at compile time, not only method arguments. For example, this example won't compile with strict nullability checking enabled:
void main () {
string? a = "hello";
string b = a; // Error: 'a' could be null and 'b' is not nullable
}
However, if you cast the nullable variable into a non-nullable variable with (!) it will compile:
void main () {
string? a = "hello";
string b = (!) a;
}
There are experiments with non-null types (via @NonNull annotations) for Java as well, e.g. JACK and JastAdd
Argument Checking
Java
void method(double d, int i, Foo foo) {
if (d < 0 || d > 1.0)
throw new IllegalArgumentException();
if (i < 0 || i > 10)
throw new IllegalArgumentException();
if (foo == null)
throw new IllegalArgumentException();
// ...
}
Vala: reference type parameters are implicitly checked for null unless they are marked nullable with ?, so you don't have to check them manually. Methods may have preconditions:
void method (double d, int i, Foo foo)
requires (d >= 0.0 && d <= 1.0)
requires (i >= 0 && i <= 10)
{
// ...
}
Vala additionally supports postconditions, for example for checking the return value:
int square (int i)
ensures (result >= 0)
{
return i * i;
}
result is a special variable representing the return value.
Use exceptions (errors) for recoverable runtime errors (database errors, I/O errors), use preconditions and assertions (assert (...)) for programming errors such as illegal arguments.
Structs
A struct is a concept not available in Java. To understand the difference between a struct and a class we will look at two implementations of a Point type, once as class and once as struct:
class Point {
public int x;
public int y;
public Point (int x, int y) {
this.x = x;
this.y = y;
}
public void print () {
stdout.printf ("(%d, %d)", this.x, this.y);
}
}
struct Point {
public int x;
public int y;
public Point (int x, int y) {
this.x = x;
this.y = y;
}
public void print () {
stdout.printf ("(%d, %d)", this.x, this.y);
}
}
As you can see, the only difference is the struct keyword instead of class. However, struct types have different semantics than class types:
// Class
var p1 = new Point (2, 4); // will allocate p1 on the heap
var p2 = p1; // assignment by reference
p2.x = 3;
p1.print (); // => (3, 4) p1 changed as well
p2.print (); // => (3, 4)
var p3 = new Point (3, 4);
p2 == p3; // => false (same values, but different references)
// Struct
var p1 = Point (2, 4); // will allocate p1 on the stack
var p2 = p1; // copied
p2.x = 3;
p1.print (); // => (2, 4) p1 did not change
p2.print (); // => (3, 4)
var p3 = Point (3, 4);
p2 == p3; // => true (same values)
Structs are not allocated on the heap (that's why the new keyword is not used for the creation of structs). The most important difference is that structs are copied on assignment. They are value types, not reference types, i.e. they basically behave like int, double, etc.
Structs don't support inheritance and signals, and they can't implement interfaces.
Synchronizing
Java: synchronized
Vala: lock, cannot be applied to whole methods, only to member objects
Conditional Compilation
Java: no conditional compilation
Vala: support for simple conditional compilation with #if, #elif, #else, #endif. However, this is not a macro preprocessor like the C preprocessor.
See Conditional Compilation Example
Memory Management
Java: Garbage collection
Vala: Automatic reference counting
This has both advantages and disadvantages. Reference counting is deterministic, but you can form reference cycles in some cases. In these cases you must use weak references in order to break those cycles. The Vala keyword for this is weak.
See Vala's Memory Management Explained
Static Initialization
Java: static initializer block, called before the first instance is created or any static members are referenced
public class Foo {
static {
System.out.println("Static initializer block invoked.");
}
}
Vala: static construct { } block. The first time that a class, or any subclass of it, is instantiated, this code is run. It is guaranteed that this code will run exactly once in a program where such a class is used.
class Foo : Object {
static construct {
stdout.printf ("Static constructor invoked.\n");
}
}
Additionally a Vala class can have a class construct { } block. This block will be executed once at the first use of its class, and once at the first use of each subclass of this class.
Varargs
Java:
String format(String pattern, Object... arguments) {
// ...
}
Vala: C-style varargs, not type-safe
string format (string pattern, ...) {
var l = va_list ();
// ...
}
For more information, see the general Vala Tutorial. Type-safe varargs planned with params keyword.
Native Methods
Java: native keyword, JNI
Vala: all method calls are "native" calls. Bind C functions quickly with extern keyword or write a .vapi file. Use CCode attribute to specify the original function name (only if it differs from the Vala name)
public class MainClass : Object {
[CCode (cname = "SampleMethod")]
public static extern int sample_method (int x);
static void main () {
stdout.printf ("sample_method () returns %d\n", sample_method (5));
}
}
Pass library name to the compiler with -X -l... (with -X meaning the next option is passed through to the C compiler)
$ valac demo.vala -X -lfoo
You can also pass a C source file containing the external method to the Vala compiler. This allows for mixed Vala and C source code projects.
$ valac demo.vala foo.c
Not Available
-
No final classes (planned as sealed classes)
- No static classes (use nested namespaces instead)
- No anonymous inner classes (use delegates + closures instead)
- No constraints on generic type parameters
-
No implicit conversion of objects to strings (no general toString()). However, types that have a to_string() method are supported by string templates (@"...")
- No named breaks / labels
-
No strictfp, transient keywords
Features Not Covered In This Tutorial
- Asynchronous methods
- Alternative construction scheme (gobject-style)
See the general Vala tutorial for more information on these.
Collections
Java: java.util.* package
Vala: Gee namespace, --pkg gee-1.0, http://live.gnome.org/Libgee
See Gee Examples, Gee Documentation
Vala allows array-like access for Gee collections (e.g. my_map[key] is equivalent to my_map.get (key)). Vala supports an in operator for collections: x in my_collection is equivalent to my_collection.contains (x). This operator also works with strings, even though strings are not collections.
Please note that Libgee checks for errors like the bounds for the index key with an assert, and so it won't raise any catchable RuntimeException like Java does.
IO, Network Sockets
Java: java.io.*, java.net.* packages
Vala: GLib namespace (imported by default), --pkg gio-2.0, GIO is part of GLib
See GIO Examples, GIO Networking Examples
Console Input / Output
Java
System.out.println("Hi!");
System.out.print("Please enter your name: ");
String name = System.console().readLine();
System.out.format("Welcome, %s!\n", name);
Scanner stdin = new Scanner(System.in);
System.out.print("Enter a string, a double, a float, and an int: ");
String s = stdin.next();
double d = stdin.nextDouble();
float f = stdin.nextFloat();
int i = stdin.nextInt();
System.out.println("You entered the following:");
System.out.println("String : " + s);
System.out.println("double : " + d);
System.out.println("float : " + f);
System.out.println("int : " + i);
Vala
stdout.printf ("Hi!\n");
stdout.printf ("Please enter your name: ");
var name = stdin.read_line ();
stdout.printf ("Welcome, %s!\n", name);
string s;
double d;
float f;
int i;
stdout.printf ("Enter a string, a double, a float, and an int: ");
stdin.scanf ("%s", out s);
stdin.scanf ("%lf", out d);
stdin.scanf ("%f", out f);
stdin.scanf ("%d", out i);
stdout.printf ("You entered the following:\n");
stdout.printf ("string : %s\n", s);
stdout.printf ("double : %lf\n", d);
stdout.printf ("float : %f\n", f);
stdout.printf ("int : %d\n", i);
From Swing to GTK+
Simple GUI App
Java
import javax.swing.*;
public class HelloWorldFrame extends JFrame {
public HelloWorldFrame() {
JLabel label = new JLabel("Hello World");
add(label);
setSize(100, 100);
}
public static void main(String args[]) {
JFrame frame = new HelloWorldFrame();
frame.setVisible(true);
}
}
Vala
using Gtk;
public class HelloWorldWindow : Window {
public HelloWorldWindow () {
var label = new Label ("Hello World");
add (label);
set_default_size (100, 100);
}
}
void main (string[] args) {
Gtk.init (ref args);
var win = new HelloWorldWindow ();
win.show_all ();
Gtk.main ();
}
Must be compiled with --pkg gtk+-3.0.
See GTK+ Examples
Transition Table
Swing | GTK+ |
JButton | |
JCheckBox | |
JColorChooser | |
JComboBox | |
JComponent | |
JDialog | |
JEditorPane | |
JFileChooser | |
JFrame | |
JLabel | |
JList | |
JMenu | |
JMenuBar | |
JOptionPane | |
JPanel | |
JPasswordField | Entry with visibility = false |
JProgressBar | |
JRadioButton | |
JScrollPane | |
JSeparator | |
JSlider | |
JSpinner | |
JSplitPane | |
JTabbedPane | |
JTable | |
JTextArea | |
JTextField | |
JTextPane | |
JToolBar | |
JToolTip | |
JTree | |
JViewport |