The Artima Developer Community
Sponsored Link

Weblogs Forum
Have Generics Killed Java?

62 replies on 5 pages. Most recent reply: Aug 8, 2010 3:43 PM by Eric Armstrong

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 62 replies on 5 pages [ « | 1 2 3 4 5 | » ]
Fire Mage

Posts: 3
Nickname: firemage
Registered: Jul, 2010

Re: Have Generics Killed Java? Posted: Jul 22, 2010 5:04 AM
Reply to this message Reply
Advertisement
> Where does it do that so far? Since when is introducing
> first-class anonymous functions "cater[ing] to the dynamic
> community" at all, let alone too much?

Well there's autoboxing, as I said. Then there's the enhanced for loop (convenient, yet also another redundant way of doing things). Then there's the new feature you mentioned:

> strings.sort().each( { s -> out.println( s ); } );

How do I know what s is? What is "->"? A new operator? Like autoboxing, this line of code looks like Java doing magic behind your back again for "convenience". What is wrong with using a for loop?

for (String s : strings.sort()){
out.println(s);
}

It even has the same number of characters!
Do we have to keep adding ever more ways of doing the same thing just so that it looks more snappy? To me, this is Java catering to the dynamic community.


> > And this is the point. Autoboxing fools you into
> thinking
> > that 12 and "new Integer(12)" are the same
>
> Which they should be.
> As far as I am concerned there is no reason for
> having both int and Integer, everything should just be
> `int` and Java does its boxing when needed (method call on
> an int or whatnot)

That's a subjective opinion. I understand the need for primitive types, which is mainly a performance consideration. Thanks to primitive types Java can be compared in performance to C++, something dynamic languages will probably never achieve. Also it makes it a lot easier and faster to work with native libraries, such as OpenGL and I/O operations. I don't think that everything has to be an object. But if there are primitive types, the distinction should be clear and they shouldn't start softening it up with "magic" such as autoboxing.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Have Generics Killed Java? Posted: Jul 22, 2010 6:52 AM
Reply to this message Reply
Eric-

To start: Java Generics suck but others are right to point out that this doesn't mean static typing is bad in general.

However, I've been working with generics in Java for something like 6 years or more (I started when they were in beta) and I've recently had a change of heart.

I've been playing around with Wicket (great framework BTW) for the last few years and I started with it before it was 'generified'. I recently made the plunge to move to the 1.4 version and started using generics. In this case, generics largely resolved the biggest cons of the framework.

In Wicket you have (your own) model objects behind all of your interface components. For simple things like labels, this is fairly straightforward. But when I want something like a table with a dynamically generated number of columns, I the structure of these models and their interactions becomes much more complicated. I would regularly become confused about which type of object to expect at which level. This could only be checked at runtime. It wasn't even the run-test cycle that was the problem: I would waste much more of time just trying to make sense of the multi-layered structures (something I've also experienced using Python.) Generics exposed this hidden structure and makes the code much more transparent and readable. This is especially true when I defined my own model types instead of using standard objects BTW.

So, yeah, generics are ugly and it's irritating to have to type (or copy) the same thing twice, thrice, etc. But once you accept that they aren't prefect, learn to use @SuppressWarnings("unchecked") safely, and learn not to overuse them, they are bearable. Not really a ringing endorsement, I know.

Cedric Beust

Posts: 140
Nickname: cbeust
Registered: Feb, 2004

Re: Have Generics Killed Java? Posted: Jul 22, 2010 7:02 AM
Reply to this message Reply
> I think that Java needs to be careful not to cater to the
> dynamic community too much

None of the additions coming in JDK 7 (whether they originated from Project Coin or elsewhere) do anything to weaken the statically typed nature of Java.

I'm not sure what gave you this idea.

Rodrigo B. de Oliveira

Posts: 2
Nickname: bamboo
Registered: Feb, 2005

Re: Have Generics Killed Java? Posted: Jul 22, 2010 7:38 AM
Reply to this message Reply
No.

Lack of decent type inference might have...

Michael Snell

Posts: 1
Nickname: snellm
Registered: Jul, 2010

Re: Have Generics Killed Java? Posted: Jul 22, 2010 7:43 AM
Reply to this message Reply
Even in Java 6, type inference can help:

public static <K, V> TreeMap<K, V> sortedMap(Map<K, V> map) {
  return new TreeMap<K, V>(map);
}

Morel Xavier

Posts: 73
Nickname: masklinn
Registered: Sep, 2005

Re: Have Generics Killed Java? Posted: Jul 22, 2010 7:52 AM
Reply to this message Reply
> > Where does it do that so far? Since when is introducing
> > first-class anonymous functions "cater[ing] to the
> dynamic
> > community" at all, let alone too much?
>
> Well there's autoboxing, as I said. Then there's the
> enhanced for loop (convenient, yet also another redundant
> way of doing things). Then there's the new feature you
> mentioned:
None of those has any relation with dynamically typed languages. Other than dynamically typed languages having them, maybe (hey, dynamically typed languages also have strings, integers and classes, should those be removed from Java?).

