Section A.2, Java Library Methods and Kotlin Code.
Calling Java library methods from Kotlin code
is the most common interaction between the two languages.
In fact, no Kotlin program running on a JVM
can avoid calling Java methods,
whether explicitly or implicitly.
This is because most Kotlin standard library functions
call Java standard library methods.
Calling Java methods from Kotlin code
would be simple if Kotlin and Java types were the same,
but they aren't.
This is fortunate because Kotlin types
are much more powerful than Java types,
but it means you have to be careful
how you handle the differences and the conversions.
Section A.2.1, Using Java Primitives.
The most visible difference
is probably the absence of primitives in Kotlin.
In Java, int and integer are the primitive
and object representations of an integer value, respectively.
Kotlin only uses int,
which is sometimes called a value type,
meaning that it can be handled like an object,
but performs like a primitive.
But Java may well have value types in the near future.
Although an int is an object in Kotlin,
computation is done under the hood
as if it were a primitive.
The same is true for other Java primitives
that have value type equivalents in Kotlin,
such as byte, short, long, float, double, and Boolean.
All have a corresponding value type in Kotlin.
The only difference,
besides that they must be handled as objects,
is that in Kotlin, the first letter is a capital letter.
Kotlin automatically does the conversion
between Java primitives and Kotlin value types.
You can still use the integer Java type in Kotlin,
but you won't gain any of the benefits of using value types.
In Kotlin, you can also use
the other numeric Java object types,
but as the names are the same,
you'll have to use the fully qualified name,
such as java.lang.long.
You'll then get the following compile warning.
See this code.
You should almost always avoid
using Java numerical object types
because Kotlin does a serious job
of handling the conversion.
Consider the following.
See this code.
This won't compile
and you'll get the following error message.
See this code.
Kotlin automatically converts the result of the call
to the java.lang.long.valueof method to kotlin.long,
so this code doesn't compile.
You can, however, write.
See this code.
But why would you want to do so?
Java primitives are converted to non-nullable types.
For example, java.int is converted to int,
but the object numerical types
are converted to nullable types.
For example, java.integer is converted to int?
Section A.2.2, using Java numerical object types.
Java also provides numerical types
that are equivalent, such as big integer and big decimal.
These types can be used in Kotlin
with the additional benefit
that Kotlin simplifies their handling.
For example, you can write.
See this code.
This prints.
See this code.
Not only can you use the plus operator with big integer,
but you can compare it with double equals for equality.
This is because Kotlin converts plus
into a call to the add method
and double equals into a call to the equals method.
In Kotlin, comparing for identity
is made with the triple equals operator.
Section A.2.3, failing fast on null values.
Java object types are always nullable,
but primitive types aren't.
Kotlin makes a distinction
between nullable and non-nullable types.
For example, the infrared type for big integer.valueof
is Kotlin big integer question mark.
Kotlin also offers the big integer type,
which is a subtype of big integer question mark
and isn't nullable.
If you were to write the types explicitly, you'd get.
See this code.
But in this case,
you wouldn't be able to use the plus operator
because this would result
in a possible null pointer exception.
The dereferencing operator can't be used either.
Here's what you'd have to do instead.
See this code.
Here you're using the ?.safe dereferencing operator,
which returns null if the value it's used on is null.
If you let Kotlin infer the type,
Kotlin does something like this.
See this code.
This code won't compile, but it shows what Kotlin does.
Big integer exclamation point
is what is called a non-denotable type,
meaning a type that you can't write in your program,
but one that the Kotlin compiler uses internally.
IntelliJ will show these types where they are inferred.
What you write is this.
See this code.
Kotlin will throw a null pointer exception
if the value returned by the Java method is null.
This, of course, will never occur with biginteger.valueof,
but with Java methods that could return null,
there are many of them in the Java standard library.
It ensures your program will fail as fast as possible,
preventing the null to leak inside your code.
If you prefer,
you can still declare the type explicitly as nullable,
such as biginteger?
See chapter two for more information
about nullable types in Kotlin.
Section A.2.4, Using Kotlin and Java String Types.
Kotlin uses a special string type called kotlin.string,
whereas Java uses the java.lang.string type.
Once again, the Kotlin type is much more powerful.
To show a simple example,
look at what you have to do
to remove the last character of a string in Java.
See this code?
The equivalent code in Kotlin is this.
See this code?
The kotlin.string class offers dozens
of useful functions like this one.
Besides this, conversion from and to java.lang.string
is fully automated and transparent to the programmer.
Section A.2.5, Implementing Other Type Conversions.
Collections and arrays provide
the main other type conversions
that occur when calling Java methods.
Arrays of primitives are converted to special types,
byte array, int array, long array, and so on.
Arrays of objects of type T are converted to array of T,
which are invariant, like Java arrays.
But you can use variant arrays if you specify those.
For example, array out T.
By default, collections are converted
into mutable collections of non-nullable types.
For example, a java.util.list string
is converted to a kotlin.collections.mutablelist string.
Although Kotlin converts Java collections
to Kotlin non-nullable collections of non-nullable types,
it will only verify that the collection is not null,
but it will not check whether
the collection contains null elements.
This could be a huge problem
because you might assume it would do this check at runtime.
Let's say you have the following Java code.
See this code?
You might want to call the getIntegrList method
from Kotlin as see this code.
This causes no error and prints.
See this code?
But if you do the following in Kotlin,
see this code,
you'll get a null pointer exception
when Kotlin tries to call the add function on null.
Section A.2.6, using Java varargs.
When calling a Java method,
taking a vararg as its argument from Kotlin,
Kotlin lets you use an array
prefixed with the spread operator, asterisk.
Consider the following example of a Java method.
See this code?
This method can be called from Kotlin using an array.
See this code?
Section A.2.7, specifying nullability in Java.
As I said earlier,
all non-primitive Java types are always nullable.
On the other hand, they can be annotated
and many tools use such annotations
to indicate that references of certain types
should never be null.
Although there's a standard specification for this,
jsr305.javax.annotation,
many tools prefer their own set of annotations.
IntelliJ uses the at nullable and at not null
from the org.jetbrains.annotations package
to specify nullability in Java.
Eclipse uses the org.eclipse.jdt.annotation package.
Android has the com.android.annotations
and android.support.annotations packages.
FindBugs uses the edu.umd.cs.findbugs.annotations.
When used to specify nullability,
Kotlin understands all these annotations and more.
For example, a Java property can be annotated with,
see this code?
IntelliJ flags the null element with a message saying,
passing null argument to parameter annotated
with at not null,
but this doesn't prevent the Java code from compiling.
When calling this method from Kotlin,
the infrared type is mutable list of int
instead of mutable list of int exclamation point,
exclamation point,
and the compiler will issue an exception.
See this code?
Unfortunately, this won't work for the type parameter.
Consider the following Java method.
See this code?
You'll get a warning about the null value in Java,
but nothing in Kotlin until you try using the null value,
which causes a null pointer exception.
Using at not null on a type parameter
isn't different than specifying a non-null parameter type
on the Kotlin side,
or even not specifying any type.
That's because Kotlin infers list of int exclamation point,
non-denotable type,
giving the exact same result.
If, however, you want to use parameter type annotations,
you'll have to use at least version 1.5.0
of the org.jetbrains.annotation library
and have your compilation target level
set to at least Java 8.
Note, Kotlin supports the JSR 305 specification,
so if you need more Java annotation support,
refer to this link.
Section A.2.8, calling getters and setters.
Java getters and setters can be called
as standard methods from Kotlin code.
Kotlin also allows and recommends calling them
with the Kotlin property syntax.
Let's say you have the following Java class.
See this code.
You can access the value property
using either the method syntax or the property syntax.
See this code.
The former is highly recommended.
The property syntax can be used to read the Java field
when there's no setter,
which is the case if the field is initialized
in the constructor.
It'll work even if there's no field at all, such as.
See this code.
But it won't work for setting a property with no getter.
For Boolean properties with a Java getter starting with is,
the Kotlin property name is prefixed with is.
Consider the following Java class.
See this code.
These properties can be read in Kotlin
using the following syntax.
See this code.
This avoids the clash that would occur
if a Java class has both is something
and get something methods.
Setters in Java are actually methods returning void.
If such methods are called from Kotlin
with the method function syntax, they return unit,
which is a singleton object.
See this code.
Section A.2.9, accessing Java properties
with reserved names.
Sometimes you might need to access
from Kotlin a Java property that has a name
that clashes with a reserved word in Kotlin,
such as in and is, that are used as short names
for input or input stream.
If you're writing both the Java or the Kotlin code,
the best thing to do is to avoid such names.
But if you're using a library you don't control,
you can use backticks to escape the property name.
Here's an example.
Java class.
See this code.
Kotlin code.
See this code.
Section A.2.10, calling checked exceptions.
In Kotlin, all exceptions are unchecked.
As a consequence, Kotlin lets you call a Java method
throwing a checked exception
without using a try-catch block.
Java.
See this code.
Kotlin.
See this code.
Unlike what's often done in Java,
this doesn't work as a wrapper.
If you use a try-catch block and an exception is thrown,
it'll still be the original exception
and not an unchecked wrapper exception.