Java 23: Restoring the Balance with Primitive Patterns - Inside Java Newscast #66
Вставка
- Опубліковано 5 чер 2024
- The ongoing introduction of pattern matching to Java has put more weight on some language features than on others and unbalanced the language. In Java 23, primitive patterns will fix this regarding primitive types in `instanceof` and `switch`. This episode also goes over other upcoming patterns (deconstruction, static, instance, and constant) and shows how they will build out pattern matching in Java.
JEP 455: openjdk.org/jeps/455
Project Amber documents: openjdk.org/projects/amber/#d...
Download JDK 23 EA: jdk.java.net/23/
~~~ Chapters ~~~
0:00 Intro
1:02 Existing Patterns
1:23 Type Patterns
1:32 Guarded Patterns
1:53 Record Patterns
2:09 Unnamed Patterns
2:29 Nested Patterns
2:50 Summary of Existing Patterns
3:38 Primitive Patterns in `instanceof`
5:17 Primitive Patterns in `switch`
6:30 Primitive Patterns when Nested
7:33 Upcoming Patterns
7:59 Deconstruction Patterns
8:40 Static Patterns
9:09 Instance Patterns
9:54 Constant Patterns
10:37 Try JDK 23 EA!
Tags: #Java #Java23 #OpenJDK #PatternMatching - Наука та технологія
BigDecimal.
I love that you used that clip, that guy is so funny. His video about senior Rust developers is too good.
I work in a corporate.
It's also linked as a card. The (i) in the top-right corner should pop open when I use it the first time.
The JS one hit so close to the bone. I loved it. He could do a new one per month!!!
I love pattern matching so much. When I used Erlang for some time, there were two things I missed a lot in Java. 1. Processes (-> Virtual Threads) and 2. Pattern Matching (which is partly already there. Great Stuff!
Never thought I'd see "Programmers Are Also Human" on the official Java channel! You guys are the best at DevRel 😄
Nice intro. So much patterns I couldn't understand what was going on there, but I could see the pattern.
:D In case you want to better understand how patterns work, check out this video: ua-cam.com/video/QrwFrm1R8OY/v-deo.html
@@nipafx that was mostly a bad joke, but I liked the segue to the other video
Instance Patterns are wild! The Regex one is something that's immediately visible, but the one with mapsTo is crazy. Might even be more efficient than an Option-returning Getter!
Very cool
switching over float sounds dangerous because typically, one wouldn't want exact equality checking due to the precision issues.
I can't recall having ever been in a situation where I wanted to switch over a float in the first place, although maybe I just never considered it, given that it was not allowed. :D I can imagine it may occur occasionally in the context of matching something else. That said, I don't really see a reason to switch over many specific values. 0, 1, maybe some constants like π (`Math.PI` is a double, though)... the rest would probably be guarded to compare to ranges (and I think upcoming patters will make that more succinct). So I don't worry too much about people comparing a float to arbitrary specific values but you are right that, if they do, that can easily create bugs - maybe something linters could have an eye open for.
Why can't the pattern match be a range test?
@@donwinston You can do that in 23 with a guarded pattern, but it isn't exactly elegant:
case float f when 100 < f && f < 200 -> ...
One could imagine a language feature targeting this specifically:
case float f in [100, 200] ->
But I don't know of any plans to add that and I guess that it won't be added. Once we can declare instance patterns, we should be able to get close to that with custom patterns:
case range(100, 200).has(float f) -> ...
The advantage of that is that it keeps the language conceptually simpler and allows custom logic that doesn't stick out, e.g.:
case isPrime(float f) -> ...
case powersOf(2).has(float f) -> ...
@@nipafx Even constants like 0 or 1 can be an issue. For example, there's a differentiation between positive and negative 0 or one could have a value that's almost 0/1/pi but not exactly. However, in the spirit of your range check reply, I could imagine something like
case float f when inRange(f, delta)
@@danthe1st This is all theoretical of course, but I think use cases that want to execute a special branch for 0 or 1 would probably only like to take it, when the number is actually 0 or 1, not when it's just close to it. (The positive/negative issue is real, though, as can be seen by me not including negative zero in my example.)
Great improvements 🎉
6:14 this is why I think switch expressions should've used a different keyword for "switch patterns", like use "match()" instead of "switch()", and we wouldn't have this issue, they would be 2 different features completely.
Using "switch" for both statements and expressions was a mistake imo.
Other than that these are great features, looking forward to use them!
when keyword :p
I really like where pattern matching in Java is going :)
Nice features :)
Hi, I want to know all these pattern matching, when comparing to if-else statements, would the compiler provide some magic behind the scenes that makes them run faster? or it's just some syntactic suger, that underneath it's the same if we just use if-else to replace them?
6:50 - when nesting switches goes too far 🤦🏾♂
😂
`instanceof` keyword is so long. Why not introduce a shorter one? Perhaps `is`:
if (o is String s) {
…
}
The usual reason: adding keywords risks incompatibility with existing code. In this case, it would probably work though, because that "is" syntax doesn't have any existing meaning.
@@prdoyle one drawback is, when existing code also use a new keyword already - for example as a variable `is`. This would in some cases also break exisiting code.
@@Muescha probably, `InpuStream is = …;`.
Java 23 😘😘👌👌
So, pattern matching in Java becomes more and more similar to Scala, interesting
I wonder if Java will have head::tail and @tailrec some day
@@avalagum7957 at least collections without streams
@@avalagum7957 This was actually on the table for Project Loom when it was in its early stages. I can't recall the connection and I think it got dropped pretty early, but it's not like OpenJDK doesn't have it on its radar.
Because... Why not?
@@Andr805 I personally love it, as Scala-dev) but my Java-friends were always against it. Especially with underscore
Hey, what would be the best way to switch over an enum and ensuring exhaustiveness. I tried the following approach and while it works, it looks a little bit hacky. I also thought about turning it into a switch expression and returning a value that gets saved to an unnamed variable but this doesn’t work when the individual switch paths don’t return a value.
enum Command {
A,
B,
C;
}
var command = Command.A;
// this compiles and checks for exhaustiveness
switch (command) {
case A -> System.out.println("A");
case B -> System.out.println("B");
case C -> System.out.println("C");
case Command c when c == null -> {/* enables exhaustiveness */}
}
change last line to `case null ->` ?
JEP441
@@Muescha case null -> {} worked, thanks :)
Call me simple, but I sincerely hope that I won't have to maintain code anytime soon that are using these fancy pants features that were introduced since Java 8. It might be great for job security to use them though, as it will take people with several PhD-s to understand them.
You are simple.
@@prdoyle Haha, I know. It's a struggle. :) I'm looking forward to great study materials when things settle down a bit, but which author dares to write a book which is obsolete in 6 months? I don't know, how universities cope with the situation. One of Java's main strengths used to be that it's being thaught in unis as one of the main languages. Heck, one has to be on the edge if wants to get a recent Oracle Certification. Which will become obsolete in a minute. Crazy, no?
🎉 finally Java is getting closer to scala!
Oh no 🤣
Who decided the "switch" keyword is more appropriate than "match"?
Not sure. Maybe Dennis Ritchie when he designed C in the early 70s? Although, chances are he took his inspiration from another language, just like Java did. Or Swift, to pick a younger example.
backport compatibility
Does this help project Valhalla?
It doesn't help to finish Valhalla earlier but it starts fixing a problem that Valhalla will cause: When we can add our own primitive-like numerical types, we will very soon want to convert between them and between them and the onboard primitives but that can't be part of the language (because it doesn't know our custom types). This opens the door to code that asks "is this custom positive int an instance of Java's int?"
Oh my God... "Instanceof Byte" is then different from "instanceof byte"???? What happens if an "Integer" object is tested against that? If have the feeling this feature will create problems...
Quote,
"Instanceof Byte" is then different from "instanceof byte"????
Yeah, because Byte is an Object and byte is a primitive. A primitive has a value, i.e. not a reference to an object.
Hi there 😁 totally off topic, but it might be good to think of an extra pop filter in front of your mike man. I just happened to listen in headphones and maaan, thats some ASMR Java experience, i tell you 😁😁😁
I notice them during editing, too. But a pop filter is large, in the way of my gesticulating, and looks shitty. :( But I'll have to figure something out. Thanks for pointing this out - bursts my delusion that "probably nobody cares". :D
I had enough "patterns" to spend for the rest of my life, thank you 😂
Mission accomplished! 😅
too much is done for switch that we are rarely using
That's like saying "too much was done for lambdas, we are rarely using anonymous classes." 😉
why not add support for default parameters
03:07 "Six fingers five bullets🤔"
It's Valhalla coming?
from now on I'll write all my java programs with gleam-style checks instead of ifs, so switch(boolean) { case true -> ....; case false -> ....;}
no more ternery operator?
@@Muescha that would be the dream
please make the deconstructor take only required fields according to name and type Point(int a), like in Rust. imagine if you have a record with 10 or more fields, it will be a horror _ _ _ _ _ _ _ _ _ _, int a, _ _
You could argue that any class with ten fields needs refactoring.
@@IanFairmanUK , right. but I still find it ugly to have to write useless _ _ _ _ _.
on the one hand you make the code more readable/shortened, but on the other hand you force to write completely useless _ (kotlin-like moment with ternary operator)
give me the ability to pull the fields I need out of the class/record, that's all
That's an interesting spin on the "named arguments" idea - I'll have to think about that. Named arguments themselves are not likely to appear any time soon, though: ua-cam.com/video/mE4iTvxLTC4/v-deo.html
@@nipafx If we are talking about refactoring problems in public libraries, if you add another field to record (at the end) that will not be processed in pattern matching (at least _), there will be problems as well, sooo...
@@nipafx I watched part of the video about mutable records. it's very unfortunate. immutability is useful in a multi-threaded environment, in the context of a game, where often everything is done by one thread, you force allocation of new objects for small changes. I also agree that you could make fields public final , the only advantage of methods is that if you change the name of the field, you will save the previously written code.
Why do i always missed your update?
please don't want to be left behind
Hard disagree on the coersion for primitive patterns; type coersion is not the same as type casting (which is how reference patterns work).
Furthermore you mention constant patterns are not useful on their own, but this is exactly how enum switches already work.
Not sure if I'm fond of these pattern matching, they are too dependant on the constructor declarations and types, and not enough on the field names.
For using TypeScript everyday, I really love how you can deconstruct objects in TS; sometimes I dream of something similar in Java.
The solution you show from Java 23 seems way too verbose and generates hard-coupling with your records structure. **Meh**
What you're describing seems to be named arguments, even if just for deconstruction. I get that that would be nice, but I'm not sure we'll get that. Here's Brian on named arguments in general: ua-cam.com/video/mE4iTvxLTC4/v-deo.html
does anybody use switch at all in projects instead of polymorphism or simple if-else? 😂
good question) typically something that based on strategy pattern)
@@yanchumak8419 simple map is much better than switch for strategy pattern, isn't it?
Sometimes polymorphism via inheritance is exactly what you don't want, e.g. because you'd rather not add all operations to the type. Check out this video for an explanation: ua-cam.com/video/QrwFrm1R8OY/v-deo.html
Almost never. Switches can most often be replaced by interfaces or polymorphism.
I'll eventually use a switch or an instanceof pattern if I need to check if an instance implements an interface (to enable traits).
But in general, I consider switches a code smell.
@@OzoneGrifCould you give an example of that code smell?
Please, leave "switch" alone!
No way. Switch has got so much better in the last few releases.
Learn AI and Python
about map.containsKey/points.get
should we even think about operator overloading? and for maps map[key] = value , value = map[key]