What Java programmers find useful in Kotlin

Kotlin will be the official language for Android was announced at Goole I / O 2017. This post is intended for Java programmers and describes some useful Kotlin features not found in Java.

This post is written so that it can be understood independently, but it is the third in the series below. It is assumed that you understand the basic syntax of Kotlin, so if you do not know the syntax of Kotlin itself, please see the previous post first.

  1. Almost the same as Java
  2. Places that require a new way of thinking and tend to trip
  3. ** Convenient things unique to Kotlin ← Contents covered in this post **

Convenient things unique to Kotlin

Learn about some useful Kotlin features that Java doesn't have.

It says "only Kotlin", but it's just a comparison with Java. This post is for Java programmers. Many say it's in other languages (though not in Java).

I've mentioned a lot, but my favorite is Data Class and the last one I mentioned ʻapply`. It's really convenient.

String Template

This is often called string interpolation in other languages.

// Kotlin
val a = 2
val b = 3
println("$a + $b = ${a + b}") // 2 + 3 = 5

You can embed the value of the variable foo in a string in the form $ foo. You can also write any expression in the ... part by writing like $ {...}. You don't have to combine strings with + as you do in Java.

Multi-line string literal

Kotlin allows multi-line string literals. This is useful for creating string literals with line breaks and "" like ↓. You can also use String Templates like $ title in multi-line string literals.

// Kotlin
val title = "Hello, World!"
val headerId = "header"
val header = "Hello, World!"

val html = """<!DOCTYPE html>
<html>
  <title>$title</title>
  <body>
    <h1 id="$headerId">$header</h1>
  </body>
</html>
"""

println(html)

↓ is the output result.

<!DOCTYPE html>
<html>
  <title>Hello, World!</title>
  <body>
    <h1 id="header">Hello, World!</h1>
  </body>
</html>

function

Kotlin allows you to create class-independent ** _ Function _ **, unlike Java. Those who are new to Java may not be familiar with the term function, but it's like an independent method that doesn't belong to a class or instance. Its role is similar to Java's static method.

For example, Kotlin's listOf is a function. Since it doesn't belong to a class, it doesn't need a part of ʻArrays. unlike the static method ʻArrays.asList.

// Java
List<Integer> list = Arrays.asList(2, 3, 5);
// Kotlin
val list = listOf(2, 3, 5)

Frequently used functions such as listOf and mapOf are useful to be called without a class name like this (even in Java, ʻimport static can do it, but ʻimport unless it is used repeatedly. It's a hassle to do).

Unlike the static method, functions do not have namespaces separated by class name, so if you make anything into a function, name conflicts will occur. However, it is convenient not to abuse it by creating a private function only in a file or a ʻinternal` function limited in a certain module.

Single-Expression function

A function that can be implemented with a single expression (not only a function but also a method) can be described concisely as ↓.

// Kotlin
//Normal writing
fun square(number: Int): Int {
  return number * number
}
// Kotlin
//Concise writing
fun square(number: Int): Int = number * number

The code can be compressed and it is much cleaner.

Function type and assignment

You can also assign a function to a variable.

// Kotlin
val square: (Int) -> Int = { it * it }
square(3) // 9

Notice that the type of square is (Int)-> Int. This means a function that takes one ʻInt as an argument and returns ʻInt. If you write (Foo, Bar)-> Baz, it will be the type of function that receives Foo as the first argument and Bar as the second argument and returns Baz.

Being put in a variable can also be passed as an argument.

val list = listOf(2, 3, 5)
list.map(square) // [4, 9, 25]

Default argument

Kotlin allows you to give default arguments instead of overloading functions and methods.

// Java
static double log(double x, double base) {
  ...
}

static double log(double x) {
  return log(Math.E);
}
// Kotlin
fun log(x: Double, base: Double = Math.E): Double {
  ...
}

You can also give multiple default arguments and specify only one of them.

// Kotlin
fun foo(x: Int = 42, y: Boolean = true, z: String = "xyz") {
  ...
}

foo(y = false) // x = 42, z = "xyz"

Operator overload

In fact, Kotlin operators are methods. For example, + is a method called plus, and writing 1 + 2 is equivalent to writing 1.plus (2). To implement a method that acts as an operator, add the ʻoperator` qualifier.

// Kotlin
class Vector2(val x: Double, val y: Double) {
  operator fun plus(vector: Vector2): Vector2 {
    return Vector2(x + vector.x, y + vector.y)
  }
}

Vector2(2.0, 3.0) + Vector2(4.0, 5.0) // Vector2(6.0, 8.0)

The correspondence between operators and methods of four arithmetic operations is as follows.

operator Method
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)

