r/java • u/lukaseder • Sep 19 '18
JEP draft: Concise Method Bodies
http://openjdk.java.net/jeps/82094345
u/lukaseder Sep 20 '18 edited Sep 20 '18
I couldn't resist. And the answer I got is quite promising, in fact!
1
u/hellectronic Sep 21 '18
nested "named lamdas"/methods would be really nice !
1
u/lukaseder Sep 21 '18
Absolutely. I really like Brian Goetz's answer to this, in particular that there's a lot of nesting that is currently quite clumsy for arcane reasons, which could be cleaned up. I totally agree that this should be done in a separate project, though.
1
5
u/_INTER_ Sep 20 '18
I always thought that Java's code readability code was rather nice. Mainly because the structure of classes, methods, many control structures always remain the same visually. You can usually scan a class easily without much interruption. It's modifier, return type / void method name, parameters, brace, body, brace.
Now this feature completely destroys that. It adds new syntax without much gain. The languages keeps on adding and bloating, like C++ and C#.
2
u/lukaseder Sep 20 '18
If that's what you think, then you will like the idea that soon empty class bodies can be replaced by semi colons. Instead of:
class A {}Just write
class A;2
2
u/Bobby_Bonsaimind Sep 21 '18
Give me a moment, I'll try to figure out if I could care less... ... ...nope, sorry.
0
u/_INTER_ Sep 20 '18
what, when, why?
2
u/lukaseder Sep 20 '18
See e.g. http://cr.openjdk.java.net/~briangoetz/amber/datum.html
interface Node { } abstract record BinaryOpNode(Node left, Node right) implements Node; record PlusNode(Node left, Node right) extends BinaryOperatorNode(left, right); record MulNode(Node left, Node right) extends BinaryOperatorNode(left, right); record IntNode(int constant) implements Node;And also: http://hg.openjdk.java.net/amber/amber/rev/727ca44aff68, https://twitter.com/jeffreymaxwell/status/984079813941125120
I've never seen a formal specification, though. Seems like a simple "under the hood" change to the JLS
7
Sep 20 '18
Okay, C# programmer here; please don't implement this crap. C# has all kinds of 'neat' features that have made the language very nasty to work with and is driving some people away (like myself). You think it's a great feature until another developer bastardizes the crap of of them and then shoves it all together. Remember that, where we can choose to or not to use a feature, that isn't true about the code you have to maintain or the devs you have to work with. I am looking to switch to Java for its elegance in its simplicity. But if they decide to start adopting the features of C#, I'll go somewhere else.
2
u/jonhanson Sep 20 '18
Preventing mis-use by idiots isn't generally a good guiding criteria for language design.
4
Sep 20 '18 edited Sep 20 '18
No it isn't. But coming from C#, this feature is not one that yields more readable or maintainable code. Once you start to open the flood gates then you get all kinds of crap...take a look at what they've done and have proposed with C#. I'm not saying that all features are bad but I am saying that we need to be extremely cautious about what gets added. It seems that languages are too focused on 'advancing' just to not be stale and forgetting the purpose of what the language was designed to do and the problems it was designed to solve. I don't want a language that is everything to everyone. I don't want my imperative, OO language turning into a landfill of pointless buzzwords/syntax sugar and littered with so much functional language idioms that it's forgotten what audience it is trying to serve. If I wanted a functional language, I would use one. I choose to use Java because of what it is and what it isn't.
1
3
u/randgalt Sep 20 '18
public static Foo make(int a, int b, int c) = Foo::new;
This is particularly nice
1
Sep 20 '18
Haven't read the article yet, this can be useful for a "quick and dirty" but extendable factory method, making the constructor protected/private, isn't it?
6
u/daniu Sep 19 '18 edited Sep 19 '18
Sure, getters and setters are somewhat shorter by this, but if you're annoyed by those and not using Lombok I can only assume it's due to your company policy. I can't see how non-trivial methods gain a lot by being able to remove the braces surrounding the body. Not that I'm against the introduction of this feature, it does make it more consistent with the lambda stuff, but I don't see it as a huge improvement.
class MyList<T> implements List<T> { private List<T> aList; public int size() = aList::size; public T get(int index) = aList::get; ... }
That's actually kind of common - delegating the implementation of an interface to a member. But it's not really that much less boilerplate if you still have to delegate on a method level - there could be something like
class DelegatingList<T> implements List<T> {
// 'delegate' meaning all non-implemented List methods are created for this class and delegated to aList
private delegate List<T> aList;
public void add(T item) {
// still able to implement specific methods of the interface yourself
aList.add(item);
}
}
5
u/lukaseder Sep 19 '18
class DelegatingList<U, T extends DelegatingList<U, T> & List<U>> implements List<U> { private delegate T aList; }Now what?
3
u/daniu Sep 19 '18
Now you've made the point about how actual language design isn't trivial ;)
I was merely bringing it up as something in the vein of the concept of the JEP draft I stumble upon from time to time.
2
u/lukaseder Sep 20 '18
And I merely wanted to nerd snipe you, hoping you'd spend a few hours finding the solution ;-)
1
1
u/yawkat Sep 20 '18
This sort of delegation has all the problems normal extension has, except for being able to swap out impl. Don't do it, even though lombok allows you to.
I wrote on the problems with extending like that a while ago: https://javachannel.org/posts/how-not-to-extend-standard-collection-classes/ - the proper solution is to just exhaustively implement abstractlist.
2
u/jhg023123 Sep 19 '18
Why both = and ->?
10
u/dpash Sep 19 '18
Because they do different things.
=is saying that the method is the same as the method handle, and will return what ever the original method returns.->would return a method handle (and ignore the parameter).public boolean isEmpty(String s) = String::isEmpty; public Predicate<String> isEmpty(String s) -> String::isEmpty;Does that make sense?
2
0
u/duhace Sep 20 '18
the second example should do like scala instead
//Predicate[String] == String => Boolean in scala def isEmpty: String => Boolean = String.isEmpty _i'm not sure why the parameter
sis even there if it's being ignored1
u/dpash Sep 20 '18
Because using
->is the wrong thing to use in that situation.1
u/duhace Sep 20 '18
I'm not sure I'm getting the difference then. In my code, i'm doing the equivalent of returning the method handle as you said, not using the isEmpty method as the implementation like 1.
1
u/dpash Sep 20 '18
Of my two examples, the second is almost certainly a mistake, and you'd normally never write that. In particular because it ignores the parameter, making the method confusing for any users.
1
u/duhace Sep 20 '18
would you post what you would write to clear things up for me? thanks in advance
1
u/lukaseder Sep 20 '18
Important to note also that specific syntax is probably not set in stone at this moment.
3
u/coderguyagb Sep 20 '18
More unmaintainable crap. Don't do this. It's hard enough to read the legacy codebases I see every day that some 'Streamify / Kotlin all the things' developer has been near. /rant
1
u/donte9181 Sep 21 '18
Shorter != better.
This feels like it's solving a non-problem. Not once have I ever felt that I was unable to complete a project on time because I had to type some curly braces for trivial methods. On top of that, I don't even type them - my IDE does, so I actually type the same number of characters the "long way" today as I would in the "short way" described here, so it doesn't affect my coding velocity at all.
What it does do is make code significantly harder to read/understand because now you're overloading the arrow/method-reference notation. Currently it's limited to method invocation but now you're suggesting that it could be used while defining methods, too. It requires extra (unnecessary) brain cycles to figure out where the method definition ends and what it's actually doing - especially in the examples w/ multiple arguments.
It's unnecessary complexity that adds to the amount of mental cycles required to consume existing Java code - which is 90% of our jobs. This will make reading Java code harder while having 0 effect on our ability to write code efficiently.
This seems like one of those things someone suggested because they saw something similar in another language and thought it was cool, but will only make Java worse. Keep Java simple. Keep Java readable. Let your IDE write the boilerplate for you.
1
u/lukaseder Sep 21 '18
So, you don't use lambdas but keep writing anonymous classes?
Stream.of(1, 2, 3) .filter(new Predicate<Integer>() { @Override public boolean test(Integer i) { return i % 2 == 0; } }) .map(new Function<Integer, String>() { @Override public String apply(Integer i) { return i.toString(); } }) .collect(toList());1
u/donte9181 Sep 21 '18
I do, but that is not even close to an equivalent comparison. Anonymous inner classes make it really hard to find the code that actually provides the meaning as to "what is this code trying to do". You have to sift through multiple lines of annotations and additional method definitions just to get to the "what does this do" whereas lambdas are much more direct.
This is not the case with the "problem" that this draft attempts to solve:
public String getName() { return name; } public String getName() -> name;There's no scouring the code for the actual logic of the first function. Your not sifting through extra crap the compiler needs to stay type safe and avoid warnings like you do with inner classes. It's just replacing curly braces with arrow notation or double colons. You basically got to get rid of the word 'return'. That's not that big of a win to me given that it will increase the mental gymnastics required to read Java code.
It's not better - it's just different - and we don't get anything interesting as a result of having yet another way to define functions.
If the community wants to take a swag at first-class properties like C# and the syntax is something like this, I'm all ears. But this just seems like trying to convince people that the barrier between them and great code is a couple of curly braces.
0
1
Sep 23 '18
Iād be happier if they introduced Case classes like those in Scala. I tend to use Lombok/Immutables to accomplish the same thing.
1
u/pavi2410 Sep 24 '18
Java will soon become Kotlin-ish with the 'switch expression' proposed for Java 12 which I love to see it coming. But, this would only matter me if newer Java versions come to the Android world. š£
1
10
u/dpash Sep 19 '18 edited Sep 19 '18
While this will make getters much concise, it won't help much with setters,
because they're a statement.would become
I'm curious to see how their introduction in C# changed the language. My initial feeling is that the usefulness of this change might be of limited scope, if only because only the most basic of methods would benefit from this.
Edit: I originally had the following setter
but it was pointed out I had needless braces.