Merge branch 'master' of https://github.com/eugenp/tutorials
This commit is contained in:
@@ -34,3 +34,7 @@
|
||||
- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
|
||||
- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
|
||||
- [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum)
|
||||
- [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project)
|
||||
- [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection)
|
||||
- [Get a Random Number in Kotlin](http://www.baeldung.com/kotlin-random-number)
|
||||
- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging)
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
<version>${kotlin-reflect.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
@@ -224,10 +223,11 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<kotlin-maven-plugin.version>1.2.41</kotlin-maven-plugin.version>
|
||||
<kotlin-test-junit.version>1.2.41</kotlin-test-junit.version>
|
||||
<kotlin-stdlib.version>1.2.41</kotlin-stdlib.version>
|
||||
<kotlin-reflect.version>1.2.41</kotlin-reflect.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin-maven-plugin.version>1.2.51</kotlin-maven-plugin.version>
|
||||
<kotlin-test-junit.version>1.2.51</kotlin-test-junit.version>
|
||||
<kotlin-stdlib.version>1.2.51</kotlin-stdlib.version>
|
||||
<kotlin-reflect.version>1.2.51</kotlin-reflect.version>
|
||||
<kotlinx.version>0.22.5</kotlinx.version>
|
||||
<ktor.io.version>0.9.2</ktor.io.version>
|
||||
<mockito-kotlin.version>1.5.0</mockito-kotlin.version>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.baeldung.builder
|
||||
|
||||
class FoodOrder private constructor(builder: FoodOrder.Builder) {
|
||||
|
||||
val bread: String?
|
||||
val condiments: String?
|
||||
val meat: String?
|
||||
val fish: String?
|
||||
|
||||
init {
|
||||
this.bread = builder.bread
|
||||
this.condiments = builder.condiments
|
||||
this.meat = builder.meat
|
||||
this.fish = builder.fish
|
||||
}
|
||||
|
||||
class Builder {
|
||||
|
||||
var bread: String? = null
|
||||
private set
|
||||
var condiments: String? = null
|
||||
private set
|
||||
var meat: String? = null
|
||||
private set
|
||||
var fish: String? = null
|
||||
private set
|
||||
|
||||
fun bread(bread: String) = apply { this.bread = bread }
|
||||
|
||||
fun condiments(condiments: String) = apply { this.condiments = condiments }
|
||||
|
||||
fun meat(meat: String) = apply { this.meat = meat }
|
||||
|
||||
fun fish(fish: String) = apply { this.fish = fish }
|
||||
|
||||
fun build() = FoodOrder(this)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.builder
|
||||
|
||||
class FoodOrderApply {
|
||||
var bread: String? = null
|
||||
var condiments: String? = null
|
||||
var meat: String? = null
|
||||
var fish: String? = null
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.builder
|
||||
|
||||
data class FoodOrderNamed(
|
||||
val bread: String? = null,
|
||||
val condiments: String? = null,
|
||||
val meat: String? = null,
|
||||
val fish: String? = null)
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.kotlin.logging
|
||||
|
||||
import org.slf4j.Logger
|
||||
|
||||
open class LoggerAsExtensionOnAny {
|
||||
val logger = logger()
|
||||
|
||||
fun log(s: String) {
|
||||
logger().info(s)
|
||||
logger.info(s)
|
||||
}
|
||||
}
|
||||
|
||||
class ExtensionSubclass : LoggerAsExtensionOnAny()
|
||||
|
||||
fun <T : Any> T.logger(): Logger = getLogger(getClassForLogging(javaClass))
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
LoggerAsExtensionOnAny().log("test")
|
||||
ExtensionSubclass().log("sub")
|
||||
"foo".logger().info("foo")
|
||||
1.logger().info("uh-oh!")
|
||||
SomeOtherClass().logger()
|
||||
}
|
||||
|
||||
class SomeOtherClass {
|
||||
fun logger(): String {
|
||||
return "foo"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.kotlin.logging
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
interface Logging
|
||||
|
||||
inline fun <reified T : Logging> T.logger(): Logger =
|
||||
//Wrong logger name!
|
||||
//LoggerFactory.getLogger(javaClass.name + " w/interface")
|
||||
LoggerFactory.getLogger(getClassForLogging(T::class.java).name + " w/interface")
|
||||
|
||||
open class LoggerAsExtensionOnMarkerInterface : Logging {
|
||||
companion object : Logging {
|
||||
val logger = logger()
|
||||
}
|
||||
|
||||
fun log(s: String) {
|
||||
logger().info(s)
|
||||
logger.info(s)
|
||||
}
|
||||
}
|
||||
|
||||
class MarkerExtensionSubclass : LoggerAsExtensionOnMarkerInterface()
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
LoggerAsExtensionOnMarkerInterface().log("test")
|
||||
MarkerExtensionSubclass().log("sub")
|
||||
"foo".logger().info("foo")
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.kotlin.logging
|
||||
|
||||
open class LoggerAsProperty {
|
||||
private val logger = getLogger(javaClass)
|
||||
|
||||
fun log(s: String) {
|
||||
logger.info(s)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PropertySubclass : LoggerAsProperty()
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
LoggerAsProperty().log("test")
|
||||
PropertySubclass().log("sub")
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.baeldung.kotlin.logging
|
||||
|
||||
import org.slf4j.Logger
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
open class LoggerAsPropertyDelegate {
|
||||
private val lazyLogger by lazyLogger()
|
||||
protected val logger by LoggerDelegate()
|
||||
private val logger2 = logger
|
||||
|
||||
companion object {
|
||||
private val lazyLoggerComp by lazyLogger()
|
||||
private val loggerComp by LoggerDelegate()
|
||||
}
|
||||
|
||||
open fun log(s: String) {
|
||||
logger.info(s)
|
||||
logger2.info(s)
|
||||
lazyLogger.info(s)
|
||||
loggerComp.info(s)
|
||||
lazyLoggerComp.info(s)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DelegateSubclass : LoggerAsPropertyDelegate() {
|
||||
override fun log(s: String) {
|
||||
logger.info("-- in sub")
|
||||
super.log(s)
|
||||
}
|
||||
}
|
||||
|
||||
fun lazyLogger(forClass: Class<*>): Lazy<Logger> =
|
||||
lazy { getLogger(getClassForLogging(forClass)) }
|
||||
|
||||
fun <T : Any> T.lazyLogger(): Lazy<Logger> = lazyLogger(javaClass)
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
LoggerAsPropertyDelegate().log("test")
|
||||
DelegateSubclass().log("sub")
|
||||
}
|
||||
|
||||
class LoggerDelegate<in R : Any> : ReadOnlyProperty<R, Logger> {
|
||||
override fun getValue(thisRef: R, property: KProperty<*>) =
|
||||
getLogger(getClassForLogging(thisRef.javaClass))
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.kotlin.logging
|
||||
|
||||
open class LoggerInCompanionObject {
|
||||
companion object {
|
||||
private val loggerWithExplicitClass = getLogger(LoggerInCompanionObject::class.java)
|
||||
@Suppress("JAVA_CLASS_ON_COMPANION")
|
||||
private val loggerWithWrongClass = getLogger(javaClass)
|
||||
@Suppress("JAVA_CLASS_ON_COMPANION")
|
||||
private val logger = getLogger(javaClass.enclosingClass)
|
||||
}
|
||||
|
||||
fun log(s: String) {
|
||||
loggerWithExplicitClass.info(s)
|
||||
loggerWithWrongClass.info(s)
|
||||
logger.info(s)
|
||||
}
|
||||
|
||||
class Inner {
|
||||
companion object {
|
||||
private val loggerWithExplicitClass = getLogger(Inner::class.java)
|
||||
@Suppress("JAVA_CLASS_ON_COMPANION")
|
||||
@JvmStatic
|
||||
private val loggerWithWrongClass = getLogger(javaClass)
|
||||
@Suppress("JAVA_CLASS_ON_COMPANION")
|
||||
@JvmStatic
|
||||
private val logger = getLogger(javaClass.enclosingClass)
|
||||
}
|
||||
|
||||
fun log(s: String) {
|
||||
loggerWithExplicitClass.info(s)
|
||||
loggerWithWrongClass.info(s)
|
||||
logger.info(s)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CompanionSubclass : LoggerInCompanionObject()
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
LoggerInCompanionObject().log("test")
|
||||
LoggerInCompanionObject.Inner().log("test")
|
||||
CompanionSubclass().log("sub")
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.kotlin.logging
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import kotlin.reflect.full.companionObject
|
||||
|
||||
fun getLogger(forClass: Class<*>): Logger = LoggerFactory.getLogger(forClass)
|
||||
|
||||
fun <T : Any> getClassForLogging(javaClass: Class<T>): Class<*> {
|
||||
return javaClass.enclosingClass?.takeIf {
|
||||
it.kotlin.companionObject?.java == javaClass
|
||||
} ?: javaClass
|
||||
}
|
||||
13
core-kotlin/src/main/resources/logback.xml
Normal file
13
core-kotlin/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.baeldung.builder
|
||||
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
internal class BuilderPatternUnitTest {
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderSettingValues_thenFieldsNotNull() {
|
||||
|
||||
val foodOrder = FoodOrder.Builder()
|
||||
.bread("white bread")
|
||||
.meat("bacon")
|
||||
.fish("salmon")
|
||||
.condiments("olive oil")
|
||||
.build()
|
||||
|
||||
Assertions.assertNotNull(foodOrder.bread)
|
||||
Assertions.assertNotNull(foodOrder.meat)
|
||||
Assertions.assertNotNull(foodOrder.condiments)
|
||||
Assertions.assertNotNull(foodOrder.fish)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderSettingValues_thenFieldsContainsValues() {
|
||||
|
||||
val foodOrder = FoodOrder.Builder()
|
||||
.bread("white bread")
|
||||
.meat("bacon")
|
||||
.fish("salmon")
|
||||
.condiments("olive oil")
|
||||
.build()
|
||||
|
||||
Assertions.assertEquals("white bread", foodOrder.bread)
|
||||
Assertions.assertEquals("bacon", foodOrder.meat)
|
||||
Assertions.assertEquals("olive oil", foodOrder.condiments)
|
||||
Assertions.assertEquals("salmon", foodOrder.fish)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderWithoutSettingValues_thenFieldsNull() {
|
||||
|
||||
val foodOrder = FoodOrder.Builder()
|
||||
.build()
|
||||
|
||||
Assertions.assertNull(foodOrder.bread)
|
||||
Assertions.assertNull(foodOrder.meat)
|
||||
Assertions.assertNull(foodOrder.condiments)
|
||||
Assertions.assertNull(foodOrder.fish)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderNamedSettingValues_thenFieldsNotNull() {
|
||||
|
||||
val foodOrder = FoodOrderNamed(
|
||||
meat = "bacon",
|
||||
fish = "salmon",
|
||||
condiments = "olive oil",
|
||||
bread = "white bread"
|
||||
)
|
||||
|
||||
Assertions.assertNotNull(foodOrder.bread)
|
||||
Assertions.assertNotNull(foodOrder.meat)
|
||||
Assertions.assertNotNull(foodOrder.condiments)
|
||||
Assertions.assertNotNull(foodOrder.fish)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderNamedSettingValues_thenFieldsContainsValues() {
|
||||
|
||||
val foodOrder = FoodOrderNamed(
|
||||
meat = "bacon",
|
||||
fish = "salmon",
|
||||
condiments = "olive oil",
|
||||
bread = "white bread"
|
||||
)
|
||||
|
||||
Assertions.assertEquals("white bread", foodOrder.bread)
|
||||
Assertions.assertEquals("bacon", foodOrder.meat)
|
||||
Assertions.assertEquals("olive oil", foodOrder.condiments)
|
||||
Assertions.assertEquals("salmon", foodOrder.fish)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderNamedWithoutSettingValues_thenFieldsNull() {
|
||||
|
||||
val foodOrder = FoodOrderNamed()
|
||||
|
||||
Assertions.assertNull(foodOrder.bread)
|
||||
Assertions.assertNull(foodOrder.meat)
|
||||
Assertions.assertNull(foodOrder.condiments)
|
||||
Assertions.assertNull(foodOrder.fish)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderApplySettingValues_thenFieldsNotNull() {
|
||||
|
||||
val foodOrder = FoodOrderApply().apply {
|
||||
meat = "bacon"
|
||||
fish = "salmon"
|
||||
condiments = "olive oil"
|
||||
bread = "white bread"
|
||||
}
|
||||
|
||||
Assertions.assertNotNull(foodOrder.bread)
|
||||
Assertions.assertNotNull(foodOrder.meat)
|
||||
Assertions.assertNotNull(foodOrder.condiments)
|
||||
Assertions.assertNotNull(foodOrder.fish)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderApplySettingValues_thenFieldsContainsValues() {
|
||||
|
||||
val foodOrder = FoodOrderApply().apply {
|
||||
meat = "bacon"
|
||||
fish = "salmon"
|
||||
condiments = "olive oil"
|
||||
bread = "white bread"
|
||||
}
|
||||
|
||||
Assertions.assertEquals("white bread", foodOrder.bread)
|
||||
Assertions.assertEquals("bacon", foodOrder.meat)
|
||||
Assertions.assertEquals("olive oil", foodOrder.condiments)
|
||||
Assertions.assertEquals("salmon", foodOrder.fish)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenBuildingFoodOrderApplyWithoutSettingValues_thenFieldsNull() {
|
||||
|
||||
val foodOrder = FoodOrderApply()
|
||||
|
||||
Assertions.assertNull(foodOrder.bread)
|
||||
Assertions.assertNull(foodOrder.meat)
|
||||
Assertions.assertNull(foodOrder.condiments)
|
||||
Assertions.assertNull(foodOrder.fish)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class CompanionObjectTest {
|
||||
|
||||
@Test
|
||||
fun givenAClassWithCompanionObject_whenCallingMethodTheSameAsStaticOne_thenWeGetAResult() {
|
||||
assertEquals("A", A.returnClassName())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class A {
|
||||
companion object {
|
||||
fun returnClassName(): String {
|
||||
return "A"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ConstructorTests {
|
||||
|
||||
@Test
|
||||
fun givenAClassWithPrimaryConstructor_whenCreatingAnInstance_thenWeGetObject() {
|
||||
var example = Example(1, "Example")
|
||||
|
||||
assertEquals(1, example.id)
|
||||
assertEquals("Example", example.name)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Example constructor(val id: Int, var name: String)
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
|
||||
class DataClassTest {
|
||||
|
||||
@Test
|
||||
fun givenASampleDataClass_whenCallingToStringMethod_thenItReturnsAllProperties() {
|
||||
val student = Student(1, "John", "Smith")
|
||||
|
||||
assertEquals(1, student.id)
|
||||
assertEquals("John", student.name)
|
||||
assertEquals("Smith", student.lastName)
|
||||
assertEquals("Student(id=1, name=John, lastName=Smith)", student.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenASampleDataClass_whenCreatingACopyWithGeneratedFunction_thenItReturnsACopyWithRequestedChanges() {
|
||||
val student = Student(1, "John", "Smith")
|
||||
val student2 = student.copy(id = 2, name = "Anne")
|
||||
|
||||
assertEquals(2, student2.id)
|
||||
assertEquals("Anne", student2.name)
|
||||
assertEquals("Smith", student2.lastName)
|
||||
assertEquals("Student(id=2, name=Anne, lastName=Smith)", student2.toString())
|
||||
assertFalse(student.equals(student2))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class Student(val id: Int, val name: String, val lastName: String)
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class DelegationTest {
|
||||
|
||||
@Test
|
||||
fun givenAClassWithDelegation_whenCallDelegatedMethod_thenWeGetAResultDefinedInPassedObject() {
|
||||
val car = Car(V6Engine())
|
||||
|
||||
assertEquals("Vroom", car.makeSound())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface Engine {
|
||||
fun makeSound(): String
|
||||
}
|
||||
|
||||
class V6Engine: Engine {
|
||||
override fun makeSound(): String {
|
||||
return "Vroom"
|
||||
}
|
||||
}
|
||||
|
||||
class Car(e: Engine) : Engine by e
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import java.io.IOException
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ExceptionsTest {
|
||||
|
||||
@Test
|
||||
fun givenATryExpression_whenReturning5InLastExpressionOfTryBlock_thenWeGet5() {
|
||||
val value: Int = try { 5 } catch (e: IOException) { 6 }
|
||||
|
||||
assertEquals(5, value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenATryExpression_whenReturning6InLastExpressionOfCatchBlock_thenWeGet6() {
|
||||
val value: Int = try { funThrowingException() } catch (e: IOException) { 6 }
|
||||
|
||||
assertEquals(6, value)
|
||||
}
|
||||
|
||||
@org.junit.Test(expected = IllegalArgumentException::class)
|
||||
fun givenANullString_whenUsingElvisOperator_thenExceptionIsThrown() {
|
||||
val sampleString: String? = null
|
||||
|
||||
val length: Int = sampleString?.length ?: throw IllegalArgumentException("String must not be null")
|
||||
}
|
||||
|
||||
private fun funThrowingException(): Nothing {
|
||||
throw IOException()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ExtensionFunctionsTest {
|
||||
|
||||
@Test
|
||||
fun givenAStringWithAnExtensionFunction_whenCallingThatFunction_thenItConcatenatesStrings() {
|
||||
val sampleString = "ABC"
|
||||
val concatenatedString = sampleString.appendString("DEF")
|
||||
|
||||
assertEquals("ABCDEF", concatenatedString)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAStringWithAnExtensionProperty_whenReadingProperty_thenItReturnsLengthOfString() {
|
||||
val sampleString = "ABC"
|
||||
|
||||
assertEquals(3, sampleString.size)
|
||||
}
|
||||
|
||||
fun String.appendString(str : String): String {
|
||||
return plus(str)
|
||||
}
|
||||
|
||||
val String.size: Int
|
||||
get() = length
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class FunctionsTest {
|
||||
|
||||
@Test
|
||||
fun givenALambdaExpressionConcatenatingString_whenUsingTheFunctionWithAAndBString_thenWeGetAB() {
|
||||
val concat: (String, String) -> String = { a, b -> a + b }
|
||||
|
||||
assertEquals("AB", concat("A","B"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAnAnonymousFunctionConcatenatingString_whenUsingTheFunctionWithAAndBString_thenWeGetAB() {
|
||||
val concat: (String, String) -> String = fun(a: String, b: String): String { return a + b }
|
||||
|
||||
assertEquals("AB", concat("A","B"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAnPlusMethodOfString_whenUsingTheFunctionWithAAndBString_thenWeGetAB() {
|
||||
val concat = String::plus
|
||||
|
||||
assertEquals("AB", concat("A","B"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAStringConstractorAssignedToFunction_whenUsingFunctionReference_thenWeGetNewString() {
|
||||
val concat = ::String
|
||||
|
||||
assertEquals("A", concat().plus("A"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAClassImplementingAFunctionType_whenUsingTheFunctionWithAAndBString_thenWeGetAB() {
|
||||
val concat = StringConcatenation()
|
||||
|
||||
assertEquals("AB", concat("A", "B"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenALambdaExpressionWithReceiver_whenUsingTheFunctionWithReceiver_thenWeGetABC() {
|
||||
val concat: String.(String, String) -> String = { a, b -> plus(a).plus(b) }
|
||||
|
||||
assertEquals("ABC", "A".concat("B", "C"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenALambdaExpressionWithinLambdaExpression_whenUsingTheFunction_thenWeGetAB() {
|
||||
val concat: (String) -> ((String) -> String) = { a -> {b -> a + b} }
|
||||
|
||||
assertEquals("AB", (concat("A")("B")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun given3NestedLambdaExpression_whenUsingTheFunction_thenWeGetABC() {
|
||||
val concat: (String) -> (String) -> (String) -> String = { a -> {b -> { c -> a + b + c} } }
|
||||
|
||||
assertEquals("ABC", concat("A")("B")("C"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StringConcatenation: (String, String) -> String {
|
||||
override fun invoke(p1: String, p2: String): String {
|
||||
return p1 + p2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class IsOperatorTest {
|
||||
|
||||
@Test
|
||||
fun givenSampleValue_whenUsingIsOperatorInIfStatement_thenItCastsAutomaticallyToString() {
|
||||
val value: Any = "string"
|
||||
|
||||
if(value is String) {
|
||||
assertEquals(6, value.length)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenSampleValue_whenUsingIsOperatorWithAndOperator_thenItCastsAutomaticallyToString() {
|
||||
val value: Any = "string"
|
||||
|
||||
assertTrue(value is String && value.length == 6)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenSampleValue_whenUsingWithWhenOperator_thenItCastsAutomaticallyToString() {
|
||||
val value: Any = "string"
|
||||
|
||||
when(value) {
|
||||
is String -> assertEquals(6, value.length)
|
||||
is Int -> assertEquals(6, value.absoluteValue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import kotlin.test.Test
|
||||
import java.lang.NullPointerException
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
class NullSafetyTest {
|
||||
|
||||
@Test
|
||||
fun givenStringAndNull_whenUsingSafeCallOperatorWithLengthMethod_thenReturnsLengthForStringAndNullForNull() {
|
||||
val stringValue: String? = "string"
|
||||
val nullValue: String? = null
|
||||
|
||||
assertNotNull(stringValue?.length)
|
||||
assertNull(nullValue?.length)
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException::class)
|
||||
fun givenNullReference_whenUsingTheNotNullAssertionOperator_thenItThrowsNullPointerException() {
|
||||
val stringValue: String? = "string"
|
||||
val nullValue: String? = null
|
||||
|
||||
assertNotNull(stringValue!!.length)
|
||||
nullValue!!.length
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenStringAndNull_whenUsingElvisOperator_thenItTestsAgainstNullAndReturnsTheProperValue() {
|
||||
val stringValue: String? = "string"
|
||||
val nullValue: String? = null
|
||||
|
||||
val shouldBeLength: Int = stringValue?.length ?: -1
|
||||
val souldBeMinusOne: Int = nullValue?.length ?: -1
|
||||
|
||||
assertEquals(6, shouldBeLength)
|
||||
assertEquals(-1, souldBeMinusOne)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenString_whenCastingToInt_thenItReturnsNull() {
|
||||
val stringValue: String? = "string"
|
||||
|
||||
val intValue: Int? = stringValue as? Int
|
||||
|
||||
assertNull(intValue)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenCollectionWithNulls_whenFilterNonNull_thenItReturnsCollectionWithoutNulls() {
|
||||
val list: List<String?> = listOf("a", "b", null)
|
||||
val nonNullList = list.filterNotNull()
|
||||
|
||||
assertEquals(2, nonNullList.size)
|
||||
assertEquals(nonNullList, listOf("a", "b"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenCollectionWithNulls_whenLetWithSafeCallOperator_thenItOmitsNulls() {
|
||||
val list: List<String?> = listOf("a", "b", null)
|
||||
for(elem in list) {
|
||||
elem?.let { assertNotNull(it) }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class OperatorsOverloadingTest {
|
||||
|
||||
@Test
|
||||
fun givenThePlaneClassWithOverloadedIncrementationOperator_whenCallingTheOperator_thenItIncreasesSpeed(){
|
||||
var plane = Plane(0.0)
|
||||
|
||||
plane++
|
||||
assertEquals(50.0, plane.currentSpeed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenThePlaneClassWithOverloadedMinusOperator_whenCallingTheOperator_thenItDecreaseSpeed(){
|
||||
var plane = Plane(1000.0)
|
||||
|
||||
plane - 500.0
|
||||
assertEquals(500.0, plane.currentSpeed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenThePlaneClassWithOverloadedInvokeOperator_whenCallingTheOperator_thenItSetSpeed(){
|
||||
var plane = Plane(0.0)
|
||||
|
||||
plane(150.0)
|
||||
assertEquals(150.0, plane.currentSpeed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun given2PlaneObjectWithOverloadedComparisonOperator_whenCallingTheOperator_thenItComparesSpeedValues(){
|
||||
var plane = Plane(0.0)
|
||||
var plane2 = Plane(150.0)
|
||||
|
||||
assertTrue(plane < (plane2))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Plane(var currentSpeed: Double) {
|
||||
|
||||
operator fun inc(): Plane {
|
||||
currentSpeed += 50.0
|
||||
return this
|
||||
}
|
||||
|
||||
operator fun minus(number: Double) {
|
||||
currentSpeed = if(currentSpeed < number) 0.0 else currentSpeed - number
|
||||
}
|
||||
|
||||
operator fun invoke(speed: Double) {
|
||||
currentSpeed = speed
|
||||
}
|
||||
|
||||
operator fun compareTo(plane: Plane): Int {
|
||||
return currentSpeed.compareTo(plane.currentSpeed)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.kotlinvsjava
|
||||
|
||||
import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class PropertiesTest {
|
||||
|
||||
@Test
|
||||
fun givenASampleClassWithValAndVarProperties_whenSettingPrice_thenWeGetZeroOrOne() {
|
||||
val product = Product()
|
||||
product.price = BigDecimal(10)
|
||||
|
||||
val product2 = Product()
|
||||
product2.price = null
|
||||
|
||||
assertEquals("empty", product.id)
|
||||
assertEquals("empty", product2.id)
|
||||
assertEquals(BigDecimal(10), product.price)
|
||||
assertEquals(BigDecimal(1), product2.price)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Product {
|
||||
|
||||
val id: String? = "empty"
|
||||
|
||||
var price: BigDecimal? = BigDecimal.ZERO
|
||||
set(value) = if(value == null) { field = BigDecimal.ONE} else { field = value }
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user