这是用户在 2024-10-19 10:59 为 https://wiki.gnome.org/Projects/Vala/ValaForJavaProgrammers 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?


面向 Java 程序员的 Vala

 源文件

 Java:*.java

 Vala:*.vala

 汇编


Java:编译为 JVM 字节码(.class 文件)

$ javac SourceFile1.java SourceFile2.java


Vala:通过 C 代码编译为原生代码作为中间代码

$ valac source1.vala source2.vala -o program


Vala 的标准对象系统是 GObject,编译后的 Vala 库是有效的 C 库。

 使用库


Java:.jar 个文件

$ javac -classpath foo-1.0.jar;bar-3.0.jar SourceFile.java


Vala:包(带有 .vapi 文件的 C 库)

$ valac --pkg foo-1.0 --pkg bar-3.0 source.vala

 命名约定

 爪哇岛


  • 类、接口、枚举: CamelCase


  • 方法、局部变量、字段: mixedCamelCase


  • 常量、枚举值: UPPER_CASE

 瓦拉


  • 类、接口、结构、枚举、委托类型、命名空间: CamelCase


  • 方法、局部变量、字段、属性、信号: lower_case


  • 常量、枚举值: UPPER_CASE


不允许使用非 ASCII 字母作为标识符。如果为 Vala 关键字添加前缀,则可以使用 Vala 关键字作为标识符 @ 。at 符号不被视为名称的一部分。

 代码组织

 文件


Java:每个文件一个顶级类,文件名类似于类名


Vala:一个 Vala 源文件可以包含多个类,文件名不需要类似于类名

 等级制度


Java:包,以目录层次结构表示,反向域名方案

import javax.swing.*;

package org.foo.bar;

// ...


Vala:命名空间,与目录层次结构无关,无反向域名方案

using Gtk;

namespace Foo.Bar {
    // ...
}


Vala 命名空间可以包含没有类的方法。它们是隐含 static 的 .

 默认导入


Java:默认导入的 java.lang.*


Vala:默认导入的 namespace GLib

 主要入口

 爪哇岛: public static void main(String[] args)

 瓦拉: static int main (string[] args)


可能在类之外,可能是 private ,可能返回 int (退出代码), args 参数是可选的

 基本类型


  • 标准类型 ( intlong , ...) 的大小取决于体系结构。使用 sizeof () 获取类型的大小(以字节为单位), sizeof (int) 例如


  • 其他 Vala 类型 int8 、 、 int16 int32int64 (有符号)、 uint8uint16uint32 uint64 (无符号) 具有独立于架构的保证大小


  • byte (改用 uint8int8


  • bool 而不是 boolean


  • additional basic type: unichar ,表示 Unicode 字符


常量修饰符: const 而不是 final .


Vala 的基本类型有方法,例如

int a = -4.abs ();
string s = a.to_string ();
int b = int.max (5, 7);      // static method call on 'int'

 字符串

 爪哇岛

 数据类型: String

 相等性测试: str1.equals(str2)

 瓦拉


数据类型: string (小写)

 相等性测试: str1 == str2


字符串比较比较的是内容,而不是引用。你可以用 < 、 、 > <= >= 等按字典顺序比较字符串。字符串可以与 switch .


Vala 字符串采用 UTF-8 编码。


Vala String 的其他功能


Vala 支持逐字字符串: """..."""

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 支持字符串模板: @"..." .字符串模板可以包含以 $ 符号为前缀的表达式。

string name = "John";
stdout.printf (@"Welcome, $name!");
stdout.printf (@"3 + 2 = $(3 + 2)");

 阵 列

 动态增长


您可以使用 运算符 += 动态地将元素添加到数组中。数组将重新分配 2 的幂大小:

int[] squares = {};
for (int i = 0; i < 100; i++) {
    squares += i * i;
}

 无边界检查


但是,Vala 中没有对数组进行运行时边界检查:

int[] a = new int[10];
a[20] = 1;  // not safe!


(计划在 Vala 的未来版本中进行可选的边界检查。

 多维数组


Java:交错多维数组 [][] (数组的数组)

int[][] matrix = new int[3][];
for (int[] row : matrix) {
    row = new int[4];
}


Vala:矩形多维数组 [,][,,] 等(分配为一个连续的内存块),计划支持交错数组

int[,] matrix = new int[3,4];


插图:矩形与锯齿状多维数组

multidimensional-arrays.png

 类型推理


Vala 支持一种称为局部变量类型推断(隐式类型)的机制:如果编译器可以从初始赋值中推断(推断)类型,则可以使用 var 关键字而不是类型名称来声明局部变量。这有助于避免不必要的冗余,并且对于泛型类型特别有用。例子:

var obj = new Object ();
var map = new HashMap<string, int> ();
var str = "hello, world";
var arr = new int[10];

 而不是

Object obj = new Object ();
HashMap<string, int> map = new HashMap<string, int> ();
string str = "hello, world";
int[] arr = new int[10];


尽管如此,一切都是静态类型的。

 Foreach (查找)

 爪哇岛: for (int i : numbers) { }

 瓦拉: foreach (int i in numbers) { }

 遗产


爪哇: extendsimplements

public class Demo extends Foo implements Bar {
    public Demo() {
        super();
    }
}


Vala:冒号后跟逗号分隔的列表,用于超类和接口

public class Demo : Foo, Bar {
    public Demo () {
        base ();
    }
}


super 在 Vala 中称为 base

 Object 基类


Java:从 Objectjava.lang.Object) 隐式继承

public class Foo {
    // ...
}


Vala:没有来自 ObjectGLib.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, default methods (JDK 8+)

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 o= (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 lambdas (Java 8+)

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 = (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 or with Java 8+ lambdas can be used. However, anonymous inner classes can only capture final variables of the outer scope, whereas Vala closures can capture any variable.

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

Button

JCheckBox

CheckButton

JColorChooser

ColorSelection

JComboBox

ComboBox

JComponent

Widget

JDialog

Dialog

JEditorPane

TextView

JFileChooser

FileChooserDialog

JFrame

Window

JLabel

Label

JList

TreeView with ListStore

JMenu

Menu

JMenuBar

MenuBar

JOptionPane

MessageDialog

JPanel

Container (depending on layout: Box, Table, Fixed, ...)

JPasswordField

Entry with visibility = false

JProgressBar

ProgressBar

JRadioButton

RadioButton

JScrollPane

ScrolledWindow

JSeparator

Separator

JSlider

Scale

JSpinner

SpinButton

JSplitPane

Paned

JTabbedPane

Notebook

JTable

TreeView with ListStore

JTextArea

TextView

JTextField

Entry

JTextPane

TextView

JToolBar

Toolbar

JToolTip

Tooltip

JTree

TreeView with TreeStore

JViewport

Viewport

Projects/Vala/ValaForJavaProgrammers (last edited 2020-01-05 21:44:18 by KenGilmer)