The lambdas are the new hotness that everyone is aware of. But the work done on streams is almost equally impressive.
There are several other small additions and reductions in pain that, when taken as a whole, make this update significant. For example, we finally will have a native JodaTime-like replacement for Calendar, Date, and the supporting utilities. I've long considered the need to enforce external thread safety on DateFormatters to be one of the silliest design failures in Java.
Disclosure: this summary was written by a colleague of mine.
- Getters and setters, C# style. That is, instead of
private int foo;
public int getFoo() { return foo; }
public void setFoo(int value) { foo = value; }
write this: public int Foo { get; set; }
which is both easier to write and makes code more readable and understandable.- Mandatory exception declarations in methods. I still don't understand why this is necessary. It ends up either leading to stupid errors (see the following example from the article)
void appendAll(Iterable<String> values, Appendable out)
throws IOException { // doesn't help with the error
values.forEach(s -> {
out.append(s); // error: can't throw IOException here
// Consumer.accept(T) doesn't allow it
});
}
, or to lots of methods just throwing Exception (bad practice, I know, but it's easy to fall in), or to useless empty try-catch on methods that won't throw an exception (because you've checked it) and don't want to add the throw declaration.- Modifying external variables in a lambda expression. Just as everyone is used to in Javascript, Ruby, C#... It's pretty useful, even more when you're using lamdbas for common operations such as forEach.
- Operator overloading. When you're using data classes (for example, models from a database) where different instances actually point to the same object, overriding == it's more comfortable than foo.equals(bar). Also, the downside of using .equals is that, if foo is null, you will end up with a nice NullPointerException out of nowhere.
- Events! I'm amazed how easy is to do events in C# versus how hard (and bloated) in Java. Take this as an example: http://scatteredcode.wordpress.com/2011/11/24/from-c-to-java...
- Pass by reference. Just as if you were passing a pointer in C. I find it surprising how few languages implement this feature, which is pretty useful...
And I'm sure I'm missing something...
Edit: added three bullet points.
I just stopped using getters and setters all together unless I have a real use for them. The most common reasons are: because they are required by some third party library or they are the external interface for whatever the module of code is doing. For all internal classes, if the field needs external access, just make it public.
Most of the arguments I hear for using getters and setters are the result of the tendency in the Java world to over engineer everything. e.g. "What if you want to change the internal name in 8 months? or add validation years from now? or add some logic to the getter? (ignoring the fact that would no longer make it much of a 'getter')"
The only argument that holds water with me for using getters/setters everywhere, because it is actually painful, is mocking field values, but there are ways around that and the trade off in code readability with public fields is well worth it.
public string Field { get; set;}
to public string field;
I felt I had to reply to this comment to discourage this practice for a couple of reasons:1) By convention anyone reading your code will think this is very strange, and it will force them to spend additional time reading your code to understand why you are breaking such a strong convention.
2) Using properties really will make your life easier when you need to track down a state change in your program. Detecting a state change on a public setter is a lot easier than detecting state change on a public field.
3) In C#, at least, using public fields where you should be using public properties will make creating an interface on existing code significantly more difficult - as interfaces can only define public properties, and not fields.
In short please don't do this. It's really bad practice just to save a couple extra characters, and if I inherit your code someday I'll probably want to strangle you.
I used to write classes and then add fields and auto generate getters/setters.
Now I don't, I just make all the state private and if I find myself wanting a getter/setter I ask myself why.
Too much use of getters/setters is just reinventing the problem that private state was meant to avoid.
So for example rather than:
if(email.getState() == EmailState.SENT) {
I have:
if(email.wasItSent()) {
I definitely would like to see a similar feature in java. In the meantime, I am pleased with the features in java 8 after being underwhelmed by java 7's new features.
It's already going to get lambdas. Add some shortcuts for getters and setters (Lombok-style, maybe) and collections literals, then you get surprisingly close to Groovy (and JPA @Entity classes will become 1/6 of their sizes). And just like Strings have special + and +=, Bignums could have some compiler help (as they already do in JSP EL).
It will still be behind C#, but not by much. At that point I could agree that Java and C# have different philosophies and Java will never get true operator overloading, but it doesn't matter much if the most important use cases are covered.
Agreed on assuming the trivial getters and setters if they are not expressly defined. That would be nice.
As for modifying variables in lambdas, you need to have a final reference available, meaning you can't modify a primitive. However, you can accomplish roughly the same thing by using a final reference to a boxed (or if parallel, atomic) primitive.
- Getters and setters are bad design. In clean object-oriented code, the internal state of a class is not exposed to the outside. Thus, getters and setters should not be encouraged.
- Exceptions: yes, it would be nice to be able to throw checked exceptions in that example. But the rule that they need to be declared is one of the basic design decisions Java has taken with the intention of always forcing the programmer to handle them. It won't change. (You can still fall back to unchecked exceptions if necessary.)
- Modifying external variables: can be done with a work-around, e.g. "final int[] x" to have a modifiable int. Not sure why that is the case though.
- Operator overloading: considered bad practice for high-reliability code. Generally, Java favors explicit statements in order to prevent mistakes.
- Events: some of the listener stuff in the example could be moved to a library, making it smaller. But still a missing feature in Java.
- Pass by reference: this is normally used as a workaround to create methods with multiple return values. In Java, one could again use the wrapping-array-workaround instead as in the external variables point. I'd love to be have methods with multiple return values in Java.
Considered by whom?
The example gjulianm gave, where == is safe if nulls are flying around but calling .equals() on a null expression results in an exception, seems a clear counterexample.
I’d also argue that if your code is mathematical in nature, it is both quicker and more reliable to write, review, and maintain concise, mathematically natural syntax like a+b*c than verbose alternatives like a.add(b.multiply(c)).
In clean object-oriented code, the internal state of a class is not exposed to the outside.
One could argue clean OO code also follows the uniform access principle. I guess everything being a method is uniform. In which case why are public fields allowed?The verboseness of writing getters and setters doesn't realistically stop people from writing them. It doesn't educate them as to why writing lots of them might be a bad idea. It doesn't suggest a better design. It just makes code harder to read and people put up with it, occasionally grumbling to themselves.
It's this kind of philosophy that's prevented java from having a terse lambda syntax for so many years, which in turn has left it out in the cold as API tastes have changed.
So then you don't write getters and setters for that stuff in C#. I don't get your point here.
How can this be a general statement? Some state can be internal, some can be public. Java supports both. Or how do you suggest that state should be accessed? Because I don't understand how a system can work if no state is shared between objects.
Damn, so why are they encouraged in Java? 11 out of 10 frameworks insist that you write getters/setters so properties can be accessed from outside.
Java designers need to get more practical. If getters/setters are unavoidable, I'd better have them without so much boilerplate in my code.
No need to go the C# way. Just enough to avoid repeating the name and type 3+ times each would be great.
Rather than write all that boilerplate, most people won't actually write exception-safe code across the board, which allows strange state-dependent failures to creep into the system.
The unexpectedly-unwound-stack problems that Java's compiler is highlighting are still there, just hidden.
Better, in my mind, to not use unchecked exceptions at all.
http://projectlombok.org/features/GetterSetter.html
(There's also a lombok-pg project that offers more extensions.)
* Every team member must install the eclipse plugin (which, if you already have any eclipse vm args set, also requires you to add a couple of extra arguments).
* No reasonable way to add javadoc comments to getters and setters without explicitly writing those getters and setters (kind of defeating the purpose of lombok).
* Sonar (which we use for static code analysis) will now report those private fields as a major warning as it thinks they are unused private fields. You can make those warning go away by adding //NOSONAR on each line, but yeah..
* Relies on internal java APIs. While the authors seem to be quite good and stay on top of things, I fear that this is still inviting issues down the road.
We felt that the cons outweighed the pros in this case, despite some of the beauty in lombok.
Disclaimer: I am a colleague of the author of the linked article.
If you _really_ have to mutate those variables then put them into a final array, and alter the entries in that, the same can be used if you need to do an effective pass by reference.
True that in typical chaos that reigns in code written by a disjointed group of people it ends up being Exceptions and RuntimeExceptions all over the place anyway. But why should disciplined people suffer?
Please leave my checked exceptions alone. I like then very much. I have not dealt with C#, but did with C++ and I prefer the Java way.
The arguments against checked exceptions that I have seen go along the lines of leaking data types from unrelated code layers. That's probably valid, but I have not experienced it. The rest seems like just whining about being forced to write code to handle errors, instead of letting things just happen.
OTOH, sometimes we need a "panic"(¹) function, and a main loop that catches everything and either communicates the error to the user, or restarts the whole thing. That's why unchecked exceptions can be useful too, especially since they makes it harder to ignore errors - who has the patience required to check every return value of printf in C?
(¹) No, I've never programmed in Go.
In Java, I use Lombok:
@Getter @Setter private Integer foobar;
>Checked exceptions
True, widely regarded as a mistake, but hard to get rid of now.
Sure, it's easier in C#, but there's no need to invent problems that doesn't have to be there.
The idea of doing a one-line parallel map-reduce that is
collection.stream().parallel().map(operation1).reduce(operation2);
is surprisingly cool imo. And the availability of streams across the collections framework allows that they can be used in routine programming. collection.parallel().map(operation1).reduce(operation2);Android's dalvik is based off of Apache Harmony, which doesn't appear to be updating anymore. Does this mean no Java 8 for Android/Dalvik? Seems like it would be a major issue if so.
I'd love to see them really shake things up in Android by, eg, going with NaCL/PNaCL (or even something like seccomp2, don't really care) to manage sandboxing and exposing an API framework (so apps can present common UI widgets) with a C API (regardless of what it is written in underneath) making it relatively easy to consume from any language. Write your Android app in Go, Python, Java, whatever you want, as long as it has API bindings! But I'm not holding my breath on that.
I just wonder how many years before there's adoption from the general Java community.
Java 8 seems to have borrowed a lot from Guava (Optional, Function, Predicate, Supplier etc.).
Extension methods as well as default methods on interfaces would have been nice.
The sad thing is that a large part of my Java programming will involve Android, and thus I will continue living in Java5/6 land, as will numerous libraries and large parts of the Java ecosystem.
I wonder when Google will address the future of Java on Android in a substantial way? Eventually it will not be tenable to stay on a 10 year old version of a language. I hope they will seriously consider either updating their supported syntax to be compatible with Java8 or introducing some other language into the Android SDK (Go go!).
Now I do program in Java 5/6 and it would be really sad if the language was still stuck in the 1.4 days.
So right now the thing I'm most interested in is actually the promise of better type inference. Anyone who has used a rich, type safe DSL like Hamcrest or Guava knows the pain of having to give so many type hints to the compiler, when the context provides all that the compiler should need.
It is always fun to watch other languages continue to implement features that bring them closer to lisp. I wonder how much longer it will be until every language is just a lisp dialect.
They are moving in the right direction but very slowly. It is impressive though that they have been able to still innovate without breaking backwards compatibility.
Indeed. The .NET IL compiler actually supports closures by generating a class with the lambda's method body as method on that class. That method takes in as parameters whatever outside variables need to be captured.
It also supports iterator continuations (e.g. "yield return") by generating an entire class which inherits off of IEnumerable and wraps your single function with all the necessary trappings to track the continuation state.
You can see this stuff by looking at C# assemblies in a free program called ILSpy[0]. Normally it'll reverse-engineer these compiler patterns, but if you uncheck all the "decompile" checkboxes in the options, it'll just straight-up translate the IL to C# and you can see the dirty tricks.
I'm convinced everytime I have to manually write the try catch clause for parse a kitten dies somewhere!
It's sort of ironic that the JVM, with it's limited Java-only bytecode has attracted so many languages, while the CLR, which is designed to handle multiple languages in an efficient manner, has relatively few.
But it occurred to me that even if they did so, a lot of people wouldn't trust them to continue to support the other platforms indefinitely. The only way around that would be for them to spin off the entire .NET division.
Microsoft being Microsoft, of course, they would never do any of this.
The way Scala (and probably other functional languages, with which i am not familiar) handle this is with a little bit of polymorphism. Using Java syntax, parsing a string into integer would return a Validation<Integer, Exception>, an abstract type which could be either a Failure<Exception> or Success<Integer>. This then exposes methods like ifSuccess(Consumer<Integer>) (it's called something less obvious in Scala, because that's how Scala works) and ifFailure(Consumer<Exception>), and various other useful things.
This seems a bit weird at first glance, but it makes it quite easy to deal specifically with either success or failure, or both, or to defer dealing with them until later (you can put a load of Validation objects in a set and worry about whether they're successful or failed later on). It also makes it impossible to ignore failure - there is no error code to forget to check, and no unchecked exception to forget to write a catch block for.
int res;
if int.TryParse(s, out res) { // OK } { else // not ok }
You certainly do not need an exception to deal with the simple case of "did this string parse into an int".Edit: A great alternative signature is to use Maybe/Option, so you get Some int or None.
match int.TryParse s with
| None -> ...
| Some i -> ... if(Int.CanParse(s))
{
i = Int.Parse(s);
// OK things.
}
else
{
// Not ok.
}
but it also be weird in Java because Parse throws and exception, so you'd have to either write an empty catch block or declare the method with a throw clause, event though it actually doesn't throw anything."List.add(otherList) <-- what does this do? Why, compared to operators, would a function name be any better than an operator? Mathematics are part of computer science, and denying basic operators for a reason like "because someone might misuse them" is like denying functions because someone may implement a sum() and call it lcm() (and then we're back to goto land). You're confusing a programmer's error (bad choice of a name/operator function) with a language feature. Just because people can write bad code it does not mean we should disallow them to write great code."
Honestly, it's about time the Java crowd stops with the mantra and starts thinking from themselves. Or at least, learn why the reason you hate operator overloading is fallacious.
I think it depends a lot on the languages. Operator overloading is easy and common in Python, but in my (limited) experience, it's used to create new classes which respond to existing operators with existing semantics, e.g. to make new number classes. For this, it's great. There's no particular reason the types built-in to the language should get special treatment for operators, as long as programmers can resist the temptation to be idiots.
Given these limitations, and the fact that most languages have relatively few built-in operators to choose from, I find that just operator overloading isn't enough. You really want the ability to define new operators as well. That's something Java (and C#, and C++, and many other languages) would really benefit from.
This is getting into blessing vs. curse territory, though. On the one hand, used well, a custom operator might enhance the benefits of allowing operator overloading in the first place. If your code is mathematical, you have an extended character set available, and you have good coding standards and keyboarding skills to match, then matching the operators/notation in the code to any related mathematical documentation has obvious advantages.
On the other hand, there are only so many obvious symbols available on most keyboards. Once those run out, you can resort to those extended characters, but they might not always be so unambiguous: most of us would recognise less-than-or-equal, but was that an empty set or just a slashed zero in the font Bill was using? The alternative is to start combining symbols, which again might make sense if say [[ ... ]] looks like whatever mathematical notation is standard in your field, but isn’t so great if you go all Haskell and define more-or-less every combination of three non-alphanumerical symbols in the universe to have some subtly different meaning... including from the same combination of symbols in the other library you’re using five lines later.
Without any restriction, except for a few basic ones.
multi infix:<plus>(Int $a, Int $b) {
return $a + $b;
}
multi infix:<plus>(Str $a, Str $b) {
return $a ~ $b;
}
say 10 plus 4;
# 14
say "foo" plus "bar";
# foobarFor me, one of the big wins of both Clojure and Scala is being able to handle maps, sequences, etc. conveniently.
Lambdas are what make operations on data structures convenient in Scala and Clojure, not saving a few characters on the handful of literals in your code.
I am actually quite opposed to the syntax sugar features like "getters/setters from C#", "events" and what not. Java the language is already large enough. IDEs do a decent job dealing with boilerplate code. Please, no new kludgy additions to the language.
Those people that need functional features could use Scala now. Jython is there for those not liking static typing.
Why don't we just leave Java alone?
Hopefully Nashorn will give http://ringojs.org a boost as well.
So, it sounds like that mean no closures? That's one of my favorite tools in c#.
(You would not be able to do stack allocation of locals in frames that contain lambdas (unless you could prove that the lambda does not escape).)
- An interface cannot have member variables.
Although it's probably a good idea not to do too much work - a factory method would be better for that.
It's ugly in terms of the UI but the infrastructure is there.
Twenty years for that one ; )
zomg. Another one debated at length through flamewars on Usenet and ##java. And now it's here. Feeling good : )