[BAEL-19883] - Move articles out of core-kotlin part2

This commit is contained in:
catalin-burcea
2019-12-16 16:26:38 +02:00
parent 2e1d1ffb01
commit b34da5aea9
58 changed files with 85 additions and 41 deletions

View File

@@ -0,0 +1,13 @@
## Core Kotlin Lang
This module contains articles about core features in the Kotlin language.
### Relevant articles:
- [Kotlin return, break, continue Keywords](https://www.baeldung.com/kotlin-return-break-continue)
- [Infix Functions in Kotlin](https://www.baeldung.com/kotlin-infix-functions)
- [Lambda Expressions in Kotlin](https://www.baeldung.com/kotlin-lambda-expressions)
- [Creating Java static final Equivalents in Kotlin](https://www.baeldung.com/kotlin-java-static-final)
- [Initializing Arrays in Kotlin](https://www.baeldung.com/kotlin-initialize-array)
- [Lazy Initialization in Kotlin](https://www.baeldung.com/kotlin-lazy-initialization)
- [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin-null-safety)
- [[<-- Prev]](/core-kotlin-modules/core-kotlin-lang)

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-kotlin-lang-2</artifactId>
<name>core-kotlin-lang-2</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-kotlin-modules</groupId>
<artifactId>core-kotlin-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
</project>

View File

@@ -0,0 +1,14 @@
package com.baeldung.lazy;
public class ClassWithHeavyInitialization {
private ClassWithHeavyInitialization() {
}
private static class LazyHolder {
public static final ClassWithHeavyInitialization INSTANCE = new ClassWithHeavyInitialization();
}
public static ClassWithHeavyInitialization getInstance() {
return LazyHolder.INSTANCE;
}
}

View File

@@ -0,0 +1,84 @@
package com.baeldung.lambda
fun inferredType(input: Int): Int {
val square = { number: Int -> number * number }
return square(input)
}
fun intToBiggerString(argument: Int): String {
val magnitude100String = { input: Int ->
val magnitude = input * 100
magnitude.toString()
}
return magnitude100String(argument)
}
fun manyLambda(nums: Array<Int>): List<String> {
val newList = nums.map { intToBiggerString(it) }
return newList
}
fun empty() {
val noReturn: (Int) -> Unit = { num -> println(num) }
noReturn(5)
}
fun invokeLambda(lambda: (Double) -> Boolean): Boolean {
return lambda(4.329)
}
fun extendString(arg: String, num: Int): String {
val another: String.(Int) -> String = { this + it }
return arg.another(num)
}
fun getCalculationLambda(): (Int) -> Any {
val calculateGrade = { grade: Int ->
when (grade) {
in 0..40 -> "Fail"
in 41..70 -> "Pass"
in 71..100 -> "Distinction"
else -> false
}
}
return calculateGrade
}
fun getCalculationLambdaWithReturn(): (Int) -> String {
val calculateGrade: Int.() -> String = lambda@{
if (this < 0 || this > 100) {
return@lambda "Error"
} else if (this < 40) {
return@lambda "Fail"
} else if (this < 70) {
return@lambda "Pass"
}
"Distinction"
}
return calculateGrade
}
fun getCalculationAnonymousFunction(): (Int) -> String {
val calculateGrade = fun(grade: Int): String {
if (grade < 0 || grade > 100) {
return "Error"
} else if (grade < 40) {
return "Fail"
} else if (grade < 70) {
return "Pass"
}
return "Distinction"
}
return calculateGrade
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.lazy;
import org.junit.Test;
import static junit.framework.TestCase.assertTrue;
public class LazyJavaUnitTest {
@Test
public void giveHeavyClass_whenInitLazy_thenShouldReturnInstanceOnFirstCall() {
//when
ClassWithHeavyInitialization classWithHeavyInitialization = ClassWithHeavyInitialization.getInstance();
ClassWithHeavyInitialization classWithHeavyInitialization2 = ClassWithHeavyInitialization.getInstance();
//then
assertTrue(classWithHeavyInitialization == classWithHeavyInitialization2);
}
}

View File

@@ -0,0 +1,49 @@
package com.baeldung.arrayinitialization
import org.junit.Test
import kotlin.test.assertEquals
class ArrayInitializationTest {
@Test
fun givenArrayOfStrings_thenValuesPopulated() {
val strings = arrayOf("January", "February", "March")
assertEquals(3, strings.size)
assertEquals("March", strings[2])
}
@Test
fun givenArrayOfIntegers_thenValuesPopulated() {
val integers = intArrayOf(1, 2, 3, 4)
assertEquals(4, integers.size)
assertEquals(1, integers[0])
}
@Test
fun givenArrayOfNulls_whenPopulated_thenValuesPresent() {
val array = arrayOfNulls<Number>(5)
for (i in array.indices) {
array[i] = i * i
}
assertEquals(16, array[4])
}
@Test
fun whenGeneratorUsed_thenValuesPresent() {
val generatedArray = IntArray(10) { i -> i * i }
assertEquals(81, generatedArray[9])
}
@Test
fun whenStringGenerated_thenValuesPresent() {
val generatedStringArray = Array(10) { i -> "Number of index: $i" }
assertEquals("Number of index: 0", generatedStringArray[0])
}
}

View File

@@ -0,0 +1,17 @@
package com.baeldung.constant
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class ConstantUnitTest {
@Test
fun givenConstant_whenCompareWithActualValue_thenReturnTrue() {
assertEquals(10, TestKotlinConstantObject.COMPILE_TIME_CONST)
assertEquals(30, TestKotlinConstantObject.RUN_TIME_CONST)
assertEquals(20, TestKotlinConstantObject.JAVA_STATIC_FINAL_FIELD)
assertEquals(40, TestKotlinConstantClass.COMPANION_OBJECT_NUMBER)
}
}

View File

@@ -0,0 +1,8 @@
package com.baeldung.constant
class TestKotlinConstantClass {
companion object {
const val COMPANION_OBJECT_NUMBER = 40
}
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.constant
object TestKotlinConstantObject {
const val COMPILE_TIME_CONST = 10
val RUN_TIME_CONST: Int
@JvmField
val JAVA_STATIC_FINAL_FIELD = 20
init {
RUN_TIME_CONST = TestKotlinConstantObject.COMPILE_TIME_CONST + 20;
}
}

View File

@@ -0,0 +1,51 @@
package com.baeldung.infixfunctions
import org.junit.Assert
import org.junit.Test
class InfixFunctionsTest {
@Test
fun testColours() {
val color = 0x123456
val red = (color and 0xff0000) shr 16
val green = (color and 0x00ff00) shr 8
val blue = (color and 0x0000ff) shr 0
Assert.assertEquals(0x12, red)
Assert.assertEquals(0x34, green)
Assert.assertEquals(0x56, blue)
}
@Test
fun testNewAssertions() {
class Assertion<T>(private val target: T) {
infix fun isEqualTo(other: T) {
Assert.assertEquals(other, target)
}
infix fun isDifferentFrom(other: T) {
Assert.assertNotEquals(other, target)
}
}
val result = Assertion(5)
result isEqualTo 5
// The following two lines are expected to fail
// result isEqualTo 6
// result isDifferentFrom 5
}
@Test
fun testNewStringMethod() {
infix fun String.substringMatches(r: Regex) : List<String> {
return r.findAll(this)
.map { it.value }
.toList()
}
val matches = "a bc def" substringMatches ".*? ".toRegex()
Assert.assertEquals(listOf("a ", "bc "), matches)
}
}

View File

@@ -0,0 +1,36 @@
package com.baeldung.lambda;
import kotlin.jvm.functions.Function1;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Created by Paul Jervis on 24/04/2018.
*/
class LambdaKotlinUnitTest {
@Test
void givenJava6_whenUsingAnonnymousClass_thenReturnLambdaResult() {
assertTrue(LambdaKt.invokeLambda(new Function1<Double, Boolean>() {
@Override
public Boolean invoke(Double c) {
return c >= 0;
}
}));
}
@Test
void givenJava8_whenUsingLambda_thenReturnLambdaResult() {
assertTrue(LambdaKt.invokeLambda(c -> c >= 0));
}
@Test
void givenJava8_whenCallingMethodWithStringExtension_thenImplementExtension() {
String actual = LambdaKt.extendString("Word", 90);
String expected = "Word90";
assertEquals(expected, actual);
}
}

View File

@@ -0,0 +1,96 @@
package com.baeldung.lambda
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class LambdaTest {
@Test
fun whenCallingALambda_thenPerformTheAction() {
assertEquals(9, inferredType(3))
}
@Test
fun whenCallingAMoreComplicatedLambda_thenPerformTheAction() {
assertEquals("500", intToBiggerString(5))
}
@Test
fun whenPassingALambdaObject_thenCallTriggerLambda() {
val lambda = { arg: Double ->
arg == 4.329
}
val result = invokeLambda(lambda)
assertTrue(result)
}
@Test
fun whenPassingALambdaLiteral_thenCallTriggerLambda() {
val result = invokeLambda({
true
})
assertTrue(result)
}
@Test
fun whenPassingALambdaLiteralOutsideBrackets_thenCallTriggerLambda() {
val result = invokeLambda { arg -> arg.isNaN() }
assertFalse(result)
}
@Test
fun whenPassingAnAnonymousFunction_thenCallTriggerLambda() {
val result = invokeLambda(fun(arg: Double): Boolean {
return arg >= 0
})
assertTrue(result)
}
@Test
fun whenUsingLambda_thenCalculateGrade() {
val gradeCalculation = getCalculationLambda()
assertEquals(false, gradeCalculation(-40))
assertEquals("Pass", gradeCalculation(50))
}
@Test
fun whenUsingReturnStatementLambda_thenCalculateGrade() {
val gradeCalculation: Int.() -> String = getCalculationLambdaWithReturn()
assertEquals("Distinction", 80.gradeCalculation())
assertEquals("Error", 244_234_324.gradeCalculation())
}
@Test
fun whenUsingAnonymousFunction_thenCalculateGrade() {
val gradeCalculation = getCalculationAnonymousFunction()
assertEquals("Error", gradeCalculation(244_234_324))
assertEquals("Pass", gradeCalculation(50))
}
@Test
fun whenPassingAFunctionReference_thenCallTriggerLambda() {
val reference = Double::isFinite
val result = invokeLambda(reference)
assertTrue(result)
}
@Test
fun givenArray_whenMappingArray_thenPerformCalculationOnAllElements() {
val expected = listOf("100", "200", "300", "400", "500")
val actual = manyLambda(arrayOf(1, 2, 3, 4, 5))
assertEquals(expected, actual)
}
}

View File

@@ -0,0 +1,68 @@
package com.baeldung.lazy
import org.junit.Test
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.test.assertEquals
class LazyUnitTest {
@Test
fun givenLazyValue_whenGetIt_thenShouldInitializeItOnlyOnce() {
//given
val numberOfInitializations: AtomicInteger = AtomicInteger()
val lazyValue: ClassWithHeavyInitialization by lazy {
numberOfInitializations.incrementAndGet()
ClassWithHeavyInitialization()
}
//when
println(lazyValue)
println(lazyValue)
//then
assertEquals(numberOfInitializations.get(), 1)
}
@Test
fun givenLazyValue_whenGetItUsingPublication_thenCouldInitializeItMoreThanOnce() {
//given
val numberOfInitializations: AtomicInteger = AtomicInteger()
val lazyValue: ClassWithHeavyInitialization by lazy(LazyThreadSafetyMode.PUBLICATION) {
numberOfInitializations.incrementAndGet()
ClassWithHeavyInitialization()
}
val executorService = Executors.newFixedThreadPool(2)
val countDownLatch = CountDownLatch(1)
//when
executorService.submit { countDownLatch.await(); println(lazyValue) }
executorService.submit { countDownLatch.await(); println(lazyValue) }
countDownLatch.countDown()
//then
executorService.shutdown()
executorService.awaitTermination(5, TimeUnit.SECONDS)
//assertEquals(numberOfInitializations.get(), 2)
}
class ClassWithHeavyInitialization {
}
lateinit var a: String
@Test
fun givenLateInitProperty_whenAccessItAfterInit_thenPass() {
//when
a = "it"
println(a)
//then not throw
}
@Test(expected = UninitializedPropertyAccessException::class)
fun givenLateInitProperty_whenAccessItWithoutInit_thenThrow() {
//when
println(a)
}
}

View File

@@ -0,0 +1,161 @@
package com.baeldung.nullsafety
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNull
import kotlin.test.assertTrue
class NullSafetyTest {
@Test
fun givenNonNullableField_whenAssignValueToIt_thenNotNeedToCheckAgainstNull() {
//given
var a: String = "value"
//a = null compilation error
//then
assertEquals(a.length, 5)
}
@Test
fun givenNullableField_whenReadValue_thenNeedToCheckAgainstNull() {
//given
var b: String? = "value"
b = null
//when
if (b != null) {
} else {
assertNull(b)
}
}
@Test
fun givenComplexObject_whenUseSafeCall_thenShouldChainCallsResultingWithValue() {
//given
val p: Person? = Person(Country("ENG"))
//when
val res = p?.country?.code
//then
assertEquals(res, "ENG")
}
@Test
fun givenComplexObject_whenUseSafeCall_thenShouldChainCallsResultingWithNull() {
//given
val p: Person? = Person(Country(null))
//when
val res = p?.country?.code
//then
assertNull(res)
}
@Test
fun givenCollectionOfObjects_whenUseLetOperator_thenShouldApplyActionOnlyOnNonNullValue() {
//given
val firstName = "Tom"
val secondName = "Michael"
val names: List<String?> = listOf(firstName, null, secondName)
//when
var res = listOf<String?>()
for (item in names) {
item?.let { res = res.plus(it); it }
?.also{it -> println("non nullable value: $it")}
}
//then
assertEquals(2, res.size)
assertTrue { res.contains(firstName) }
assertTrue { res.contains(secondName) }
}
@Test
fun fivenCollectionOfObject_whenUseRunOperator_thenExecuteActionOnNonNullValue(){
//given
val firstName = "Tom"
val secondName = "Michael"
val names: List<String?> = listOf(firstName, null, secondName)
//when
var res = listOf<String?>()
for (item in names) {
item?.run{res = res.plus(this)}
}
//then
assertEquals(2, res.size)
assertTrue { res.contains(firstName) }
assertTrue { res.contains(secondName) }
}
@Test
fun givenNullableReference_whenUseElvisOperator_thenShouldReturnValueIfReferenceIsNotNull() {
//given
val value: String? = "name"
//when
val res = value?.length ?: -1
//then
assertEquals(res, 4)
}
@Test
fun givenNullableReference_whenUseElvisOperator_thenShouldReturnDefaultValueIfReferenceIsNull() {
//given
val value: String? = null
//when
val res = value?.length ?: -1
//then
assertEquals(res, -1)
}
@Test
fun givenNullableField_whenUsingDoubleExclamationMarkOperatorOnNull_thenThrowNPE() {
//given
var b: String? = "value"
b = null
//when
assertFailsWith<NullPointerException> {
b!!.length
}
}
@Test
fun givenNullableField_whenUsingDoubleExclamationMarkOperatorOnNotNull_thenReturnValue() {
//given
val b: String? = "value"
//then
assertEquals(b!!.length, 5)
}
@Test
fun givenNullableList_whenUseFilterNotNullMethod_thenRemoveALlNullValues() {
//given
val list: List<String?> = listOf("a", null, "b")
//when
val res = list.filterNotNull()
//then
assertEquals(res.size, 2)
assertTrue { res.contains("a") }
assertTrue { res.contains("b") }
}
}
data class Person(val country: Country?)
data class Country(val code: String?)

View File

@@ -0,0 +1,121 @@
package com.baeldung.structuraljump
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
class StructuralJumpUnitTest {
@Test
fun givenLoop_whenBreak_thenComplete() {
var value = ""
for (i in "hello_world") {
if (i == '_')
break
value += i.toString()
}
assertEquals("hello", value)
}
@Test
fun givenLoop_whenBreakWithLabel_thenComplete() {
var value = ""
outer_loop@ for (i in 'a'..'d') {
for (j in 1..3) {
value += "" + i + j
if (i == 'b' && j == 1)
break@outer_loop
}
}
assertEquals("a1a2a3b1", value)
}
@Test
fun givenLoop_whenContinue_thenComplete() {
var result = ""
for (i in "hello_world") {
if (i == '_')
continue
result += i
}
assertEquals("helloworld", result)
}
@Test
fun givenLoop_whenContinueWithLabel_thenComplete() {
var result = ""
outer_loop@ for (i in 'a'..'c') {
for (j in 1..3) {
if (i == 'b')
continue@outer_loop
result += "" + i + j
}
}
assertEquals("a1a2a3c1c2c3", result)
}
@Test
fun givenLambda_whenReturn_thenComplete() {
var result = returnInLambda();
assertEquals("hello", result)
}
private fun returnInLambda(): String {
var result = ""
"hello_world".forEach {
// non-local return directly to the caller
if (it == '_') return result
result += it.toString()
}
//this line won't be reached
return result;
}
@Test
fun givenLambda_whenReturnWithExplicitLabel_thenComplete() {
var result = ""
"hello_world".forEach lit@{
if (it == '_') {
// local return to the caller of the lambda, i.e. the forEach loop
return@lit
}
result += it.toString()
}
assertEquals("helloworld", result)
}
@Test
fun givenLambda_whenReturnWithImplicitLabel_thenComplete() {
var result = ""
"hello_world".forEach {
if (it == '_') {
// local return to the caller of the lambda, i.e. the forEach loop
return@forEach
}
result += it.toString()
}
assertEquals("helloworld", result)
}
@Test
fun givenAnonymousFunction_return_thenComplete() {
var result = ""
"hello_world".forEach(fun(element) {
// local return to the caller of the anonymous fun, i.e. the forEach loop
if (element == '_') return
result += element.toString()
})
assertEquals("helloworld", result)
}
@Test
fun givenAnonymousFunction_returnToLabel_thenComplete() {
var result = ""
run loop@{
"hello_world".forEach {
// non-local return from the lambda passed to run
if (it == '_') return@loop
result += it.toString()
}
}
assertEquals("hello", result)
}
}