4

I'm taking my first steps with kotlin.

I am migrating some my existing java code to kotlin.

I have the folllowing line:

storyDate.ifPresent(article::setPublishDate);

Where storyDate is an Optional and article has a method setPublishDate(Date) method.

How would I migrate this line to kotlin?

The auto migrator at https://try.kotlinlang.org is

storyDate.ifPresent(Consumer<Date>({ article.setPublishDate() }))

But this line doesn't compile with the kotlin compiler.

Jayson Minard
  • 84,842
  • 38
  • 184
  • 227
Michael Wiles
  • 20,902
  • 18
  • 71
  • 101
  • The choice for you is, do you want idiomatic Kotlin code that uses the built-in way of dealing with null safety or do you want to stick with more Java friendly code that must resort to optionals to hide the null checks – zapl Feb 19 '18 at 09:42
  • 1
    You don't even have to convert it. The Java line should work as well. It's compatible with Kotlin syntax. – tynn Feb 19 '18 at 13:30
  • 1
    Thanks for your inputs... I've realised, as you've all said, that null safety is built into kotlin so converting java code that uses lots of Optionals would require some massaging to I would say, remove the Optional as one should be using a language as its designed. – Michael Wiles Feb 26 '18 at 21:22

3 Answers3

10

I strongly prefer using extension functions and extension fields, so I've written smth like

val <T> Optional<T>.value: T?
    get() = orElse(null)

And then you can use it anywhere (after import) like

myOptional.value?.let {
    // handle here
}
asm0dey
  • 2,841
  • 2
  • 20
  • 33
6

It’s rather uncommon to use Optional in Kotlin. If you can make storyDate work as an ordinary unwrapped type, such constructs can often be expressed with a simple let call:

storyDate?.let {
    article.setPublishDate(it) 
    //probably property access works as well:
    article.publishDate = it
}

How it works: The safe call ?. will invoke let only if storyDate is not null, otherwise the whole expression evaluates to, again, null. When the variable is not null, let is called with a simple lambda where storyDate is accessible by it (or you can rename it to whatever you like).

Side note:

If storyDate really must be Optional, you can still use the depicted construct by unwrapping it like this:

storyDate.orElse(null)?.let {}
s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
5
storyDate.ifPresent { Article.setPublishDate(it) }

or

storyDate.ifPresent(Article::setPublishDate)

will work.

In the first example, it denotes the value in the optional instance, which is the Date in the optional storyDate.

I assumed that Article is a class, which has the setPublishDate(Date) static method, because class names are always capitalized.


But if article is an instance, not a class, and it has non-static method, then the following will work.

// article = Article(/* some Article-typed object */)
storyDate.ifPresent { article.setPublishDate(it) }

it has the same meaning as the above one, i.e., the actual Date value in Optional.

Naetmul
  • 14,544
  • 8
  • 57
  • 81