232 lines
11 KiB
Plaintext
232 lines
11 KiB
Plaintext
[Kotlin] is designed with *Java*\-compatibility in mind. Existing *Java* code can be called from [Kotlin] in a natural way, and [Kotlin] code can be used from *Java* rather smoothly as well.
|
|
|
|
h2. Calling Java code from [Kotlin]
|
|
|
|
In this section we describe some details about calling *Java* code from [Kotlin]. In most cases, you just use it:
|
|
{jet}
|
|
import java.util.*
|
|
|
|
fun demo(source : List<Int>) {
|
|
val list = ArrayList<Int>()
|
|
// 'for'-loops work for Java collections:
|
|
for (item in source)
|
|
list.add(item)
|
|
// Operator conventions work as well:
|
|
for (i in 0..source.size() - 1)
|
|
list[i] = source[i] // get and set are called
|
|
}
|
|
{jet}
|
|
|
|
h3. {{void}}\-returning methods
|
|
|
|
If a *Java* method returns *void*, it will return {{Unit}} when called from [Kotlin]. If, by any chance, someone uses that return value, it will be assigned at the call site by the [Kotlin] compiler, since the value itself is known in advance (being {{()}}).
|
|
|
|
h3. Escaping for Java identifiers that are keywords in [Kotlin]
|
|
|
|
Some of the [Kotlin] keywords are valid identifiers in *Java*: *in*, *object*, *is*, etc. It may happen that some of your favorite *Java* libraries use these words as names for methods. In this situation you still can call those methods from [Kotlin], but you need to _escape_ their names with backticks:
|
|
{jet}
|
|
foo.`is`(bar)
|
|
{jet}
|
|
|
|
h3. Null-safety
|
|
|
|
Any reference in *Java* may be {{null}}. So, all the *Java* methods called from [Kotlin] return [nullable references|Null-safety] (except for those annotated with [{{@NotNull}}|http://www.jetbrains.com/idea/documentation/howto.html]). This allows [Kotlin] to keep the guarantee of [having no {{NullPointerExceptions}}|Null-safety] unless they are explicitly thrown by [Kotlin] code or caused by something inside *Java* code called from [Kotlin].
|
|
|
|
Consider the following examples:
|
|
{jet}
|
|
val list = ArrayList<Int>() // non-null (constructor result)
|
|
val size = list.size() // non-null (primitive int)
|
|
val iterator = list.iterator() // nullable (ordinary method)
|
|
{jet}
|
|
|
|
h3. Checked exceptions
|
|
|
|
In [Kotlin], [all exceptions are unchecked|Exceptions], meaning that the compiler does not force you to catch any of them. So, when you call a *Java* method that declares a checked exception, [Kotlin] does not force you to do anything:
|
|
|
|
{jet}
|
|
fun render(list : List<out Any?>, to : Appendable) {
|
|
for (item in list)
|
|
to.append(item.toString()) // Java would require us to catch IOException here
|
|
}
|
|
{jet}
|
|
|
|
{anchor:Java generics}
|
|
|
|
h3. Java generics in [Kotlin]
|
|
|
|
[Kotlin]'s generics are a little different from *Java*'s (see [Generics]). When importing *Java* types to [Kotlin] we perform some conversions:
|
|
* *Java*'s wildcards are converted into [type projections|Generics#Type projections]
|
|
** {{Foo<? extends Bar>}} becomes {{Foo<out Bar>}}
|
|
** {{Foo<? super Bar>}} becomes {{Foo<in Bar>}}
|
|
* *Java*'s raw types are converted into [star projections|Generics#Star-projections]
|
|
** {{List}} becomes {{List<*>}}, i.e. {{List<out Any?>}}
|
|
|
|
Besides, *Java*'s generics are not [retained at runtime|Generics#Reified generics], i.e. *Java* objects do not carry information about actual type arguments passed to their constructors, i.e. {{new ArrayList<Integer>()}} is indistinguishable from {{new ArrayList<Character>()}}. This makes it impossible to perform *instanceof*\-checks that take *Java* generics into account. [Kotlin] only allows *is*\-checks for [star-projected|Generics#Star-projections] *Java*'s generic types:
|
|
{jet}
|
|
if (a is <error desc="java.util.List is a Java class and its generic application to <Int> cannot be used in 'is'">java.util.List<Int></error>) // Error: cannot check if it is really a List of Ints
|
|
// but
|
|
if (a is java.util.List<*>) // OK: no guarantees about the contents of the list
|
|
{jet}
|
|
|
|
{anchor:Arrays}
|
|
|
|
h3. Invariant arrays
|
|
|
|
Arrays in [Kotlin] are [_invariant_|Generics#Declaration-site variance], unlike [*Java*|http://c2.com/cgi/wiki?JavaArraysBreakTypeSafety]. This means that [Kotlin] does not let us assign an {{Array<String>}} to an {{Array<Any>}}, which prevents a possible runtime failure. Neither does it allow us to pass an array of a subclass as an array of superclass to a *Java* method. In most cases, this should not be a major obstacle, but if one _really_ needs to pass an array in a covariant way, they may cast explicitly.
|
|
|
|
On the Java platform, having a generic class {{Array}} to represent arrays leads to a lot of boxing/unboxing operations. As arrays are mostly use where performance is critical, we introduced a workaround for this issue and defined classes {{IntArray}}, {{DoubleArray}}, {{CharArray}} and so on, which are not related to the Array class and are compiled down to Java's primitive arrays.
|
|
|
|
h3. Object methods
|
|
|
|
When *Java* types are imported into [Kotlin], all the references of type {{java.lang.Object}} are turned into {{Any?}}, for any reference may be used there.
|
|
|
|
The big difference between {{java.lang.Object}} and {{Any}} is that {{Any}} does not declare _any_ members at all. This is due to the [inheritance rules|Classes and Inheritance#Overriding rules] in [Kotlin]. Now, what do we do if we need our {{toString()}}, {{equals()}} etc?
|
|
|
|
h5. toString()
|
|
|
|
{{toString()}} is declared as an [extension function|Extension functions] that looks for an instance function named {{toString}} and calls it. If there's no {{toString}} it returns some default like {{this.javaClass.getName() + "@" + System.identityHashCode(this)}}.
|
|
|
|
From the programmer's perspective almost nothing changes compared to *Java*: all the existing *toString()* implementations work, and when you need a custom {{toString}} for your class, you simply put if there:
|
|
{jet}
|
|
class A() {
|
|
fun toString() : String = "A"
|
|
}
|
|
{jet}
|
|
You don't have to make it *virtual*, and you are allowed to put *override* there only if one of the superclasses declares it *virtual*.
|
|
|
|
h5. equals()
|
|
|
|
In [Kotlin], {{==}} stands for a [guarded call to {{equals()}}|Basic operations#Equality]. The expression on the left-hand side must have a method named {{equals}} that takes one parameter of type {{Any?}} and returns {{Boolean}}. Thus, all the *Java* objects have it out of the box. On the other hand, there's an extension function to {{Any?}} that performs the same kind of lookup as {{toString()}}.
|
|
|
|
h5. hashCode()
|
|
|
|
{{hashCode()}} works for *Java* objects.
|
|
|
|
In the upcoming [Kotlin] standard library we plan to have a {{Hashable}} interface that is required for something to be put into a _non-identity_ hash-map.
|
|
|
|
h5. wait()/notify()
|
|
|
|
[Effective Java|http://java.sun.com/docs/books/effective] Item 69 kindly suggests to *Prefer concurrency utilities to wait and notify*. Thus, these methods are not available on references of type {{Any}}, only on *Java* objects.
|
|
|
|
h5. getClass()
|
|
|
|
To retrieve the type information from an object, one uses the [{{javaClass}}|Runtime Type Information] extension function. {{getClass()}} is available for *Java* objects.
|
|
|
|
h5. finalize()
|
|
|
|
{{finalize()}} can be overridden exactly like {{toString()}}
|
|
|
|
h5. clone()
|
|
|
|
{{clone()}} can be overridden like {{toString()}} but with specifying {{Cloneable}} as a supertype. Do not forget about [Effective Java|http://java.sun.com/docs/books/effective] Item 11: *Override clone judiciously*.
|
|
|
|
h3. Inheritance from Java classes
|
|
|
|
At most one *Java*\-class (and as many *Java* interfaces as you like) can be a supertype for a class in [Kotlin]. This class must go first in the supertype list.
|
|
|
|
h3. Accessing static members
|
|
|
|
Static members of *Java* classes form "class objects" for these classes. One cannot pass such a "class object" around as a value, but can access the members explicitly, for example
|
|
{jet}
|
|
if (Character.isLetter(a)) {
|
|
// ...
|
|
}
|
|
{jet}
|
|
|
|
h2. Calling [Kotlin] code from Java
|
|
|
|
We plan to target more platforms in the future, but currently, [Kotlin] is only compiled for the *Java* platform. This means that the compiler generates *Java* bytecode, and thus the code that we write in [Kotlin] can be called from *Java*. There are some concepts in [Kotlin] that are not available in *Java*, though. In this section, we briefly describe how these concepts are mapped to *Java* concepts.
|
|
|
|
h3. Package-level functions
|
|
|
|
All the functions and properties declared inside a [*package*|Packages] {{org.foo.bar}} are put into a *Java* class named {{org.foo.bar.namespace}}.
|
|
|
|
{jet}
|
|
package demo {
|
|
class Foo() {
|
|
}
|
|
|
|
fun bar() {
|
|
}
|
|
}
|
|
{jet}
|
|
|
|
{code}
|
|
// Java
|
|
new Foo();
|
|
demo.namespace.bar();
|
|
{code}
|
|
|
|
h3. Checked exceptions
|
|
|
|
As we mentioned above, [Kotlin] does not have checked exceptions. So, normally, the *Java* signatures of [Kotlin] functions do not declare exceptions thrown. Thus if we have a function in [Kotlin] like this:
|
|
{jet}
|
|
package demo
|
|
|
|
fun foo() {
|
|
throw IOException();
|
|
}
|
|
{jet}
|
|
And we want to call it from *Java* and catch the exception:
|
|
{jet}
|
|
// Java
|
|
try {
|
|
demo.namespace.foo();
|
|
}
|
|
catch (<error desc="Exception IOException is never thrown in the corresponding try block">IOException e</error>) { // error: foo() does not declare IOException in the throws list
|
|
// ...
|
|
}
|
|
{jet}
|
|
we get an error message from the *Java* compiler, because {{foo()}} does not declare {{IOException}}. Now, what should we do? There are a few options:
|
|
* Option one (suggested in the comments below) is to create a pseudo-throwing function in Java:
|
|
{code}
|
|
// Java
|
|
<E extends Throwable> void mayThrow(Class<E> eClass) throws E {
|
|
// Do nothing
|
|
}
|
|
{code}
|
|
And then write:
|
|
{code}
|
|
// Java
|
|
try {
|
|
mayThrow(IOException.class);
|
|
demo.namespace.foo();
|
|
}
|
|
catch (IOException e) { // No problem
|
|
// ...
|
|
}
|
|
{code}
|
|
* Option two is to catch {{Throwable}} and do an *instanceof* check. This is not very elegant, but will work.
|
|
* Option three is to write a wrapper function in *Java*:
|
|
{jet}
|
|
void foo() throws IOException { // Java does not require us to throw an exception if we declare one
|
|
demo.namespace.foo();
|
|
}
|
|
{jet}
|
|
Now, you can call {{foo()}} instead of {{demo.namespace.foo()}}, and catch the exception.
|
|
* Option four is to make [Kotlin] put a *throws* list to the {{foo()}}'s signature with the *throws* annotation:
|
|
{jet}
|
|
throws<IOException> fun foo() {
|
|
throw IOException();
|
|
}
|
|
{jet}
|
|
|
|
h3. Runtime Type Information
|
|
|
|
{note:title=Runtime Generics are not implemented yet}{note}
|
|
|
|
[Kotlin]'s generics are retained at runtime, this means that upon object creation, we pass the type information as parameter to the constructor:
|
|
{code}
|
|
// Java
|
|
new SomeClassDesclaredInKotlin<Integer>(TypeInfos.Int()) // We are passing a TypeInfo object explicitly
|
|
{code}
|
|
|
|
And the same for generic functions.
|
|
|
|
h3. Null-safety
|
|
|
|
When calling [Kotlin] functions from *Java*, nobody prevents us from passing a {{null}} as a non-null parameter. That's why [Kotlin] generates runtime checks for all *public* functions that expect non-nulls. This way we get a {{NullPointerException}} in the *Java* code immediately.
|
|
|
|
h3. Properties
|
|
|
|
Property getters are turned into {{get}}\-methods, and setters -- into {{set}}\-methods. |