面向 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 参数是可选的
基本类型
标准类型 ( int , long , ...) 的大小取决于体系结构。使用 sizeof () 获取类型的大小(以字节为单位), sizeof (int) 例如
其他 Vala 类型 int8 、 、 int16 int32 、 int64 (有符号)、 uint8 、 uint16 、 uint32 uint64 (无符号) 具有独立于架构的保证大小
否 byte (改用 uint8 ) int8
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];
插图:矩形与锯齿状多维数组
类型推理
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) { }
遗产
爪哇: extends , implements
public class Demo extends Foo implements Bar {
public Demo() {
super();
}
}
Vala:冒号后跟逗号分隔的列表,用于超类和接口
public class Demo : Foo, Bar {
public Demo () {
base ();
}
}
super 在 Vala 中称为 base 。
Object 基类
Java:从 Object (java.lang.Object) 隐式继承
public class Foo {
// ...
}
Vala:没有来自 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, 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 |
|
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 |