Things to consider when calling Java from Kotlin.
fun main() {
val car = Car("silver", "Audi", "A3", "3.2 V6", "Leather", 2004)
car.colour = "Akoya silver" // Can only refer to this like a property if getter and setters are set in Java. Will work without setter if property is public, but not usually desirable
// Wildcard assignments in Java are converted to use-site variance in Kotlin. ? extends someClass -> out someClass, ? super someClass -> in someClass
// If you call a Java method that throws an exception and you don't handle the exception in the code, you don't have to declare that the Kotlin function throws the exception - Kotlin doesn't care
// varargs: If you want to call a Java method that wants multiple arguments:
car.variableMethod(5, "hello", "goodbye") // This works
val strings = arrayOf("hello", "goodbye")
// car.variableMethod(10, strings) // But it doesn't allow us to pass in an array
car.variableMethod(10, *strings) // So we need to use the spread operator to unpack the array
// Kotlin doesn't have void, so it will return Unit
// As previously discussed, when Java method expects primitive types we cannot use arrayOf. We need to use e.g. intArrayOf or call .toIntArray on the array:
// car.wantsIntArray(arrayOf(1, 2, 3)) // Nope
car.wantsIntArray(intArrayOf(1, 2, 3)) // Fine
car.wantsIntArray(arrayOf(1, 2, 3).toIntArray()) // Fine
// Any? is top of Kotlin hierarchy, Object is top of Java. What happens when Java calls Object explicitly? Will be treated like Any in Kotlin.
// However, does not have methods such as wait(), notify(), clone() or finalize(). If wanting to call these cast the variable to java.lang.Object in your Kotlin code:
// car.anObject.equals("bh") // Has equals() method and some others but missing the methods listed above
// (car.anObject as java.lang.Object).notify() // All methods now available on casting
// Static methods and fields are translated to companion objects. You can't pass the companion object around as a value but you can use its members
println("x = ${Car.x}") // Accessing static variable
println(Car.xString()) // The same as calling a companion object
// Single Abstract Method (SAM) interface as of Java 8, can use lambda. E.g. Runnable interface is a SAM (see Car.java demoMethod and demoMethod2)
// If a Java method wants an object that implements a SAM interface e.g. Runnable then you can pass it a Kotlin function:
car.demoMethod3 ({ println("I'm in a Thread") }) // Function signature has to match parameter, in this case Runnable
}
package academy.learnprogamming.javainteroperability;
import org.jetbrains.annotations.NotNull; // N.B. Had to prompt for download from Maven
import org.jetbrains.annotations.Nullable;
public class Car {
public static int x = 5;
private String colour;
private String manufacturer;
private String model;
private String variant;
private String interior;
private int year;
private Object anObject;
public Car(String colour, String manufacturer, String model, String variant, String interior, int year) {
this.colour = colour;
this.manufacturer = manufacturer;
this.model = model;
this.variant = variant;
this.interior = interior;
this.year = year;
}
public void demoMethod() {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I'm in a Thread");
}
}).start();
}
public void demoMethod2() {
new Thread(() -> System.out.println("I'm in a Thread")).start();
}
public void demoMethod3(Runnable r) {
new Thread(r).start();
}
public static String xString() {
return "This is x: " + x++;
}
public String getColour() {
return colour;
}
public void setColour(@NotNull String colour) { // @NotNull comes from JetBrains, not Java. Not enforced by Java.
this.colour = colour;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(@Nullable String manufacturer) {
this.manufacturer = manufacturer;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getVariant() {
return variant;
}
public void setVariant(String variant) {
this.variant = variant;
}
public @Nullable String getInterior() {
return interior;
}
public void setInterior(String interior) {
this.interior = interior;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public Object getAnObject() {
return anObject;
}
public void setAnObject(Object anObject) {
this.anObject = anObject;
}
public void variableMethod(int num, String... strings) {
for (String string: strings) {
System.out.println(string);
}
}
public void wantsIntArray(int[] theArray) {
for (int i: theArray) {
System.out.println(i);
}
}
@Override
public String toString() {
return "Car{" +
"colour='" + colour + '\'' +
", manufacturer='" + manufacturer + '\'' +
", model='" + model + '\'' +
", variant='" + variant + '\'' +
", interior='" + interior + '\'' +
", year=" + year +
'}';
}
}
