Live data from Hacker News

New Features in Java 14

blogs.oracle.com

51–60 of 188 posts

Re: New Features in Java 14

#51

I wonder about records - they would be great for simplified implementation of immutability, but they seem to not provide a way to copy with a subset of modified fields - like in Scala: case class Person ( firstName: String, lastName: String, age: Int ) you could create an instance like this: val emily1 = Person("Emily", "Maness", 25) and then create a new instance by updating several parameters at once, like this: //…

>val emily1 = Person("Emily", "Maness", 25)

The assumption of inputs based on the order of the class items frightens me!

Re: New Features in Java 14

#52
post #9
post #5

Earlier quoted context omitted.

Java is quite far away from finally solving NullPointerException issues. Kotlin, C# or TypeScript with their compile time null checks solved it mostly. Common to these three languages is that they need null to be interoperable with older language versions (C#) or with related languages (Java, JavaScript). Languages like Rust that don't even know null (or nil as in Go), have finally solved the problem.

> Languages like Rust that don't even know null (or nil as in Go), have finally solved the problem. I'm in no way a Rust expert, but I see a lot of code with Optionals, something like match sth { Some(v) => do_something None => nothing_to_do } This looks awfully a lot like if (something == null) { nothing_to_do } else { do_something } It might look more pleasant, but it doesn't "solve" anything, only shifts it in a d…

For the case where something really could be absent, you're right; it's the same amount of code. The difference is that in a language with null you have to write that code for every single function parameter, whereas in Rust you can have required parameters that are actually required and only need to check the genuinely optional cases (which is what, maybe 5% of the time?). Make invalid states unrepresentable.

Re: New Features in Java 14

#53

I wonder about records - they would be great for simplified implementation of immutability, but they seem to not provide a way to copy with a subset of modified fields - like in Scala: case class Person ( firstName: String, lastName: String, age: Int ) you could create an instance like this: val emily1 = Person("Emily", "Maness", 25) and then create a new instance by updating several parameters at once, like this: //…

You'd probably have to manually write a Builder in the Person record class. Then the callsite might look something like this:

    val emily2 = emily1.newBuilder()
                    .lastName("Wells")
                    .age(26)
                    .build()

I think the inner Builder pattern is common enough in immutable java object implementations that they might want to include that fully in the Record class generation at some point. Most immutable object libraries that I've seen include a lot more functionality than Records, like builders.

Re: New Features in Java 14

#54
post #51

I wonder about records - they would be great for simplified implementation of immutability, but they seem to not provide a way to copy with a subset of modified fields - like in Scala: case class Person ( firstName: String, lastName: String, age: Int ) you could create an instance like this: val emily1 = Person("Emily", "Maness", 25) and then create a new instance by updating several parameters at once, like this: //…

>val emily1 = Person("Emily", "Maness", 25) The assumption of inputs based on the order of the class items frightens me!

You can use named parameters if you're worried:

  val emily1 = Person(firstName="Emily", lastName="Maness", age=25)
Scala's approach to constructors is a good example of convention over configuration; in Java 99.9% of classes have a constructor like:

    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
which is just ceremonial boilerplate that obscures the actual logic of what the class is doing (an IDE can generate the constructor for you, but the person maintaining your code still has to take the time to comprehend it). You can do the more complicated things in cases where you need to, but it's important to keep the simple case simple.

Re: New Features in Java 14

#55

I wonder about records - they would be great for simplified implementation of immutability, but they seem to not provide a way to copy with a subset of modified fields - like in Scala: case class Person ( firstName: String, lastName: String, age: Int ) you could create an instance like this: val emily1 = Person("Emily", "Maness", 25) and then create a new instance by updating several parameters at once, like this: //…

Java lacks default arguments for functions, which makes that particular API infeasible without adding support for such. They could generate "withFoo" methods or even builder types, but that would butt up against developer preference, so it's probably best to leave it up to developers or a third-party library. Kotlin has a very similar feature in its data classes, FWIW.

Does Kotlin have anything to let you treat data classes in a generic way like you can do with Shapeless in Scala? That's where the real power comes IME - e.g. look at Circe where you can derive JSON encoders/decoders for arbitrarily nested case classes at compile time, so you have zero boilerplate but still get compile-time type safety that stops you from accidentally trying to serialise a file handle or semaphore.

Re: New Features in Java 14

#56

Earlier quoted context omitted.

