-- | Java | Kotlin |
---|---|---|
Build/Run/Dist | Gradle | Gradle |
Testing | Junit | Junit |
Code coverage | jacoco | jacoco |
Static analysis | PMD | Detekt, CPD |
Code linting | checkstyle | ktlint |
Mocking | Mockito | MockK |
Bytecode tools | infer | spotbugs/findbugs |
- Type system superiority
- Nullability built in, default non-null (
arg: String
is non-null,arg: String?
is nullable) - No raw types (
List
must have a type specified, evenAny?
) - Array invariance (Can't assign
Array<Int>
toArray<Any>
without a type projection [below]) - Function types (Don't require an interface class for more than 2-arg lambdas)
- Declaration-site variance and type projections [kotlin variance] [variance explained]
- Java only has use-site type variance but has wanted to add declaration-site variance for some time [link]
- Kotlin type projections provide use-site variance
- Nullability built in, default non-null (
- Mutability as a language construct
- Built-in to allocation syntax,
var
mutable,val
immutable - Kotlin standard library separates mutable and immutable object APIs as well (
listOf(1,2,3)
returnsImmutableList
,mutableListOf(1,2,3)
returnsMutableList
)
- Built-in to allocation syntax,
- Coroutines
- Code length
- Functional constructs
- Function types (above)
- Inline functions (let the compiler inline your lambda)
- Extension functions (extend third-party classes with new functionality)
- Trailing lambdas
- Singleton objects, lazily initialized and thread-safe
- Data classes (Java has record classes but Data classes are much more flexible)
- Syntactic enhancements
lazy
keyword to lazily initialize anything- function default values
- named parameters
- range expressions
- string templates
- multiline string (now in java)
- smart casts built into the compiler
lateinit
keyword- property and interface delegates using the
by
keyword typealias
keywordinfix
keyword for infix notation (1 plus 2
byinfix fun Int.plus(x: Int)
)tailrec
keyword to label tail recursive functions for loop conversion- constructor hierarchy enforced by the compiler (must have all n-ary constructors call through to the primary constructor)
- Generates JVM bytecode (interoperable with just about any library that also generates JVM bytecode)
- Mature compilation constructs (slightly faster language compilation)
- More mature tooling around java projects (PMD, jmh, etc.)
- Ternary operator
- Static notation is more straightforward than Kotlin versions
- Dedicated primitive types are more intuitive than using boxed classes (though they are optimized down to actual primitives where possible in Kotlin)
- Checked Exceptions
Coming to Java, in an arguably better way (can implement custom templates): https://openjdk.org/jeps/430