See the official documentation (https://kotlinlang.org/docs/reference/operator-overloading.html) for more details.

The ones that I find particularly useful are get and set. Each corresponds to [] (in an array in Java).

// Kotlin
val a = list[i] // list.get(i)
list[i] = b // list.set(i, b)

Java's List and Map's get / set (put) were annoying, but in Kotlin thanks to operator overloading, collection elements like[i] You can access (in Kotlin you can also register an entry with the set method in Map).

Destructuring Declaration

Sometimes I want to temporarily pair two values and treat them, but not enough to create a class for that. In Java, you can always return only one method return value, but you may have wanted to return two return values once. In such a case, I had no choice but to make a crying arrangement or create a dedicated class.

Kotlin always has one return value, but instead it provides a generic class called Pair <out A, out B>.

// Kotlin
val x = Pair(42, "xyz")

The convenience of this Pair is that it can be assigned as ↓.

// Kotlin
val (a, b) = x
println(a) // 42
println(b) // "xyz"

This is called ** Destructuring Declaration **. In this case, if you create a method that returns Pair, you can make it behave as if there are two return values.

// Kotlin
fun foo(): Pair<Int, String> {
  return Pair(42, "xyz")
}

val (a, b) = foo()

In fact, this feature is not a proprietary patent of Pair. Any class can implement this functionality using classes with ʻoperator fun such as component1, component2`.

// Kotlin
class Foo(val a: Int, val b: String) {
  operator fun component1(): Int {
    return a
  }

  operator fun component2(): String {
    return b
  }
}

val (a, b) = Foo(42, "xyz")

Of course, it can be decomposed into two or more values and assigned. In addition to Pair, Kotlin's standard library also provides a class that holds three values, Triple.

// Kotlin
val triple = Triple(42, "xyz", true)
val (a, b, c) = triple

However, be aware that abuse of Pair and Triple will make the type meaningless and impair readability. In particular, if you start to handle values as Pair or Triple instead of just using it temporarily as a return value, consider whether it is better to replace it with your own class.

Destructuring Declarations can also be used in combination with the for loop. For example, in Kotlin, when you retrieve an element of List in a for loop, you can retrieve the index along with it as follows:

// Kotlin
val list = listOf("a", "b", "c")
for ((index, element) in list.withIndex()) {
  println("$index : $element")
}
0 : a
1 : b
2 : c

The return type of the withIndex method is ʻIterable <IndexedValue >. ʻIndexedValue <T> implements component1 and component2, so you can retrieve the value while decomposing it like ↑.

You can also iterate Map to retrieve keys and values.

// Kotlin
val map = mapOf(
  "a" to 2,
  "b" to 3,
  "c" to 5
)

for ((key, value) in map) {
  println("$key : $value")
}
a : 2
b : 3
c : 5

This is because the Map <K, V> ʻiterator method returns ʻIterator <Map.Entry <K, V >>, and the component1 ofMap.Entry <K, V>is the key. This is because component2 returns a value. The Map.Entry <K, V> returned by the iterator next is assigned to(key, value)one by one and the loop is executed.

Furthermore, the above to is actually generated by Pair. " a "to 2 is the same as writing"a" .to (2). In Kotlin, methods declared with the ʻinfixmodifier can be called infix notation in this way. Since" a "to 2 = "a" .to (2) = Pair ("a", 2) , the part of mapOfis written as follows using the constructor ofPair`. can also do.

// Kotlin
val map = mapOf(
  Pair("a", 2),
  Pair("b", 3),
  Pair("c", 5)
)

Since ʻA and BofPair <A, B> do not have a separate relationship of ʻA to B, it is assumed that this to is used together with mapOf. I think it has been done. Most languages often have special literals and syntax for Map, but Kotlin tends to try to solve with the language syntax as much as possible, and to is one of the typical ones. It is one.

Data class

With the primary constructor, it was easy to put together the declaration and implementation of the constructor, fields, getters, and setters. But ** _Data Class _ ** makes it even easier.

Often classes have only getters and setters, just hold values as data. Such a class is called a Data Class in Kotlin.

In such classes, in addition to constructors and properties, there are often routine implementations of ʻequals, hashCode, and toString. In Java, those codes are generated by the function of the IDE, but in Kotlin, you just add dataas a modifier to the class declaration. Then, implementations ofhashCode, ʻequals, toString are created behind the scenes and can be treated as if they existed.

// Java
public final class Person {
  private final String firstName;
  private final String lastName;
  private final int age;

  public Person(String firstName, String lastName, int age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public int getAge() {
    return age;
  }

  @Override
  public int hashCode() {
    return ...;
  }

  @Override
  public boolean equals(Object object) {
    if (!(object instanceof Person)) {
      return false;
    }

    Person person = (Person)object;
    return firstName.equals(person.firstName) && lastName.equals(person.lastName) && age == person.age;
  }

  @Override
  public String toString() {
    return "Person(firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + ")";
  }
}
// Kotlin
data class Person(val firstName: String, val familyName: String, val age: Int)

In addition, Data Class automatically generates methods such as component1, component2 for each property. Therefore, you can also use Destructuring Declaration on an instance of Data Class.

// Kotlin
val person = Person("Albert", "Einstein", 28)
val (firstName, familyName, age) = person

And the most useful thing about Data Class is the copy method.

In modern programming, the idea is that what can be immutable should be as immutable as possible. Mutable instances tend to cause problems when shared, so you have to return a copy depending on your needs. However, if you return a copy of an instance and the value it holds is a mutable instance, you must also copy it in a chain reaction (shared without a deep copy rather than a shallow copy). We cannot guarantee that mutable instances will not cause problems). To avoid such complexity, it is simpler to separate the parts that can be immutable from the parts that must be mutable, and to complete the immutable world with immutable.