Java lacks default arguments for functions, which makes that particular API infeasible without adding support for such. They could generate "withFoo" methods or even builder types, but that would butt up against developer preference, so it's probably best to leave it up to developers or a third-party library. Kotlin has a very similar feature in its data classes, FWIW.

> Java lacks default arguments for functions, which makes that particular API infeasible without adding support for such I really wish Java would add both default arguments for functions, and also support for passing function arguments by name. One of these days...

This goes against the very idea of method signatures in Java an overloads based on them. An attempt to add it will likely bring in way, way more backwards-compatibility pain than any benefits are worth.

Writing simple methods with few arguments helps.

Re: New Features in Java 14

#57
post #54
post #51

Earlier quoted context omitted.

>val emily1 = Person("Emily", "Maness", 25) The assumption of inputs based on the order of the class items frightens me!

You can use named parameters if you're worried: val emily1 = Person(firstName="Emily", lastName="Maness", age=25) Scala's approach to constructors is a good example of convention over configuration; in Java 99.9% of classes have a constructor like: this.firstName = firstName; this.lastName = lastName; this.age = age; which is just ceremonial boilerplate that obscures the actual logic of what the class is doing (an ID…

Lombok solves this for Java.

Re: New Features in Java 14

#58
post #5

"Helpful NullPointerExceptions": One of the biggest pain points of Java, probably the biggest. Good that it's being finally solved;

Java is quite far away from finally solving NullPointerException issues. Kotlin, C# or TypeScript with their compile time null checks solved it mostly. Common to these three languages is that they need null to be interoperable with older language versions (C#) or with related languages (Java, JavaScript). Languages like Rust that don't even know null (or nil as in Go), have finally solved the problem.

I have no faith that Java will ever solve the problem after their bungled introduction of the Option type. Step 1 to migrating away from null would be to introduce a working Option type - one that could contain any valid Java value (which includes null for the time being) and where chaining behaviour worked the way you expect (i.e. that doesn't violate the monad laws, even when nulls are being thrown around). People from languages that have solved the problem told the Java folks about these issues, and were ignored, with the result that it's impossible to migrate an existing Java codebase to use Option, and I can't imagine the Java community having the appetite to introduce a non-broken Option that would allow moving off null.

Re: New Features in Java 14

#59
post #9

Earlier quoted context omitted.

> Languages like Rust that don't even know null (or nil as in Go), have finally solved the problem. I'm in no way a Rust expert, but I see a lot of code with Optionals, something like match sth { Some(v) => do_something None => nothing_to_do } This looks awfully a lot like if (something == null) { nothing_to_do } else { do_something } It might look more pleasant, but it doesn't "solve" anything, only shifts it in a d…

And you can write sth.unwrap() in Rust, and then it panics when it is null. Kotlin solves it much better. sth?.do_something() ?: nothing_to_do

Panicing is the right thing to do: fail-fast is much better than silently continuing in an invalid state. If the None state is valid then don't call unwrap() (which you should almost never use, because if None was not a valid state then why were you using an Option in the first place?), call a function that lets you handle both cases, e.g. unwrap_or.

Re: New Features in Java 14

#60

Earlier quoted context omitted.

No that's not the key difference, because you can just call `unwrap()` and forget about it, which is effectively the same footgun as other languages. The key difference is that now the type system can tell you the truth. In other languages when you have a reference to a type T, null is considered a valid T but you cannot treat it as one or everything blows up. Meanwhile in rust when you have a reference to T, you don…

> No that's not the key difference, because you can just call `unwrap()` and forget about it, which is effectively the same footgun as other languages. Are you sure? Each line of Java or Javascript can be equivalent to multiple `unwrap()` calls. You can't see them because the compiler is generating ([0]) them but they are there and there are many hundreds of thousands (or maybe even millions including dependencies) o…

Please do not quote posts out of context in order to make your argument seem stronger.

> Please respond to the strongest plausible interpretation of what someone says, not a weaker one that's easier to criticize. Assume good faith.

I am well aware of the issues in other popular languages. You and I agree that there is an implicit `unwrap()` call in each dereference operation.

The post I was responding to claimed that in Rust you cannot leave null/None values unhandled. This is false because `unwrap()` exists and more importantly is in fairly common use.

The distinction is not whether you can (at your own peril of course) assume a value is not null. Rust lets you do that.

As you point out however, it does force you to be more explicit. Why is that? It's because the concept of `None` is not hidden from the type system.

The reason that your Java examples work that way is not because `unwrap()` is implicit, it's because the type system doesn't know about nulls in the first place.

Post reply on HN