[00:00.000 --> 00:07.000] Thanks to be here. Thanks for missing your lunch. [00:07.000 --> 00:13.000] And let me rant about Kotlin. I am Nicolas Frankel. [00:13.000 --> 00:16.000] I've been a developer for, like, now more than 20 years. [00:16.000 --> 00:18.000] Perhaps I'm not a developer anymore. [00:18.000 --> 00:21.000] I'm a developer advocate, but I still see myself as a [00:21.000 --> 00:23.000] developer. I love developing. [00:23.000 --> 00:28.000] Right now I work on the Apache API 6 gateway. [00:28.000 --> 00:31.000] It has nothing to do with Java. [00:31.000 --> 00:34.000] It's just an infrastructure component. [00:34.000 --> 00:38.000] But since they allow me to be here, here is the slide. [00:38.000 --> 00:43.000] Anyway, why am I talking about Kotlin in a Java room? [00:43.000 --> 00:46.000] Well, they didn't want me to talk about Kotlin in the Kotlin [00:46.000 --> 00:50.000] room, so that might be one of the reasons. [00:50.000 --> 00:55.000] And also I've mentioned I have, like, two decades of coding [00:55.000 --> 00:59.000] experience, and those two decades were spent in Java. [00:59.000 --> 01:05.000] So I started with Java 1.3, 1.4, 1.3 perhaps. [01:05.000 --> 01:11.000] And, well, there were, like, big wins and small losses. [01:11.000 --> 01:16.000] And I tried Scala, and I didn't like it at all. [01:16.000 --> 01:21.000] I still have the certificate saying, hey, you are like Scala [01:21.000 --> 01:24.000] certified. I didn't like it for multiple [01:24.000 --> 01:27.000] reasons. Then I went to a couple of [01:27.000 --> 01:29.000] conferences. I had a friend, [01:29.000 --> 01:32.000] and she made all sorts of talks about Kotlin. [01:32.000 --> 01:34.000] And I said, we don't need Kotlin. [01:34.000 --> 01:36.000] We have Java. It's enough. [01:36.000 --> 01:41.000] Then I wanted to teach myself Android development, [01:41.000 --> 01:45.000] and Android development at the time was only in Java, [01:45.000 --> 01:47.000] and the API was super low level. [01:47.000 --> 01:51.000] And I said, no, I cannot write such like codes that it brings [01:51.000 --> 01:55.000] me back 15 years ago when I was writing Java on the service [01:55.000 --> 01:57.000] site. And I looked for solutions, [01:57.000 --> 02:00.000] and I found Kotlin. And I thought, wow, [02:00.000 --> 02:03.000] that's cool. And I stopped learning [02:03.000 --> 02:08.000] Android, and now I write Kotlin on the back end. [02:08.000 --> 02:13.000] So just a disclaimer. If Java is the best language in [02:13.000 --> 02:16.000] the world for you, just leave the room. [02:16.000 --> 02:19.000] I'm not trying to bash Java, but depending on your [02:19.000 --> 02:21.000] culture, I'm pretty straightforward. [02:21.000 --> 02:24.000] You might feel offended. So better leave now. [02:24.000 --> 02:28.000] It's up to you. OK, let's start slow. [02:28.000 --> 02:31.000] Immutable references. I'm telling you, [02:31.000 --> 02:35.000] hey, it's better in Kotlin. And you can't tell me, [02:35.000 --> 02:39.000] hey, Java has it, right? Immutable references. [02:39.000 --> 02:42.000] OK, let's try to check how it works. [02:42.000 --> 02:47.000] Immutable references in Java. Oh, fun stuff. [02:47.000 --> 02:52.000] Immutable references in Java. So here, [02:52.000 --> 02:56.000] this is my immutable reference class. [02:56.000 --> 03:01.000] So I have to put final here. I have to put final here. [03:01.000 --> 03:05.000] And I have to put final here. Now I have immutable [03:05.000 --> 03:09.000] references. Who puts final everywhere? [03:09.000 --> 03:13.000] A couple of people. No, really. [03:13.000 --> 03:18.000] We had this idea 15 years ago, and then we decided, [03:18.000 --> 03:23.000] no, it just makes the reading so much harder. [03:23.000 --> 03:26.000] So perhaps not. Even worse, [03:26.000 --> 03:29.000] if you don't put final on the parameter, [03:29.000 --> 03:34.000] you can actually relocate stuff, which I believe is one of [03:34.000 --> 03:37.000] the worst things you can do. Like really, really, [03:37.000 --> 03:41.000] really bad. So I'm not saying that Java [03:41.000 --> 03:44.000] doesn't have it, but I'm saying that in Kotlin, [03:44.000 --> 03:48.000] it's, from the beginning, you need to decide whether it's a [03:48.000 --> 03:51.000] vowel, which means it cannot be reassigned, [03:51.000 --> 03:54.000] or it's a vowel, which means it can be reassigned. [03:54.000 --> 03:57.000] If you are using IntelliJ, I don't know about Eclipse or [03:57.000 --> 04:00.000] NetBeans. The good thing is that if I [04:00.000 --> 04:03.000] say it's a vowel, so it can be reassigned, [04:03.000 --> 04:06.000] it tells me, hey, like, there is something fishy. [04:06.000 --> 04:10.000] It's not an error per se, but at least it's visually like [04:10.000 --> 04:14.000] pleasing. And, of course, by default, [04:14.000 --> 04:19.000] yeah, for those who don't know, any is the equivalent of [04:19.000 --> 04:22.000] object, so it's not very important. [04:22.000 --> 04:25.000] I could write object. By default, you cannot reassign [04:25.000 --> 04:27.000] parameters. Any language that allows you [04:27.000 --> 04:30.000] to reassign parameters should be taken with, [04:30.000 --> 04:35.000] like, utmost caution. It's actually not a great [04:35.000 --> 04:37.000] design idea. So, of course, [04:37.000 --> 04:40.000] Java was designed a long time ago, doesn't have it, [04:40.000 --> 04:44.000] but Kotlin takes the lesson. And, if you think that vowel [04:44.000 --> 04:47.000] and vowel are coming from Scala, because you are a Scala [04:47.000 --> 04:50.000] fanboy, that's completely true. Kotlin has stolen every good [04:50.000 --> 04:53.000] idea. So, don't pretend otherwise. [04:53.000 --> 04:57.000] That's fine. OK. [04:57.000 --> 05:01.000] Second, immutable classes. Well, that's fine. [05:01.000 --> 05:04.000] Now we have Java records. We've got them. [05:04.000 --> 05:07.000] That's fine. Let's continue. [05:07.000 --> 05:12.000] Null safety. Null safety in Java is not that [05:12.000 --> 05:16.000] fun, right? How many ways do you have to [05:16.000 --> 05:20.000] implement null safeties in Java? [05:20.000 --> 05:23.000] That's a good thing. Yeah, that's a good thing. [05:23.000 --> 05:26.000] Diversity is a good thing, because we work in IT. [05:26.000 --> 05:31.000] And, if you want to really, like, have fun, you might check, [05:31.000 --> 05:34.000] like, null-able, null-able, null-able, null-able, [05:34.000 --> 05:37.000] null-able, null-able, null-able, null-able. [05:37.000 --> 05:40.000] Oh, not null. Well, I'm sorry. [05:40.000 --> 05:43.000] Sorry? Yeah, exactly. [05:43.000 --> 05:47.000] I'm not sure it's an error. I think I just copy-pasted. [05:47.000 --> 05:50.000] So, I'm not sure. Yeah, that's really fun stuff. [05:50.000 --> 05:53.000] And, of course, they won't work with one another. [05:53.000 --> 05:56.000] So, you need to have the preprocessor. [05:56.000 --> 05:59.000] Sorry, you need to have the compile-time processor. [05:59.000 --> 06:02.000] And, you need to choose which library you will be using. [06:02.000 --> 06:06.000] And, then, you hope that somehow it will work. [06:06.000 --> 06:09.000] Good. In Kotlin, what do we have? [06:09.000 --> 06:11.000] Well, it's backed into language. [06:11.000 --> 06:16.000] So, basically, here I was too lazy to write it in Java. [06:16.000 --> 06:19.000] But, basically, if you write something in Kotlin, [06:19.000 --> 06:22.000] you have additional types. So, basically, for every, [06:22.000 --> 06:27.000] like, normal type, this is a non-null-able type. [06:27.000 --> 06:31.000] And, this says it's a null-able type. [06:31.000 --> 06:36.000] It means that if you are calling something on a non-null-able [06:36.000 --> 06:43.000] type, you can call whatever you want, plus whatever. [06:43.000 --> 06:48.000] And, if you call something on a null-able type, [06:48.000 --> 06:53.000] Kotlin will say, oh, it was saying something, [06:53.000 --> 07:02.000] and now it doesn't say it. Yes, because plus is smart. [07:02.000 --> 07:09.000] Plus knows how to operate on, like, null-able types. [07:09.000 --> 07:17.000] But, let's do something that is not safe. [07:17.000 --> 07:22.000] Which is, it's also very smart. The library is too smart for [07:22.000 --> 07:29.000] me. Empty. [07:29.000 --> 07:35.000] Reversed? Yeah, finally, thanks. [07:35.000 --> 07:39.000] And, it tells you, hey, you know, this might be null-able, [07:39.000 --> 07:43.000] so please don't call it like this, because there is a chance [07:43.000 --> 07:46.000] you might encounter a null pointer at runtime. [07:46.000 --> 07:50.000] And, yeah, you should take care. And, well, afterwards, [07:50.000 --> 07:52.000] it's quite easy. You can do, [07:52.000 --> 07:55.000] OK, this stuff. I mean, if you have been doing [07:55.000 --> 07:58.000] groovy or, I think, Scala does it too. [07:58.000 --> 08:02.000] But, the compiler tells you, you should be careful about this. [08:02.000 --> 08:06.000] So, and it's, again, it's backed into the language. [08:06.000 --> 08:10.000] So, like, for every type, there are like two real types, [08:10.000 --> 08:14.000] one that might be null-able, the other might not be null-able. [08:14.000 --> 08:17.000] The good thing with, I will show you afterwards, [08:17.000 --> 08:20.000] one you can write extension function that work on null-able [08:20.000 --> 08:23.000] type, which is really, really crazy. [08:23.000 --> 08:27.000] Good. So, second stuff, [08:27.000 --> 08:33.000] better. [08:33.000 --> 08:36.000] The utils classes. [08:36.000 --> 08:40.000] Who has not written a single unit utils classes in their [08:40.000 --> 08:44.000] life? Nobody. [08:44.000 --> 08:48.000] So, even people younger than 30 have written them. [08:48.000 --> 08:51.000] In general, there might be a divide because, like, [08:51.000 --> 08:54.000] yeah, all their developers have written them, [08:54.000 --> 08:58.000] the younger ones, they are smart enough to use the library. [08:58.000 --> 09:02.000] But, the thing is, well, at our age there was no library. [09:02.000 --> 09:07.000] So, basically, we say that Java is in the object-oriented [09:07.000 --> 09:11.000] language, and then we put everything in a class, [09:11.000 --> 09:14.000] we put static methods in a class, and we pretend that it's [09:14.000 --> 09:17.000] object-oriented. Right? [09:17.000 --> 09:21.000] Yes. Well, let's not pretend it's [09:21.000 --> 09:24.000] object-oriented. If it's no object, [09:24.000 --> 09:28.000] a class with static methods is not object-oriented. [09:28.000 --> 09:33.000] So, here I have created my amazing string-utils class. [09:33.000 --> 09:37.000] And, of course, I need to remember because the users of [09:37.000 --> 09:41.000] my class, well, they might instantiate it. [09:41.000 --> 09:45.000] So, I will just remove the constructor, make it private, [09:45.000 --> 09:49.000] again, very object-oriented, and then I create these [09:49.000 --> 09:52.000] capitalized stuff, and I do whatever I want, [09:52.000 --> 09:56.000] and then I can call the capitalized method. [09:56.000 --> 09:59.000] Good. Scala and Kotlin have, [09:59.000 --> 10:03.000] I think, like, similar stuff. [10:03.000 --> 10:09.000] Let's not pretend we are an object-oriented language. [10:09.000 --> 10:14.000] We can just add methods in states, but mostly methods, [10:14.000 --> 10:21.000] on existing classes. That's crazy. [10:21.000 --> 10:25.000] Yeah. Of course, at the bytecode level, [10:25.000 --> 10:28.000] it boils down to a static method. [10:28.000 --> 10:31.000] That's not the problem. The problem is the user [10:31.000 --> 10:34.000] experience, the developer experience. [10:34.000 --> 10:40.000] We can see now that we are really doing here, [10:40.000 --> 10:45.000] we actually are doing object-oriented development. [10:45.000 --> 10:48.000] So, through these functional stuff, [10:48.000 --> 10:53.000] because here we create a function that is at the root [10:53.000 --> 10:57.000] level, we are able to write better object-oriented [10:57.000 --> 11:02.000] code, which is mind-blowing. [11:02.000 --> 11:07.000] Even better, as I mentioned, we can say, [11:07.000 --> 11:14.000] hey, this only applies so here we can have for f of type string [11:14.000 --> 11:18.000] might be null, so this is a nullable type, [11:18.000 --> 11:23.000] and here we cannot say f.capitalize because it's [11:23.000 --> 11:27.000] null, right? It's a nullable type. [11:27.000 --> 11:29.000] Here it only applies to real strings, [11:29.000 --> 11:32.000] but we can do something like this. [11:32.000 --> 11:35.000] We can say, hey, it might be a nullable type, [11:35.000 --> 11:41.000] and we can check if this equals null, [11:41.000 --> 11:47.000] then we return the default, which might be an empty string. [11:47.000 --> 11:53.000] Yeah, I see like, what the hell? [11:53.000 --> 11:56.000] And in the end, that's a static method, [11:56.000 --> 12:00.000] but how you call it is like object-oriented, [12:00.000 --> 12:05.000] which, in my opinion, makes Kotlin much more object-oriented [12:05.000 --> 12:08.000] than Java will ever be. Well, will ever be, [12:08.000 --> 12:12.000] no, I'm not sure. Let's see what we have in the [12:12.000 --> 12:17.000] future. So, that's already good stuff. [12:17.000 --> 12:23.000] And then, oof, Rayfied generics, right? [12:23.000 --> 12:29.000] Who has been bitten by the lack of Rayfied generics already? [12:29.000 --> 12:34.000] Yeah, so I have a collection of thingy and a collection of [12:34.000 --> 12:39.000] foo, and well, at one time you have nothing. [12:39.000 --> 12:47.000] So, the trick when you do Java is to pass the class. [12:47.000 --> 12:51.000] So, here is taken from Spring, when you get a bean, [12:51.000 --> 12:55.000] you say, hey, I want a bean of class whatever, [12:55.000 --> 12:58.000] and then you will get the whatever. [12:58.000 --> 13:02.000] Okay? How can we do it in Kotlin? [13:02.000 --> 13:08.000] Kotlin has this Rayfied T. [13:08.000 --> 13:14.000] When you call a get bean, you can pass the type that you [13:14.000 --> 13:26.000] want, and it will get you, but it's a string. [13:26.000 --> 13:31.000] If we are a bit, like, tricky, we can do this, [13:31.000 --> 13:35.000] and it's a list of strings. [13:35.000 --> 13:38.000] And if you tell it, because it's all about compiling, [13:38.000 --> 13:41.000] because in the end, of course, the byte code is still the [13:41.000 --> 13:44.000] same. The byte code must be compatible [13:44.000 --> 13:47.000] with Java byte code. There is no Rayfied generic in [13:47.000 --> 13:50.000] the byte code. So, it's just about compiling. [13:50.000 --> 13:54.000] And here we can say either we set it here in the signature [13:54.000 --> 13:58.000] when we call it, or we tell that type of, [13:58.000 --> 14:04.000] that S is of type string, and we will get a string. [14:04.000 --> 14:09.000] And I think that's pretty amazing. [14:09.000 --> 14:15.000] The only thing that we need to do is do this. [14:15.000 --> 14:20.000] We need to tell it's Rayfied. Sorry. [14:20.000 --> 14:25.000] Again, we need to tell it's Rayfied, and for Rayfied, [14:25.000 --> 14:28.000] you need to have inline. Why? [14:28.000 --> 14:31.000] Because as I mentioned, there is no trick. [14:31.000 --> 14:35.000] At compile time, it will actually replace the code. [14:35.000 --> 14:41.000] It won't be a call. It will be just copy-pasted. [14:41.000 --> 14:46.000] And so it knows which type you are. [14:46.000 --> 14:51.000] And in the end, so I still have a bit of time, [14:51.000 --> 14:55.000] we can do, like, really, really fun stuff. [14:55.000 --> 15:06.000] I will, yes, fun stuff. [15:06.000 --> 15:11.000] OK. I will create a function beans, [15:11.000 --> 15:15.000] and for the moment, I will return any. [15:15.000 --> 15:18.000] OK? So, some syntactic sugar, [15:18.000 --> 15:20.000] I don't think it's really important. [15:20.000 --> 15:23.000] I don't think it makes me want to use Kotlin. [15:23.000 --> 15:25.000] I don't think you need to use it, [15:25.000 --> 15:35.000] like, either you return the type like this, [15:35.000 --> 15:43.000] or here any idiot can understand it returns any. [15:43.000 --> 15:47.000] So the Kotlin compiler is not an idiot, [15:47.000 --> 15:52.000] but the Java compiler is. [15:52.000 --> 15:55.000] It doesn't make any sense to specify the type explicitly [15:55.000 --> 15:57.000] every time, but still the Java compiler [15:57.000 --> 16:00.000] requires you to do it. It makes no sense. [16:00.000 --> 16:04.000] OK. [16:04.000 --> 16:07.000] Sure, sure. If for whatever reason, [16:07.000 --> 16:10.000] if for whatever reason you want to specify what it is, [16:10.000 --> 16:13.000] because it might be complex, but then if it's complex, [16:13.000 --> 16:16.000] perhaps it doesn't belong to a liner, [16:16.000 --> 16:19.000] then you can still have loads, too. [16:19.000 --> 16:22.000] Especially if you are using, if you return a concrete [16:22.000 --> 16:25.000] implementation and you want your signature to be an interface. [16:25.000 --> 16:28.000] That's perfect. OK. [16:28.000 --> 16:32.000] And now I will have a class which I will call, [16:32.000 --> 16:37.000] let's say, beans DSL. [16:37.000 --> 16:46.000] OK. Here I want this to return beans DSL. [16:46.000 --> 16:51.000] OK. So now I can write something like this. [16:51.000 --> 16:56.000] I can have a main function, main, main, OK. [16:56.000 --> 16:58.000] Private static void main, OK. [16:58.000 --> 17:02.000] And I can call the beans function, beans function. [17:02.000 --> 17:04.000] Great. Nothing mind-blowing. [17:04.000 --> 17:12.000] Now what I can do is I want to write something like this. [17:12.000 --> 17:15.000] OK. So I want to write something like this. [17:15.000 --> 17:20.000] I will just use the compiler, OK. [17:20.000 --> 17:26.000] So I create, here I accept a parameter that takes nothing [17:26.000 --> 17:28.000] and returns units. [17:28.000 --> 17:34.000] Here what I can do is normally I would write something like this. [17:34.000 --> 17:39.000] But in Kotlin, if the loss argument is a lambda, [17:39.000 --> 17:42.000] you can move it outside the parenthesis. [17:42.000 --> 17:45.000] So that's what I did before. [17:45.000 --> 17:49.000] And then here if there is no arguments and there is a lambda, [17:49.000 --> 17:52.000] I can remove the parenthesis. [17:52.000 --> 18:05.000] Good. Now I can add the bean method inside. [18:05.000 --> 18:10.000] And I can say that I can actually call the bean method on the [18:10.000 --> 18:12.000] bean DSL. [18:12.000 --> 18:16.000] So here I can do something like this. [18:16.000 --> 18:19.000] And what is it telling me? [18:19.000 --> 18:21.000] And resolve method beans. [18:21.000 --> 18:24.000] So I still have an issue. [18:24.000 --> 18:26.000] Yes. [18:26.000 --> 18:30.000] Little trick. [18:30.000 --> 18:34.000] Yeah. [18:34.000 --> 18:37.000] Sorry, that's live coding completely. [18:37.000 --> 18:40.000] I thought I would be less fast. [18:40.000 --> 18:42.000] OK. [18:42.000 --> 18:48.000] And now we can say that the bean method is generic, right? [18:48.000 --> 18:53.000] So we can say it accepts a type T. [18:53.000 --> 18:55.000] And I don't remember how it's written. [18:55.000 --> 19:06.000] So I will be doing my stupid stuff. [19:06.000 --> 19:08.000] So this is the inline function. [19:08.000 --> 19:10.000] So here inline fun. [19:10.000 --> 19:13.000] Refi T. [19:13.000 --> 19:17.000] Here and it returns a T. [19:17.000 --> 19:26.000] And if you continue like this, you can have this kind of stuff. [19:26.000 --> 19:30.000] So here this is the spring boot Kotlin DSL. [19:30.000 --> 19:33.000] So you say this will create beans. [19:33.000 --> 19:38.000] And then you can define either through lambda or directly. [19:38.000 --> 19:44.000] And through the refit stuff, here you see the product handler [19:44.000 --> 19:48.000] actually requires two dependencies. [19:48.000 --> 19:51.000] And at compile time, it knows that it requires, [19:51.000 --> 19:54.000] I don't know, a foo and a bor. [19:54.000 --> 19:59.000] So because those ref methods are refit for generics, [19:59.000 --> 20:03.000] it knows it needs to call the ref method calling, [20:03.000 --> 20:05.000] getting a foo and a bor. [20:05.000 --> 20:07.000] And it will inject them. [20:07.000 --> 20:09.000] So here you have the magic at compile time. [20:09.000 --> 20:14.000] And at runtime, it's the usual spring boot stuff. [20:14.000 --> 20:20.000] And I believe it makes my code much easier to read. [20:20.000 --> 20:22.000] Of course, you need to understand the trick. [20:22.000 --> 20:25.000] It's like every time you need to be very explicit in the beginning [20:25.000 --> 20:27.000] because you like a lot of context. [20:27.000 --> 20:30.000] When you have the context, then it makes your stuff [20:30.000 --> 20:32.000] much, much easier. [20:32.000 --> 20:34.000] And that's all. [20:34.000 --> 20:38.000] I don't want to bore you with more details. [20:38.000 --> 20:40.000] You can follow me on Twitter. [20:40.000 --> 20:42.000] You can follow me on masterdom because, well, [20:42.000 --> 20:44.000] you don't know what will happen to Twitter. [20:44.000 --> 20:47.000] And though the talk was not about Apache API 6, [20:47.000 --> 20:51.000] you can check Apache API 6, which makes my job so much [20:51.000 --> 20:52.000] easier. [20:52.000 --> 20:56.000] And I can come back here to talk about unrelated stuff. [20:56.000 --> 20:58.000] Is there any time for questions? [20:58.000 --> 20:59.000] There is. [20:59.000 --> 21:00.000] There is. [21:00.000 --> 21:29.000] Thanks.