However, even in an immutable world, there are cases where you want to change only part of an instance. When you want to change an instance of an immutable class, express the change by recreating a new instance with the changes.

// Kotlin
val person = Person("Albert", "Einstein", 28)
val newPerson = Person(person.firstName, person.lastName, person.age + 1)

As shown in ↑, it is troublesome to pass all properties to the constructor just to change one property. It might be tolerable if you have about 3 properties, but what if you have 20 properties? It's easier to write using the Data Class's copy method.

The following copy method is automatically generated in the Data Class.

// Kotlin
fun copy(firstName: String = this.firstName, lastName: String = this.lastName,
  age: Int = this.age) = User(firstName, lastName, age)

Since the default arguments are set, you only need to specify the property you want to change.

// Kotlin
val person = Person("Albert", "Einstein", 28)
val newPerson = person.copy(age = person.age + 1)

This is not much different from changing a mutable instance with setter. ** It's great to be able to achieve immutability and ease of change at the same time **.

Extension

When writing an object-oriented language program, you may want to add methods to an existing class.

// Kotlin
(3 + 2) * (3 + 2) //I want to square the calculation result`+`Is done twice and is useless
(3 + 2).square() // `Int`To`square`I wish I had a method

Of course, you can create a function instead of a method and pass the object as the first argument.

// Kotlin
fun square(value: Int): Int = value * value

square(3 + 2)

However, if you want to concatenate multiple processes with a function, it is inconvenient because the order of the processes and the order in the code are reversed.

// Kotlin
//Execute in the order of foo → bar → baz → qux
qux(baz(bar(foo(x))))

Methods can be chained in order.

// Kotlin
//Execute in the order of foo → bar → baz → qux
x.foo().bar().baz().qux()

Kotlin allows you to add methods (like) to your class later. This mechanism is called ** Extension **.

// Kotlin
fun Int.square(): Int = this * this

(3 + 2).square()

However, the methods added by Extension are different from regular methods.

Ordinary methods are dynamically resolved at run time which implementation is actually called.

// Kotlin
open class Animal {
  open fun foo(): Int = 2
}
class Cat: Animal() {
  override fun foo(): Int = 3
}

