Michael has posted 1 posts at DZone. View Full User Profile

When Should You Jump? JSR 308. That's When.

05.08.2008
| 10371 views |
  • submit to reddit

One of the frequently asked questions at the No Fluff, Just Stuff expert panels boils down to, "When should I get off the Java train?" There may be good money out there for the last living COBOL programmer, but most of the Java developers we see still have a lot of years left in their careers, too many to plan on riding Java off into it's sunset.

Most of the panelists talk about the long future ahead of Java the Platform, no matter what happens with Java the Language. Reasonable. I also think that a young developer's best bet is to stick with the Boy Scout motto: Be Prepared. Keep learning new languages and new programming paradigms. Work in many different domains, styles, and architectures. That way, no matter what the future brings, the prepared developer can jump from one train to the next.

After today, I think I need to revise my usual answer.

When should a Java developer jump to a new language? Right after JSR 308 becomes part of the language.

Beware: this stuff is like Cthulu rising from the vasty deep. There's an internal logic here, but if you're not mentally prepared, it could strip away your sanity like a chill wind across a foggy moor. I promise that's the last hypergolic metaphor. Besides, that was another post.

JSR 308 aims to bring Java a more precise type system, and to make the type system arbitrarily extensible. I'll admit that I had no idea what that meant, either. Fortunately, presenter and MIT Associate Professor Michael Ernst gave us several examples to consider.

The expert group sees two problems that need to be addressed.

The first problem is a syntactic limitation with annotations today: they can only be applied to type declarations. So, for example, we can say:

@NonNull List<String> strings;

If the right annotation processor is loaded, this tells the compiler that strings will never be null. The compiler can then help us enforce that by warning on any assignment that could result in strings taking on a null value.

Today, however, we cannot say:

@NonNull List<@NonNull String> strings;

This would mean that the variable strings will never take a null value, and that no list element it contains will be null.

Consider another example:

@NonEmpty List<@NonNull String> strings = ...;

This is a list whose elements may not be null. The list itself will not be empty. The compiler---more specifically, an annotation processor used by the compiler---will help enforce this.

They would also add the ability to annotate method receivers:

void marshal(@Readonly Object jaxbElement, @Mutable Writer writer) @Readonly { ... }

This tells the type system that jaxbElement will not be changed inside the method, that writer will be changed, and that executing marshal will not change the receiving object itself.

Presumably, to enforce that final constraint, marshal would only be permitted to call other methods that the compiler could verify as consistent with @Readonly. In other words, applying @Readonly to one method will start to percolate through into other methods it calls.

The second problem the expert group addresses is more about semantics than syntax. The compiler keeps you from making obvious errors like:

int i = "JSR 308";

But, it doesn't prevent you from calling getValue().toString() when getValue() could return null. More generally, there's no way to tell the compiler that a variable is not null, immutable, interned, or tainted.

Their solution is to add a pluggable type system to the Java compiler. You would be able to annotate types (both at declaration and at usage) with arbitrary type qualifiers. These would be statically carried through compilation and made available to pluggable processors. Ernst showed us an example of a processor that can check and enforce not-null semantics. (Available for download from the link above.) In a sample source code base (of approximately 5,000 LOC) the team added 35 not-null annotations and suppressed 4 warnings to uncover 8 latent NullPointerException bugs.

Significantly, Findbugs, Jlint, and PMD all missed those errors, because none of them include an inferencer that could trace all usages of the annotated types.

That all sounds good, right? Put the compiler to work. Let it do the tedious work tracing the extended semantics and checking them against the source code.

Why the Lovecraftian gibbering, then?

Every language has a complexity budget. Java blew through it with generics in Java 5. Now, seriously, take another look at this:

@NotEmpty List<@NonNull String> strings = new ArrayList<@NonNull String>();

Does that even look like Java? That complexity budget is just a dim smudge in our rear-view mirror here. We're so busy keeping the compiler happy here, we'll completely forget what our actual project it.

All this is coming at exactly the worst possible time for Java the Language. The community is really, really excited about dynamic languages now. Instead of those contortions, we could just say:

var strings = ["one", "two"];

Now seriously, which one would you rather write? True, the dynamic version doesn't let me enlist the compiler's aid for enforcement. True, I do need many more unit tests with the dynamic code. Still, I'd prefer that "low ceremony" approach to the mouthful of formalism above.

