Kotlin Language Features Related to Null Handling

Any software engineer with a Java background would find the null handling features in the Kotlin language interesting. Let's summarize this topic with some examples. Nullable types: In Kotlin, types are non-nullable by default. If you want a variable to be able to hold a null value, you need to explicitly declare its type as nullable using the Type? syntax. For example, String? denotes a nullable string, while String represents a non-nullable string. Safe calls (?.): Kotlin introduces the safe call operator (?.) for handling nullable types. It allows you to safely invoke a method or access a property on a nullable object. If the object is null, the expression returns null instead of throwing a NullPointerException. Example: data class Person(val name: String, val age: Int, val address: String?) fun main() {     // Create a person with a nullable address     val person1 = Person("John Doe", 25, "123 Main Street")     val person2 = Person("Jane Doe", 30,...

Remembering Java 8 Features


FUNCTIONAL INTERFACES

There are many ways to use a functional interface:

Example 1:

public class Main {

    public void myMethod() {

        for (; ; )
            System.out.println("my Method");
    }

    public static void main(String[] args) {
        
        // Anonymous method syntax
        new Thread(new Runnable() {
            @Override

            public void run() {
                System.out.println("Anonymous method");
            }
        }
        ).start();

        // method reference        
        Main main = new Main();
        new Thread(

                main::myMethod

        ).start();
        
        // lambda expression
        new Thread(

                () -> System.out.println("lambda expression")

        ).start();
    }
}
    
Example 2:

Here we can see two types of lambda expressions: single line and block lambda. For the block lambda, we have to write parameter types and also a return keyword is mandatory. There is nothing difficult regarding these language features, it's all about knowing the syntax. 

public class Main {

    public static void main(String[] args) {

        File directory = new File("./src/main/java");
        // Anonymous inner class

        String[] names = directory.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".java");
            }
        });

        // lambda expression (single line)    
        String[] names2 = directory.list((dir, name) -> name.endsWith(".java"));

        // lambda expression (multiple statements possible)    
        String[] names3 = directory.list((File dir, String name) -> {
            return name.endsWith(".java");
        });

        // inner class
        String[] names4 = directory.list(new MyFilter());

    }

    public static class MyFilter implements FilenameFilter {

        @Override
        public boolean accept(File dir, String name) {
            return false;
        }
    }

}

Example 3:

// Lambda expression
Stream.of(3, 1, 4, 1, 5, 9).forEach(x -> System.out.println(x));

// Method reference
Stream.of(3, 1, 4, 1, 5, 9).forEach(System.out::println);

// Use a variable
Consumer printer = System.out::println;
Stream.of(3, 1, 4, 1, 5, 9).forEach(printer);


@FunctionalInterface annotation

It is not mandatory but we can use FunctionalInterface annotation for our interface that has 1 abstract method. The benefit is that we will have compile time error if the interface has zero or multiple methods. A functional interface can have static methods or default methods.

Example 4:

@FunctionalInterface
public interface MyInterface {
    int myMethod();

default String sayHello() {
        return "Hello, World!";    }
    
static void myStaticMethod() {
        System.out.println("I'm a static method in an interface");    }
}

What are "Default Methods" in Java 8?

Before Java 8, an interface could not have a method with an implementation. Implementers had to implement all methods of an interface, so adding a new method to the interface was always affecting the implementers. In Java 8, an interface can have many default methods with bodies and they dont have to be implemented.

java.util.function package

Some functional interfaces are defined in this package.

Consumers: They take an argument and return nothing.
Suppliers: They dont take any arguments and they return a value.
Predicates: They take an argument and return a boolean value.
Functions: They take arguments and return a value.

Example 5: foreach method takes a Consumer as an argument:

public class Main {

    public static void main(String[] args) {

        List strings = Arrays.asList("this", "is", "a", "list", "of", "strings");

        // anonymous "Consumer"
        strings.forEach(new Consumer() {
            @Override
            public void accept(String s) {
                System.out.println(s);            }
        });

        // lambda
        strings.forEach(x -> System.out.println(x));

        // method reference
        strings.forEach(System.out::println);
    }
}


Some examples are taken from this excellent book:

Modern Java Recipes - Ken Kousen
http://a.co/d/4witmpA

Comments

Popular posts from this blog

Trie Data Structure and Finding Patterns in a Collection of Words

Virtual Memory

NOTES ON COMPUTER ARCHITECTURE: Some important concepts in computer architecture