val animal: Animal = if (Math.random() < 0.5) Animal() else Cat()
animal.foo() // `animal`But`Animal`If`2` 、 `Cat`If`3`

However, the methods added by Extension are statically resolved at compile time. Polymorphism is not possible.

// Kotlin
open class Animal
class Cat: Animal()

fun Animal.foo(): Int = 2
fun Cat.foo(): Int = 3

val animal: Animal = if (Math.random() < 0.5) Animal() else Cat()
animal.foo() // `animal`But`Animal`But`Cat`But`2`

Extension is not rewriting the class itself. The substance of the method added by Extension is a function. A function that looks like such a method is called ** Extension Function **. The behavior of the code in ↑ is easy to understand if you think of it as an ordinary function like ↓.

// Kotlin
open class Animal
class Cat: Animal()

fun foo(animal: Animal): Int = 2
fun foo(cat: Cat): Int = 3

val animal: Animal = if (Math.random() < 0.5) Animal() else Cat()
foo(animal) // `animal`But`Animal`But`Cat`But`2`

Which of the overloaded foos is called is determined at compile time. Since ʻanimal is of type ʻAnimal, which foo is called, whether it is ʻAnimal or Cat, is determined by the type of the value passed to the argument (in this case ʻAnimal). Will be done.

Why does Extension do this confusing thing without rewriting the class itself? If you rewrite the class itself, if you happen to add a method with the same name between different libraries, the method implementation will conflict. If libraries A and B both add a method called foo to the same class, it is possible that the foo method in library A will be called unexpectedly in library B. That's scary and I can't use Extension. Such confusion cannot occur if it is resolved statically at compile time.

It is convenient to be able to call the Extension Function in the form of a method, but it can be confusing that the behavior changes depending on whether it is a real method or an Extension Function, even though it looks the same from the user side. Don't add an Extension Function with the same name in a superclass and a subclass, as it can be confusing.

object

In some cases, like a singleton, a class needs only one instance. Kotlin makes it easy to create singletons by using the keyword ʻobject instead of class`.

// Java
class Foo {
  private static final Foo INSTANCE = new Foo();

  private Foo() {}

  public static Foo getInstance() {
    return INSTANCE;
  }

  public int bar() {
    return 42;
  }
}

Foo.getInstance().bar(); // 42
// Kotlin
object Foo {
  fun bar(): Int = 42
}

Foo.bar() // 42

It may look like a static method in Java because it'sFoo.bar (), but Foo is a class and an instance. As proof of that, you can also assign Foo to a variable of type Foo.

// Kotlin
val foo: Foo = Foo
foo.bar() // 42

It's easy not to do something like Foo.getInstance (), and unlike a class that only has a static method, ʻobject` is also an instance, so you can inherit from other classes. It's convenient because you can even do polymorphism.

// Kotlin
interface Foo {
  fun bar(): Int
}

object Baz : Foo {
  override fun bar(): Int = 42
}

Baz.bar() // 42
val foo: Foo = Baz
foo.bar() // 42

