What you can learn from kotlin
Kotlins compiles to the same byte code as Java, interoperates with Java classes in natural ways, and shares its tooling with Java. Because there is no overhead for calling back and forth between Kotlin’s and Java, adding Kotlin’s incrementally to an Android app currently in Java makes perfect sense. The few cases where the interoperability between Kotlin and Java code lacks grace, such as Java set-only properties, are rarely encountered and easily fixed.
Since the release of Android Studio 3.0 in October 2017, Kotlin’s has been included as an alternative to the standard Java compiler. The Android Kotlin compiler lets the user choose between targeting Java 6 or Java 8 compatible bytecode. Allowing top-level functions is just the beginning of the functional programming story for Kotlin. The language also supports higher-order functions, anonymous functions, lambdas, inline functions, closures, tail recursion, and generics. In other words, we has all of the features and advantages of a functional language. For example, consider the following functional idioms. Kotlin has single inheritance from a named superclass, and all Kotlin classes have a default superclass Any, which is not the same as the Java base class java.lang.Object. Any contains only three predefined member functions: equals(), hashCode(), and toString(). Kotlin classes have to be marked with the open keyword in order to allow other classes to inherit from them; Java classes are kind of the opposite, as they are inheritable unless marked with the final keyword. To override a superclass method, the method itself must be marked open, and the subclass method must be marked override. This is all of a piece with Kotlin’s philosophy of making things explicit rather than relying on defaults. In this particular case, I can see where Kotlin’s way of explicitly marking base class members as open for inheritance and derived class members as overrides avoids several kinds of common Java errors.