8 ms·
As a C# developer now experimenting with Java, I still miss some things even from Java 8. Probably some have technical reasons behind, but... - Getters and set
by gjulianm 14y ago
As a C# developer now experimenting with Java, I still miss some things even from Java 8. Probably some have technical reasons behind, but...
- 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-events/ 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.
- bhauer 14y agoAt least with respect to checked exceptions, my read of modern popular convention is simply to avoid using checked exceptions unless there is a very strong use-case. In our own code, we have transitioned to using predominantly unchecked exceptions with no decrease in code quality that we have yet perceived. 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.
- rallison 14y agoThe boilerplate getters and setters in java do get old very quickly, and C#'s properties handle this nicely. On the surface, it seems like something minor and superficial, but when you are seeing the unnecessary verbosity of getters and setters day in and day out, it becomes frustrating not to have something like C#'s properties. 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.
- rdtsc 14y agothat is why I think java IDEs became so popular, they are almost a part of the language because they do some of this lower level refactoring for you
- PySlice 14y agoMe too. However, I don't think Java needs much to become an appealing language (for language-geeks). 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.
- volkadav 14y agoYou might like project lombok re: getters and setters. It has a feature that implements this using annotations. True, this is an additional external dependency for a project when it'd be nice if it was a core language feature, but as external deps go it isn't a killer one -- the library is not huge and doesn't spiderweb out to a bunch of other deps. http://projectlombok.org/features/GetterSetter.html http://projectlombok.org/features/GetterSetter.html (There's also a lombok-pg project that offers more extensions.)
- rallison 14y agoWe actually evaluated Lombok for this reason (and others), and eventually decided against continuing with it for a few reasons: * 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.
- aardvark179 14y agoGive the desire for lambdas to enable more simple concurrent programming, and the added complexity mutating the external variables in the implementation, I think they made the right choice. 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.
- spullara 14y agoThe Atomic* classes are also good choices.
- pifflesnort 14y agoThe checked exception concern leaves me scratching my head. Without checked exceptions, the forEach implementation has no way to gaurentee that the lamba won't throw, and has to be exception-safe at all times -- in the case of stateful code, this can generate a lot of boilerplate. 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.
- rictic 14y agoIt's a pain that operations can fail, but handling state when they do fail is a problem that exists whether your exceptions are checked or unchecked. Forcing all exceptions to be checked doesn't seem to help with the problem, but would rather cause a lot of code to simply declare that it throws Exception, rather than listing off all possible exception types that it doesn't handle (e.g. out of memory, SIGTERM received, SIGINT received, etc)
- pifflesnort 14y agoFailure types are generally classifiable; part of clean module design is in classifying your exceptions in a way that allows you to declare that a more or less granular exception types are thrown based on the actual failure mode(s) possible from your code. The 'throws Exception' behavior only emerges when people don't take the time to define how code can fail, which is something that is necessary to fully define an interface, regardless of whether or not you have language support for declaring failure modes.
- pswenson 14y agoGiven that most code degrades into either wrapping checked exceptions into runtime exceptions or most methods having "throws Exception" declared...I think it's safe to say Checked Exceptions don't work well in the real world. There is a reason no other language created in computer history uses them.
- nollidge 14y agoAnd the two things I notice Java has that C# does not (static methods on Interfaces, and functional interfaces) have completely viable alternatives in C# (extension methods, and Action/Func, respectively). This really smacks of catch-up.
- foohbarbaz 14y agoSpeaking of C#, it's missing one critical for me feature: it does not run on the platforms I am (or my employer is) using. There are some attempts like Mono, but in practical sense it does not. That is sort of a no go right there.
- edwinnathaniel 14y agoYou can tweak JVM but you can't tweak CLR. While it's not Java vs C# the language but the VM/Runtime and the language is almost tight together (Mono is an exception).
- Hermel 14y agoI don't think there are technical reasons behind, but rather philosophical ones. - 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.
- nollidge 14y ago> In clean object-oriented code, the internal state of a class is not exposed to the outside. So then you don't write getters and setters for that stuff in C#. I don't get your point here.
- Hermel 14y agoThe point is that a language should not add features that make it easier to write bad code.
- evanspa 14y agoGetters / Setters don't automatically mean that the internal state of an object is exposed. For example, an object may internally have mutable linked-list of something, but a Getter that returns an array (immutable) of immutable members. What is the alternative to Getters / Setters (or, properties, which is basically just syntactic sugar) in an OO language?
- crazyowl 14y agoAbout events. One could argue that the example code is really made to look bad in the Java example. Sure, it's easier in C#, but there's no need to invent problems that doesn't have to be there.
- mbell 14y ago> Getters and setters, C# style. That is, instead of 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.
- mercurial 14y agoWith dependency injection frameworks, you don't really need setters anyway. I add getters only as needed, unless it's a public API.
- edwinnathaniel 14y ago2 things: 3rd-party API that only works on "beans" and thin object (not your Services or DAOs that use DI heavily).
- mercurial 14y agoYou can't do much with 3rd-party APIs. For thin objects, a best practice is to keep them immutable by having only getters, but then you generally end up with Builder boilerplate.
- jiggy2011 14y agoI think it's partly a defensive tactic to stop others playing fast and loose with your object state. 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()) {
- mercurial 14y agoWhat I'm missing the most from C# is actually the "var" keyword.
- iSnow 14y ago>- Getters and setters, C# style. 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.
- foohbarbaz 14y agoI like my checked exceptions. I like knowing what might go wrong with a call and I like being forced by compiler to handle it. 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.
- PySlice 14y agoTo me, checked exceptions seem to be a second return value: you need to catch it or declare that you are going to pass it to the caller. In this sense, it is enforced by the compiler even more rigidly than the return values themselves. They can be useful. 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.