Note that Kotlin uses this ʻobject` to create an anonymous inner class. This is because there is always only one instance of an anonymous inner class.

// Java
button.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
    ...
  }
});
// Kotlin
button.setOnClickListener(object : View.OnClickListener {
  override fun onClick(view: View) {
    ...
  }
})

By the way, Kotlin can also use SAM conversion like Java 8, so in reality, the code above can be written concisely as follows.

// Kotlin
button.setOnClickListener { view ->
  ...
}

Sealed Class

You may want to create a class or interface and limit it to just this class that can inherit / implement it.

For example, suppose you create a type that maps JSON. The JSON specification is clearly defined at here, and the only accepted JSON values are object, array, string, number, true, false, and null. Let's express this by type.

Let's assume that they are represented by JSONObject, JSONArray, JSONString, JSONNumber, JSONTrue, JSONFalse, and JSONNull, respectively. And consider the JSONValue interface as their supertype.

// Kotlin
interface JSONValue
class JSONObject(val value: Map<String, JSONValue>) : JSONValue
class JSONArray(val value: List<JSONValue>) : JSONValue
class JSONString(val value: String) : JSONValue
class JSONNumber(val value: Double) : JSONValue
object JSONTrue : JSONValue
object JSONFalse : JSONValue
object JSONNull : JSONValue

Note that JSONTrue, JSONFalse, JSONNull are ʻobject, not class. Instances of these types correspond to JSON true, false, and null, respectively, and are ʻobject because there is only one.

However, this allows someone to add something like class JSONFoo: JSONValue later. The JSON spec allows only the above seven JSON values, so I want to prevent other classes from implementing JSONValue. Java cannot enforce such constraints, but Kotlin's ** Sealed Class ** does.

// Kotlin
sealed class JSONValue
class JSONObject(val value: Map<String, JSONValue>) : JSONValue()
class JSONArray(val value: List<JSONValue>) : JSONValue()
class JSONString(val value: String) : JSONValue()
class JSONNumber(val value: Double) : JSONValue()
object JSONTrue : JSONValue()
object JSONFalse : JSONValue()
object JSONNull : JSONValue()

Sealed Class can only be inherited from within the same file in which it was declared. Therefore, a third party cannot implement the subclass without permission.

Since the types of subclasses are limited, it works well with exhaustive branching by type using when.

// Kotlin
val json: JSONValue = ...
when (json) {
  is JSONObject -> { ... }
  is JSONArray -> { ... }
  is JSONString -> { ... }
  is JSONNumber -> { ... }
  is JSONTrue -> { ... }
  is JSONFalse -> { ... }
  is JSONNull -> { ... }
}

If you branch with ʻis, Smart Cast can treat json as a checked type in the part of {...} . For example, in the {...}part of ʻis JSONObject-> {...}, json can be treated as a JSONObject type.

Note that Sealed Class is a class, not an interface. However, you cannot instantiate the Sealed Class itself because it automatically becomes an abstract class. You can define only the ʻabstract` method in the Sealed Class body and use it as an interface, or you can write a common implementation.

Scope function

Kotlin has a set of useful functions called scope functions. ʻAlso, ʻapply, let, run, with. However, although the name scope function is used in both Japanese and English, it could not be confirmed in the official document. → (Addition) [Original from the official blog](http://qiita.com/ngsw_taro/items/d29e3080d9fc8a38691e#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97% E9% 96% A2% E6% 95% B0% E3% 81% A8% E3% 81% 84% E3% 81% 86% E5% 90% 8D% E7% A7% B0% E3% 81% AB% E3% It looks like 81% A4% E3% 81% 84% E3% 81% A6).

@Ngsw_taro detailed explanation about the scope function, so I think it is especially useful here let and ʻapply` I will only introduce about.

let

Let's say you want to do a calculation like x + 1 / x. Now, if x is found byfoo (42), the code to calculate x + 1 / x can be written as:

// Kotlin
foo(42.0) + 1 / foo(42.0)

However, there is a problem with this code. That is, I've run foo (42) twice. If foo is a very heavy process, it is useless to do the same calculation twice. Or, if the process changes the result every time it is executed like Math.random (), the calculation result will change. To avoid that, you have to assign the result of foo (42) to a variable once.

// Kotlin
val x = foo(42.0)
x + 1 / x

However, it is inconvenient because it becomes impossible to write in one expression if the assignment to the variable is inserted. Let is useful in such a case. let is an Extension Function implemented in the standard library for any type and can be used as follows:

// Kotlin
foo(42.0).let { x -> x + 1 / x }

The [implementation] of let (https://github.com/JetBrains/kotlin/blob/1.1.2/libraries/stdlib/src/kotlin/util/Standard.kt#L62) looks like this: ..

// Kotlin
inline fun <T, R> T.let(block: (T) -> R): R = block(this)

That is, it passes itself to the function passed as an argument, and the return value of that function is the return value of let itself.

As mentioned above, let is convenient when you want to use the calculation result multiple times in one formula.

In addition, it is convenient to use it in combination with ?. As shown in Last introduction.

// Kotlin
val x: Int? = ...
val square: Int? = x?.let { it * it }

The lambda expression {it * it} above is only executed if x is not null. If x is 3, then square becomes 9. On the other hand, if x is null, it is x? ., so let itself is not executed and the result ( square) is null. This is the equivalent of map or flatMap in Java's ʻOptional`.

apply

Last but not least, this is my favorite ʻapply`.

For a class with many parameters to set, you may want to create an instance and then read setter repeatedly to set it up. ʻApply` is useful in such cases.

For example, ↓ is the code excerpted from the JavaFX Oracle Tutorial (http://docs.oracle.com/javafx/2/get_started/hello_world.htm).

// Java
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event) {
        System.out.println("Hello World!");
    }
});

StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();

The code is verbose because I call setter repeatedly, and the hierarchy is confusing and cluttered.

Rewriting this in Kotlin with ʻapply` gives:

// Kotlin
primaryStage.apply {
  title = "Hello World!"
  scene = Scene(StackPane().apply {
    children.add(Button().apply {
      text = "Say 'Hello World'"
      onAction = EventHandler<ActionEvent> { println("Hello World!") }
    })
  }, 300.0, 250.0)
  show()
}

In the lambda expression passed to ʻapply, the point is that you can access titlewithout going throughprimaryStage, like title = "Hello World!" . This avoids repeatedly accessing members in the form of primaryState.. This is because in the lambda expression passed to ʻapply, the receiver of ʻapply, primaryStage, is treated as this. You can do this with Kotlin's [linkage mechanism](https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver) that associates the receiver with a function literal as this`. Because.

Also, since the return value of ʻapply is the receiver itself (primaryStageforprimaryStage.apply {...}), eliminate the temporary variables such as btn and root` in the Java code. I can. This is easy to understand on a case-by-case basis, but if you want to create a temporary variable, you can also create it in Kotlin. I only assign to temporary variables when it's hard to tell what I'm doing without a name and it's likely to compromise the readability of the code.

ʻApply` is implemented as follows:

// Kotlin
inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

The T. of this T. ()-> Unit links the receiver to this.

How to learn Kotlin in the future

This post is intended to help Java programmers get started with Kotlin smoothly and is not an exhaustive explanation. If you want to learn Kotlin more comprehensively, I recommend you to use the Official Site Documents. Although it is in English, I think that Android application developers usually read English, and since it is plain English, I don't think there is a big problem.

Recommended Posts

What Java programmers find useful in Kotlin
Cannot find javax.annotation.Generated in Java 11
Find a subset in Java
[Java] Get KClass in Java [Kotlin]
I tried to find out what changed in Java 9
Bean mapping useful in Java ModelMapper
A summary of what Java programmers find when reading Kotlin source for the first time
What is a class in Java language (3 /?)
What is a class in Java language (1 /?)
What is a class in Java language (2 /?)
What is the main method in Java?
HMAC in Kotlin
Partization in Java
Changes in Java 11
Rock-paper-scissors in Java
What is Java <>?
What I learned in Java (Part 2) What are variables?
What is Java
What I did when I converted java to Kotlin
What I've always been interested in in Java final
Pi in Java
Where Java programmers tend to trip over Kotlin
How to write Java String # getBytes in Kotlin?
What Java inexperienced people did to study Kotlin
FizzBuzz in Java
[Java] Get KFunction from Method / Constructor in Java [Kotlin]
Which is better, Kotlin or Java in the future?
Browse class objects in Kotlin (instead of Java class name.class)
Write a class in Kotlin and call it in Java
What I learned in Java (Part 3) Instruction execution statement
What I learned when building a server in Java
[java] sort in list
Read JSON in Java
Interpreter implementation in Java
Make Blackjack in Java
Rock-paper-scissors app in Java
Constraint programming in Java
Put java8 in centos7
Combine arrays in Java
"Hello World" in Java
Callable Interface in Java
Comments in Java source
Azure functions in java
Format XML in Java
Simple htmlspecialchars in Java
What is Java Encapsulation?
Big Decimal in Kotlin
Boyer-Moore implementation in Java
Hello World in Java
Use OpenCV in Java
webApi memorandum in java
[Java, Kotlin] Type Variance
Type determination in Java
Ping commands in Java
Various threads in java
Zabbix API in Java
ASCII art in Java
Compare Lists in Java
POST JSON in Java
What is Java technology?
Express failure in Java