>
> > strings.sort().each( { s -> out.println( s ); } );
>
> How do I know what s is?
A parameter specification for a function.

> What is "->"? A new operator?
Probably. Or part of a structure, just as { isn't an operator but part of the block structure specification.

> Like autoboxing, this line of code looks like Java doing
> g magic behind your back again for "convenience".
Also like the garbage collector, classes definitions, objects initialization, .... Down with the garbage collector, you should malloc() your Java structures and pattern-emulate methods through function pointers and like it!

> What is wrong with using a for loop?
For loops are not composable or extendable, and you can't build your own flow-control structures on the structures behind a for loop.

> It even has the same number of characters!
> Do we have to keep adding ever more ways of doing the same
> thing just so that it looks more snappy?
I completely agree that this should be accompanied by the deprecation and removal of the old features.

> To me, this is Java catering to the dynamic community.
And you are completely wrong.

> That's a subjective opinion. I understand the need for
> primitive types, which is mainly a performance
> consideration.
Let performance considerations be managed by the compiler and the JIT.

> Thanks to primitive types Java can be
> compared in performance to C++, something dynamic
> languages will probably never achieve.
C# has similar performance and doesn't force userland to deal with that crap, it is all managed by the compiler and runtime. Likewise with Haskell which is generally able to infer whether it should compile down to boxed or unboxed type without user interaction.

> Also it makes it a
> lot easier and faster to work with native libraries, such
> as OpenGL and I/O operations.
That is complete and utter bull. Python has a much easier time interacting with native libraries via ctypes than Java ever had, even though it doesn't have primitive types. Hell, the mapping is utterly trivial, why would Java's native lib interaction layer have a harder time dealing with translating Java's Integer to C's int than it currently does translating Java's int to C's int?

> But if there are primitive
> types, the distinction should be clear and they shouldn't
> start softening it up with "magic" such as autoboxing.

There shouldn't be primitive types. Or the difference between boxed and unboxed type should not be visible to the user unless he really, really wants to know, anyway. It's an implementation detail, not a feature.

Morel Xavier

Posts: 73
Nickname: masklinn
Registered: Sep, 2005

Re: Have Generics Killed Java? Posted: Jul 22, 2010 7:54 AM
Reply to this message Reply
> Even in Java 6, type inference can help:
>
>
> public static <K, V> TreeMap<K, V> sortedMap(Map<K, V>
> map) {
>   return new TreeMap<K, V>(map);
> }
> 

Though to be fair, a C#-style local type inference in this case would have fairly limited benefits, the best you'd get is probably:

public static <K, V> TreeMap<K, V> sortedMap(Map<K, V> map) {
    return new TreeMap<>(map);
}

Tim Jansen

Posts: 1
Nickname: timjansen
Registered: Jul, 2010

Re: Have Generics Killed Java? Posted: Jul 22, 2010 8:13 AM
Reply to this message Reply
I would argue that in real life, the Ruby map example is often less readable than the Java example, depending on the context. The problem is that I don't know the types of the key and values in the 'map' returned by getInfo(). The Java code's generic annotations clearly state that the key is always a String, and thus I can use all the methods of a String on them. And I know that the value is only Object, and using any other methods would be an error.

But what is the type of the Ruby map's key? Unless I wrote the code myself, I would have to read the code that created the map (getInfo()) in order to find out the type.

So the Ruby snippet is only then more readable when getInfo() is more readable than the Java snippet. Because without any compiler-enforced contract, you can not just look at this short piece of code. You always need to look at the whole thing in order to understand it. Or, at least, you'd need to work with comments and/or assertions. That's why I don't like dynamic typing for larger projects (I wouldn't mind IDE-supported type inference though).

Kris Nuttycombe

Posts: 2
Nickname: nuttycom
Registered: Aug, 2008

Re: Have Generics Killed Java? Posted: Jul 22, 2010 8:28 AM
Reply to this message Reply
FireMage,

The power of the new functional constructs in Java lies not in the side-effecting higher-order functions (like each) but instead in those higher-order functions that behave like functions should - by returning results.

For example, take the task of finding the lengths of the top 3 longest strings in a list and see that this:

List<Integer> top3Lengths = strings.map({ s -> s.length() }).sort().drop(strings.length - 3);

is much superior to this:

List<Integer> strlengths = new ArrayList<>()
for (String s : strings) {
strlengths.add(s.length());
}
Collections.sort(strlengths)
List<Integer> top3Lengths = new ArrayList<>()
for (int i = strlengths.size() - 3; i < strlengths.size(); i++) {
top3lengths.add(strlengths.get(i));
}

In the second version, not only is it massively more verbose for the same operation, but you're depending upon the mutability of the List object.

You'll notice too that all of the operations in the first version are *composable* - instead of writing a recipe for how to mutate each intermediate list, you simply chain together a number of calls which may or may not produce an intermediate result. In this particular example you can't really take advantage of laziness (because of the sort) but in many many situations, it's not even necessary to evaluate the intermediate lists. Also, each of these operations can be defined for any sequence-like or iterable object.