So, getting back to that mainstream Java developer... it looks like there are only two choices: more dynamic or more static. More formal and strict, or more loosey-goosey and terse. JSR 308 will absolutely accelerate this polarization.

And, by the way, in case you were thinking that Java the Language might start to follow the community move toward dynamic languages, Alex Buckley, Sun's spec lead for the Java language, gave us the answer today.

He said, "Don't look for any 'var' keywords in Java."

Published at DZone with permission of its author, Michael Nygard.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

James Imber replied on Thu, 2008/05/08 - 3:34am

Personally, I don't use annotations at all. I guess that I consider it already as unneeded extension.

Johan Compagner replied on Thu, 2008/05/08 - 4:16am

we see it then really different

 i prefer this 

@NotEmpty List<@NonNull String> strings = new ArrayList<@NonNull String>(); 

 above this

var strings = ["one", "two"]; 

 

and not by a small margin but by a large large large margin

I hate the way it seems to go, why that completely stupic dynamic langagues are so hot, i have no idea

they can break at any point in any time

If i had to maintain a large 100.00+ LOC project that is all dynamic. i would be horrified.. reading that code would really suck.. Where are the Call Hierarchy where does it start, what calls what, what are the params.

People make mistakes that will also be the case in 10 years..what ever the compiler can catch the better it is.

 

Ok what java should get is method and field pointers (dont talk about reflection here but instance fields and methods) in the core language.. Because that is one thing i like about about dynamic languages. That you just can give a method pointer to another method..  The api will be a bit verbose but IDE's will solve that.. You dont have to type everything. 

Ewald Dieser replied on Thu, 2008/05/08 - 5:01am

What's the point? If you don't like the new annotations proposed in JSR 308 just don't use them. They are created for people who need them. No one forces you to use annotations at all.

There is no language, that can make every one happy. Java's strength is it's type safety, that's what people can rely on. If you want a dynamic language go on and use one. I don't even understand the connection between JSR 308 and your wish to have a var keyword in Java. The one can improve type safety and you wish to abolish it.

I like to drive a safe car, I need airbags, ESP, ABS and all the other stuff. But if you want two wheels and like bugs between your teeth then a motorcycle is the right vehicle for you. You cannot have both. Now that's a stupid comparison!

Cosmin Marginean replied on Thu, 2008/05/08 - 8:10am

Oh boy. Why? For the love of god. Is this what we need? A language/platform that allows a monkey to code? If you don't want to read the docs before using an API or for some reason you cannot focus or be sober when you code, I think IT might not be the best option for you.

 @Ewald Dieser - I think your comparison is not that accurate. I think more likely would be:

a)  I want a car with auto-pilot that allows me to "drive" drunk

or

b) i want to be able to drive a car and be aware of the things that I am doing with it and wha't happening at all times. That's why it's called drivers license, isn't it?

I don't think everyone should code. I really don't.  @Ewald: The problem is not that "you can choose not to use it", the problem is that if it's there, someone in your team will want to use it. And somtimes just because it's a buzz.

Ewald Dieser replied on Thu, 2008/05/08 - 8:58am in response to: Cosmin Marginean

[quote=cosmin.marginean]
I don't think everyone should code. I really don't. @Ewald: The problem is not that "you can choose not to use it", the problem is that if it's there, someone in your team will want to use it. And somtimes just because it's a buzz.
[/quote]


Exactly, that's the Problem. If we introduce some crazy/cool (==unsafe) dynamic features someone on your team will use them. But guess who will have to deal with the bugs? But on the other hand there is no problem if team members use JSR 308 annotations even if someone considers them ugly. I don't care if they are ugly as long as they are safe. I don't want to see runtime exceptions only because some developer had to use dynamic language features to save view lines of code.

Cosmin Marginean replied on Thu, 2008/05/08 - 9:15am in response to: Ewald Dieser

[quote=slomo][quote=cosmin.marginean]
I don't think everyone should code. I really don't. @Ewald: The problem is not that "you can choose not to use it", the problem is that if it's there, someone in your team will want to use it. And somtimes just because it's a buzz.
[/quote]


