I downloaded the release candidate of JDK19 from here https://jdk.java.net/19/ to play a little bit with the new record patterns that were implemented there, but I'm encountering some issues. In my tests, I wrote a version of Optional based on sealed interface plus records, in the following way:
package tests.patterns;
import java.util.Objects;
public class TestRecordPatter
{
public static void main(final String[] args)
{
final Opt<String> opt1 = computeAnswer(23);
final String answer1 = switch (opt1) {
case Opt.Some<String>(String ans) -> ans;
case Opt.None __ -> "no answer";
default -> throw new IllegalStateException("This should not happen"); // A
};
System.out.println(answer1);
final Opt<String> opt2 = computeAnswer(35);
final Object answer2 = switch (opt2) { // B
case Opt.Some<String>(var ans) -> ans; // C
case Opt.None __ -> "no answer";
default -> throw new IllegalStateException("This should not happen"); // A-2
};
System.out.println(answer2);
final Opt<String> opt3 = computeAnswer(84);
final String answer3 = switch (opt3) { // D
case Opt.Some<String> s -> s.value();
case Opt.None __ -> "no answer";
};
System.out.println(answer3);
}
private static Opt<String> computeAnswer(final int question)
{
if (question % 2 == 0) {
return Opt.some(String.valueOf(question / 2));
} else {
return Opt.none();
}
}
private sealed interface Opt<T> permits Opt.Some, Opt.None
{
static <T> Opt<T> of(final T value)
{
return value == null ? none() : some(value);
}
static <T> Opt<T> some(final T value)
{
return new Opt.Some<>(value);
}
@SuppressWarnings("unchecked")
static <T> Opt<T> none()
{
return Opt.None.NONE;
}
record Some<T>(T value) implements Opt<T>
{
public Some
{
Objects.requireNonNull(value, "Value must not be null");
}
}
@SuppressWarnings({ "rawtypes" })
enum None implements Opt
{
NONE;
}
}
}
The first switch expression is using record deconstruction to get the value out of the Some variant using an explicit type for the ans
variable but in this case the java compiler requires the default branch (line marked with A) otherwise it fails with the following error:
TestRecordPatter.java:[10,40] the switch expression does not cover all possible input values
In the second switch, the issue is that using var
instead of explicit type for ans
binds the returned type of the switch to Object
and not to String
. (line marked with B). Moreover, but this is not a java compiler issue, IntelliJ complains on line marked as C, highlighting the var ans
part and saying something like "Type T is required but null is provided".
Finally, the third switch works fine, but that's the "old" (java 17 is old, right?) way of doing it.
Can someone help me? Am I doing something wrong?
EDIT: I just downloaded the Oracle JDK-19 GA version and it has the same issue.
EDIT 2: the second switch, the one with var
has the same behaviour as the first one, so it needs a default case, as pointed by Holger
var
is not a java compiler issue, I’m not sure whether including it here, is helpful. An IntelliJ bug is an entirely different question (if we consider it a question at all, rather than something to report to the IntelliJ developers). – Landmass