Higher-order functions (ever used the Strategy pattern?) and function literals lead to more reusable, more composable code. Eliminating external iterators, such as are used in a for loop, allows new patterns to emerge that let you drastically reduce boilerplate and thus reduce errors.

Benjamin James

Posts: 7
Nickname: bmjames
Registered: Oct, 2009

Re: Have Generics Killed Java? Posted: Jul 22, 2010 8:35 AM
Reply to this message Reply
Generics were a major new language feature in a mature language which already had a clunky, restricted syntax. To use this feature requires yet more clunky syntax. I don't think generics killed Java, I think Java killed Java (or at least, irreversibly poisoned its own chances of flourishing in the future with unlucky backwards-compatibility problems). For people who for whatever reason have no choice but to continue using Java, generics are welcome.

Michael Goldman

Posts: 9
Nickname: keppla
Registered: Jul, 2009

Re: Have Generics Killed Java? Posted: Jul 22, 2010 9:08 AM
Reply to this message Reply
I would argue, the problem is not Generics, but the lack of tuple unpacking and the library.

Looking at
Map<String,Object> map = getInfo();
Map<String,Object> sortedMap = new TreeMap<String,Object>(map);

there seems to me no compelling reason the EntrySet could not have a "sorted" method, that returns an Iterable<Map.Entry<K,V>>, so it's a library thing we cannot write
for(Map.Entry<String, Object> e : getInfo().entrySet().sorted()) { ...

The next problem is, that for a intuitive usage, we dont want to think of key,value-pairs, but of two separate variables, a key, and a value.

In ruby, this is done via "tuple unpacking". Just try this:
{:one => 1, :two => 2 }.each do |pair|
puts pair.inspect
end

it reveals, that "each" passes a key,value-pair to the closure, just like java's Map.Entry<K,V>.
The big difference is "tuple unpacking", (i.e. the fact, that in ruby you can write a, b = 1, 2), which allows to pass the lines "key = pair[0]; value = pair[1]"

Without a nicer library and tuple unpacking, ruby's version would look like this:

map = getMap
treemap = treeMap.new(map)
treemap.each do |pair|
  key = pair[0]
  value = pair[1]
  ...
end


which looks in my opinion like the java version, and sucks as much too.

Therefore i think, the generics have nothing to do with it.

Cedric Beust

Posts: 140
Nickname: cbeust
Registered: Feb, 2004

Re: Have Generics Killed Java? Posted: Jul 22, 2010 9:46 AM
Reply to this message Reply
> Though to be fair, a C#-style local type inference in this
> case would have fairly limited benefits

The JDK7 diamond syntax is certainly welcome, but note that you can already get a decent syntax with today's JDK:

Map<Integer, String> m = Maps.newHashMap();

This is something I use everywhere in my code these days.

Randy Rizun

Posts: 2
Nickname: rrizun
Registered: Mar, 2006

Re: Have Generics Killed Java? Posted: Jul 22, 2010 9:48 AM
Reply to this message Reply
google guava library helps a bit wrt verbose syntax

Cedric Beust

Posts: 140
Nickname: cbeust
Registered: Feb, 2004

Re: Have Generics Killed Java? Posted: Jul 22, 2010 9:49 AM
Reply to this message Reply
> Generics were a major new language feature in a mature
> language which already had a clunky, restricted syntax. To
> use this feature requires yet more clunky syntax. I don't
> think generics killed Java, I think Java killed Java (or
> at least, irreversibly poisoned its own chances of
> flourishing in the future with unlucky
> backwards-compatibility problems). For people who for
> whatever reason have no choice but to continue using Java,
> generics are welcome.

I can't help being amused whenever I read about the imminent death of Java.

Here's another thought: the most popular languages are the ones that have been able to maintain backward compatibility across computer eras.

Justin Silver

Posts: 1
Nickname: lukewarmmi
Registered: Jul, 2010

Re: Have Generics Killed Java? Posted: Jul 22, 2010 9:58 AM
Reply to this message Reply
Your very first example of preference was:

SALES MINUS COSTS DIVIDED BY YEAR
to
(sales - costs) / years

For me it comes down to being clear about what you mean, and having the compiler warn you when it isn't sure. Your sentence could just as easily mean "sales - (costs/years)", which is something else entirely no? The placement of parens is my example of why I like makings sure the proper object types are in the right place.

I have personally run into issues where the wrong object type was put in an untyped memory cache, and when you're dealing with hundreds of thousands of lines of code, it's nice to see that everything is where it should be. Typing the cache gives you that. Not all programmers are 31337 h@x0rs, and having rules in place to make sure they stay in line helps.

Flat View: This topic has 62 replies on 5 pages [ « | 1  2  3  4  5 | » ]
Topic: How Much Unit Test Coverage Do You Need? - The Testivus Answer Previous Topic   Next Topic Topic: Adding Optional Static Typing to Python

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use