Exactly, that's the Problem. If we introduce some crazy/cool (==unsafe) dynamic features someone on your team will use them. But guess who will have to deal with the bugs? But on the other hand there is no problem if team members use JSR 308 annotations even if someone considers them ugly. I don't care if they are ugly as long as they are safe. I don't want to see runtime exceptions only because some developer had to use dynamic language features to save view lines of code. [/quote]

I was talking more about using this JSR vs. not using it. Not the JSR vs. dynamic language. I need things to be both "non-ugly" and safe. And I think that a programmer that actually has a brain and the abilites required by the job should be able to do it.

But as some people say,lazyness (almost always) prevails. In this case, "safe" means to me "i am to lazy to read the API or the docs, or etc, focus and think about what I am doing. The compiler should warn me if I made a business logic boo-boo". No. It shouldn't. We need to know what we are coding/driving.

But then again, that's just my opinion. I am pretty sure that from the business model point of view in IT, it pays off a lot more to have monkeys do a dirty job than scientist doing a cleaer job in less time with the same results.

Collin Fagan replied on Thu, 2008/05/08 - 9:41am

"i am to lazy to read the API or the docs, or etc, focus and think about what I am doing"

In the end the code is the ultimate documentation. These annotation attempt to express intent. Which is something that can be lost with documentation when it's not kept up to date, or missing. I agree that superior talent produces superior results, regardless of language. Still moving any runtime error to compile time speeds up the development process and saves the overhead of a bug that would otherwise be caught by testing.

Karim Elsayed replied on Fri, 2008/05/09 - 8:29am

said it once and will repeat it

 "Attention! Attention! The Java train is overloaded, please all dynamic language fans jump NOW!"

Gabriel Belingueres replied on Fri, 2008/05/09 - 8:48am

Here is my two cents:

As everybody may know, a project is composed of several economic variables: time, quality, cost, people, etc.

I think it remains to be tested in real projects if such an approach to coding really improves some of the project variables, while not significantly deteriorate others.

The first exercise somebody will try is reduce development time: If you want to improve time, the first common sense reasoning is "stick with what we know it works" meaning "don't use this new type annotation thing, shut up and work".

Now a good real world test is to do the opposite: introduce this new feature, and start counting some coding artifacts to roughly calculate the ROI that produce this new tool: the many tests you don't need to write, the many bugs you will not have (related to programming logic, not business logic at least), the reduced effort the people will do in learning the current code base, the amount of documentation that there is no need to write, etc.

I personally will welcome this feature as long it doesn't get in my way, meaning doesn't force me to use any of this in order to compile a class, be backwards compatible with existing written code, and a 3KB .class file doesn't end having 2MB size because of all this machinery!

Time will tell...

Jose Chavez replied on Fri, 2008/05/09 - 3:18pm

I don't understand why people want so many changes in the Java language. It works so well in the industry. If people want a more dynamic language, there's always Groovy.

Just my opinion.

cowwoc replied on Sun, 2008/05/11 - 1:29am

I'm no fan of dynamic languages but I think Michael makes a good point here. Every language has a complexity budget, and Java's Generics pushes us over the edge.

 

I would really like to see Java7 include further improvements to Generics to make them more readable and (if possible) add Reification. I'm all for adding new features into Java but only *after* we reduce the existing complexity. Please, fix Generics.

Jose Smith replied on Sun, 2008/05/11 - 9:56pm

Personally, I find "using" generic classes makes the code much easier to read and therefore... less complicated.

I rarely use annotations. Even using @Override makes cringe (really wish we had C#'s syntax for that). But as a junior developer, I think using @NonEmpty, @NonNull, etc. would definitely improve the quality of my code.

Is there any reason why this:

@NotEmpty List<@NonNull String> strings = new ArrayList<@NonNull String>(); 

 

Cannot be shortened to this:

@NotEmpty List<@NonNull String> strings = new ArrayList<>(); 

...if it's initialized on the same line that it's declared?

cowwoc replied on Sun, 2008/05/11 - 10:03pm

Part of the problem is that @NonNull should be the default. It is used extremely frequently (more often than not) in ways that @NotEmpty would not.

 

I can definitely see the value of @NonNull (enabled by default) but I see less value in @NotEmpty. Ideally we want to define @Nullable instead of @NotNull.

 

Java's biggest problem is backwards compatibility. I fully understand the need for binary compatibility, but source-code compatibility doesn't seem nearly as important to me, especially when it prevents @NotNull from become the default.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.