Overriding Object.equals in Generic class

Hello all!

I'm finding the erasure feature of Java Generics to be a total pain. It appears that I cannot create an overridden version of theObject.equals (Object) method that returns true if, and only if:

1. The supplied object reference is not null.

2. The supplied object reference has the same type as the generic type. (This seems to be impossible.)

3. This object and the supplied object have the same values.

For example,

publicclass MeasurementUnit{

// ...

}

publicfinalclass Distanceextends MeasurementUnit{

// ...

}

publicfinalclass Velocityextends MeasurementUnit{

// ...

}

// etc.

publicclass Measurement <UnitTypeextends MeasurementUnit>{

privatedouble measurement;

// ...

public Measurement (double value){

this.measurement = value;

}

@Override

publicboolean equals (Object obj){

// Null references are not equal to this instance.

if (obj ==null){

returnfalse;

}

// Only measurement types of the same type can equal. Sadly, Java generics only

// let us verify that obj is a Measurement.

if (!obj.getClass ().equals (Measurement.class)){

returnfalse;

}

// Determine if both objects have the same data. Requires an unchecked cast.

Measurement <UnitType> other = (Measurement <UnitType>) obj;// Unchecked cast.

return this.measurement == other.measurement;

}

// ...

}

publicclass Test{

publicstaticvoid main (String []){

Measurement <Distance> someLength =new Measurement <Distance> (5.0);

Measurement <Velocity> someVelocity =new Measurement <Velocity> (5.0);

if (someLength.equals (someVelocity)){

System.out.println ("It didn't work! Velocities and distances are equal?");

}

else{

System.out.println ("It worked! Velocities and distances cannot be equal!!!!");

}

}

}

Have a guess which string would be output? Yup! The wrong one!

Is there any way around this, or does erasure ensure that Java can never give the right answer to this problem?

Mike

Message was edited by:

MikeAllen

[4517 byte] By [MikeAllena] at [2007-11-27 0:28:35]
# 1

> 2. The supplied object reference has the same type as

> the generic type. (This seems to be impossible.)

Right, it's impossible. The information simply isn't there after the compilation is done.

So... it's not in the byte code, not in the runtime system, not anywhere.

KathyMcDonnella at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 2

Thanks for your reply.

That's what I thought. However, what I'm trying to do is valid, IMHO. Would you agree? Do I have to live with this "bug" forever, or is there any workaround that achieves the result I'm looking for?

My personal opinion is that erasure is a disaster that causes a whole lot more problems than it solves. Furthermore, the severity of the problems it causes are significantly higher than preserving JVM backwards compatibility. Worse still, its side-effects mean that it is highly unlikely ever to be corrected.

MikeAllena at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 3

The disadvantages of erasure is unfortunately well discussed and documented.

I'm not familiar enough to comment on alternative design choices (in particular,

C#'s implementation which DOES retain the type info at runtime)

Google, and you'll find lots and lots of articles about this.

It has sort of becomes an extension of the Java vs C# debate.

KathyMcDonnella at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 4

I'm afraid that you're not telling me anything that I do not already know. C# has a very good generics implementation. In fact, you can actually do generic programming in C#. You cannot do generic programming in Java - it's a bodged implementation with way too many restrictions and poor run-time efficiency. Sadly, no-one in the Java community seems to want to do anything about it. Then again, fixing Java generics is going to bust a lot of code from early adopters. Erasure is a poorly thought-out disaster and it's going to ensure that many programmers with a choice are going to go elsewhere. Personally, I'd like to see someone at Sun admit that they screwed up and put a plan in place to put things right as soon as possible. The longer this goes on, the worse it's going to get...

But philosophical language discussions aside, my question remains: is there a workaround that would allow me to fix this method other than making Measurement <Distance> and Measurement <Velocity> different classes that have identical code, but which cannot (apparently) be programmed generically?

null

MikeAllena at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 5

> I'm afraid that you're not telling me anything that I

> do not already know.

I'm not implying otherwise. :)

>

> C# has a very good generics implementation.

>

Many people agree with you.

I don't know enough to be able to judge yet.

>

> But philosophical language discussions aside, my

> question remains: is there a workaround that would

> allow me to fix this method other than making

> Distance and Velocity different classes

> that have identical code, but which cannot

> (apparently) be programmed generically?

>

Definitely not using generics. But you could embed a runtime object

to denote the difference.

class Measurement

{

Class type;

double value;

Measurement(Class type, double value) { this.type=type; this.value=value; }

...

}

So when creating a Measurement, you need to pass in Distance.class or Velocity.class, etc.

And when doing equals(), it compares the class as well.

(Obviously, without syntax support, this gets very cumbersome to write)

KathyMcDonnella at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 6

Thanks! Embedding extra type information is something I stupidly didn't consider - I'll give it some thought...

Maybe even:

public class Measurement <UnitType extends MeasurementUnit> {

private double measurement;

private Class <? extends UnitType> unitType; // Yak!

// ...

public Measurement (double value) {

this.measurement = value;

this.unitType = UnitType.class; // Sadly illegal!

}

@Override

public boolean equals (Object obj) {

// Null references are not equal to this instance.

if (obj == null) {

return false;

}

// Only measurement types of the same type can be equal. Sadly, Java generics only

// lets us verify that obj is a Measurement. That will do for now...

if (!obj.getClass ().equals (Measurement.class)) {

return false;

}

// So these are both measurements. Do an unchecked cast so that we can look at

// each object's members.

Measurement <UnitType> other = (Measurement <UnitType>) obj; // Unchecked cast.

return this.unitType.equals (other.unitType) && this.measurement == other.measurement;

}

// ...

}

Nah! UnitType.class is illegal. So even that doesn't work! What use are Java generics again? :-(

I find it ironic that you recommend ditching generics - and all of the type-safety that (allegedly) comes with it - and go back to the pre-generic way of doing this kind of thing. Yak! ;-)

MikeAllena at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 7

> Nah! UnitType.class is illegal.

Right, you cannot take the class of a Java generics parameter.

>

> What use are Java generics again? :-(

>

:) :)

>

> I find it ironic that you recommend ditching generics

>

Well, I'm not a big fan of Java's generics implementation in general.

I just think each tool has its place, that's all.

So if embedding a type tag works for you, then that's great.

>

> and all of the type-safety that (allegedly) comes with it

>

You could actually double it up.

Measurement<Velocity> x = new Measurement<Velocity>(Velocity.class, 3.0);

Measurement<Distance> y = new Measurement<Distance>(Distance.class, 3.0);

x=y; // This error will be caught at compile time by generics

x.equals(y); // This will return false at runtime by the embedded tag

KathyMcDonnella at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 8

Hmmm...

A bulletproof implementation would need to guard against someone doing the following:

Measurement <Velocity> x = new Measurement <Velocity> (Distance.class, 3.0); // Er...!?!?

I personally dislike this solution because the first constructor argument is (or rather, ought to be) redundant. If you had to work with an API like this, my bet is that your first reaction would be "what the...?". Still, it's a natural consequence of trying to use Java generics (which I am now convinced is a misnomer - it ought to be called "Java JVM-backwards-compatible-feature-with-restricted-type-safety-improvements-and-run-time-penalties-not-be-confused-with-generic-programming-support" - not exactly catchy, but accurate!).

Surely, the whole point of generic programming is to overcome such issues with elegant, simple, dare I say obvious, solutions? Sorry about the rant...

Fortunately, the actual code I'm working on has a more elegant solution - but it still requires me to store a (redundant) per-instance type member. This has a large memory and run-time overhead to solve a simple bug in a basic method.

MikeAllena at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 9

> Sorry about the rant...

I often curse at Java's generics implementation too. :)

>

> Fortunately, the actual code I'm working on has a

> more elegant solution - but it still requires me to

> store a (redundant) per-instance type member.

> This has a large memory and run-time overhead to solve a

> simple bug in a basic method.

>

I believe C#'s implementation will also (under the hood) store a "tag" per object.

(otherwise, how would you be able to access the type at runtime?)

So the memory overhead should be comparable.

But runtime overhead should indeed be less in C#,

since the compiler doesn't have to insert the secret "type casts"

KathyMcDonnella at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 10

> I believe C#'s implementation will also (under the hood) store a "tag" per object.

Not exactly. At worst it has one tag per generic class. That is, if I define a class G <T>, then I might have the following generic classes: G <Thing>, G <Gizmo>, G <Widget>, etc. Each of these generic classes would have a type "tag" - but I would certainly not have one "tag" per instance of each type.

Let's be honest: C# is just Microsoft's embraced-and-extended version of Java. It irks me that Micro$oft have implemented a better generics solution - one that actually works and does what you expect - when Java's implementation does not. Java could have easily gone the same route as C# - but it dropped the ball and screwed up big time. How many questions in this forum would just disappear if Java did generics properly?

MikeAllena at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 11

> Not exactly. At worst it has one tag per generic

> class. That is, if I define a class G <T>, then I

> might have the following generic classes: G <Thing>,

> G <Gizmo>, G <Widget>, etc. Each of these generic

> classes would have a type "tag" - but I would

> certainly not have one "tag" per instance of

> each type.

Oh, so does C# instantiate distinct classes during runtime? If I have this:

Measurement<Velocity> x = new Measurement<Velocity>(1.0);

Measurement<Velocity> y = new Measurement<Velocity>(2.0);

Measurement<Distance> z = new Measurement<Velocity>(3.0);

Then surely x points to a struct of at least 3 fields: class(Measurement), param(Velocity), double(1).

And y points to a struct: Measurement, Velocity, 2.

And z points to a struct: Measurement, Distance, 3.

If a pointer takes at least 4 bytes, then sizeof(x) >= 4+4+8, no?

Edit: Never mind, I've found the answer to my question.

You're right in that "x" and "y" only have to point at Measurement<Velocity>, and not Measurement+Velocity.

See http://www.artima.com/intv/generics2.html

KathyMcDonnella at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 12

The way I understand it is that, like Java, the C# compiler generates a single class definition. In the case of Java, that single definition is what executes no matter what the actual type definition(s). This is why Java "forgets" generic type information at run-time - all the type parameters get converted to Object references.

C#, on the other hand, uses this definition as a template. Each time a new generic class is required, it copies this template and changes the generic type information into the actual types. This, I think, is handled by the .NET virtual machine. Consequently, not only does C# remember exact generic types (that is, it can distinguish between a G <Gizmo> and a G <Widget> - in Java, both are just type G) but it also allows each generic class to have distinct static members too!

Given:

public class G <T> {

private static int staticVar1;

private static T staticVar2; // Illegal in Java, but not in C#

// ...

}

then G <Gizmo>.staticVar1 and G <Widget>.staticVar1 would be different objects - in Java, they are identical objects. Also, G <Gizmo>.staticVar2 and G <Widget>.staticVar2 are not only different objects, they are different types.

I'll look up a reference that explains better than I can what C# actually does under the hood.

MikeAllena at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 13
Thank you for your explanation! It clarified a lot.
KathyMcDonnella at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 14
> Thank you for your explanation! It clarified a lot.No problem. Thanks for your assistance, which helped me to solve my initial problem even if it did not help me come to terms with Java's generics... ;-)
MikeAllena at 2007-7-11 22:30:01 > top of Java-index,Core,Core APIs...
# 15

> A bulletproof implementation would need to guard

> against someone doing the following:

>

> Measurement <Velocity> x = new Measurement <Velocity>

> (Distance.class, 3.0); // Er...!?!?

Well, that's doable, isn't it? (If you can tear your mind away from explaining why Java is bad and C# is good...)public class Measurement<T> {

public Measurement<T> (Class<T>, double value) {

...

}

...

}

DrClapa at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 16

> Well, that's doable, isn't it?

Sure it is - never said it wasn't. But is that how you would solve this problem? Really?

>If you can tear your mind away from explaining why Java is bad and C# is good...

I don't believe I ever said that Java was bad and C# is good. I certainly said that Java Generics are bad and that C# Generics are (comparatively) good. You see, stupid design decisions only get put right when enough people complain about them. Stop complaining, and there's no pressure to put things right. Of course, if you're happy with the status quo - and you're certainly free to have that opinion - then you can disagree with me. However, you cannot do generic programming in Java with the current implementation, in the sense that you can take a class and genericise it.

MikeAllena at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 17

> > Well, that's doable, isn't it?

>

> Sure it is - never said it wasn't. But is that how

> you would solve this problem? Really?

I'm not sure whether it's how I would solve that problem or not. I didn't put a lot of thought into it, and there might be something better. It's not my problem, you see, so I don't have to come up with a final solution. But I was irked that you seemed to have already decided it wasn't possible and went off on a tangential rant.

Normally I would suggest that griping on forums is a waste of time in terms of getting changes to happen, but this particular forum might be an exception to that rule.

DrClapa at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 18

I agree ... some complaining about this might help. From the little bit I just learned here about how C# does it, I hate to admit it but it makes more sense than the Java implementation.

What scares me is this: [url http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#Using_Generic_Methods] ava Generics FAQs - Programming With Java Generics [/url] ... wherein I read concerning the disadvantages of 'raw' types: "No future deprecation. The Java Language Specification states that raw types might be deprecated in a future version of Java, and might ultimately be withdrawn as a language feature."

This reminds me (don't know how many others might remember this) of what happened to COBOL. COBOL was - and still is IMO - an excellant report writer language. That's because that is what it was designed to do. It's good for other things too, but that is it's strong suite. Over time it was added onto and onto, so that finally theres OO COBOL - and code that virtually unreadable to someone very familiar with COBOL but unfamiliar with OO COBOL.

Java, I think, is trying to be all things to everyone. If it continues to do this it will fail ultimately. No one language can fulfill such goals. To take away backward compatibility is or would be a super duper humungus mistake!

~Bill

abillconsla at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 19

> You cannot do generic programming

> in Java - it's a bodged implementation with way too

> many restrictions and poor run-time efficiency.

I'm not so sure about this efficiency claim. Erasure makes the code as fast as is if there was no generics where reification requires runtime instructions.

> Sadly, no-one in the Java community seems to want to

> do anything about it.

You haven't been paying attention. If you were hanging around here a few years ago, you'd see a lot of complaining about how things were shaping up. Even the main engineer working on generics had similar concerns (that's how I read it anyway.) The obsession with backwards compatability is really at fault. There were too many mistakes in earlier versions (e.g. arrays) to allow a good implementation of generic and maintain backwards compatibility.

> Then again, fixing Java

> generics is going to bust a lot of code from early

> adopters. Erasure is a poorly thought-out disaster

> and it's going to ensure that many programmers with

> a choice are going to go elsewhere.

My personal feeling is that as a language Java hit its highmark at 1.4 (runtimes continue to improve dramatically.) Generic make some things better but add too much complexity for what they do well. I'm spend more time now looking at other languages that allow integration with Java and the JVM (e.g. Scala although it too has erasure) and less trying to follow developments in Java. I agree with the abillconsl. Java jumped the shark in 1.5.

dubwaia at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 20
Perhaps it's Suns implementation of BMW's 'I'-Drive ;o)
abillconsla at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 21

> I'm not so sure about this efficiency claim. Erasure makes the

> code as fast as is if there was no generics where reification

> requires runtime instructions.

Consider:

public class G <T> {

private T value;

public G () {

this.value = null;

}

public void setValue (T newValue) {

this.value = newValue;

}

public T getValue () {

return this.value;

}

}

When seeing this, the compiler actually emits code that is equivalent to:

public class G {

private Object value;

public G () {

this.value = null;

}

public void setValue (Object newValue) {

this.value = newValue;

}

public Object getValue () {

return this.value;

}

}

So you're right in the sense that there is no loss in efficiency compared to how you would have done this in Java compared before Generics came along.

Whenever I call G <SomeType>.setValue, whatever SomeType value I pass as a parameter gets upcast to an Object. No overhead there; all instances of SomeType must be instances of Object.

But whenever the compiler sees a call to G <SomeType>.getValue, it has to downcast the value (stored as an Object reference) back to a SomeType reference - with the associated run-time overhead.

Now, if Java did generics in the same way that C# does - that is, preserving the actual types and not doing erasure - then there would be no need for upcasting and no need for downcasting - and no run-time overhead. That's what I meant by poor run-time efficiency.

If you're dealing with primitive types, then the boxing and unboxing of these types (say from an int to an Integer and back again, so that you can use int type parameters) makes matters even worse.

> You haven't been paying attention. If you were hanging around

> here a few years ago, you'd see a lot of complaining about how

> things were shaping up.

I'm in general agreement with your comments. But I maintain that something must be done about this feature - and I'm not seeing any progress, hence my comment about no-one doing anything about it. Go look on the JSR site and see if there are any proposals to fix generics. Sometimes the cure is worse than the disease - but, this "disease" is so bad, the cure has to be taken!

MikeAllena at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 22

I agree - as you've no doubt noted. I've been reading up on Generics as much as time permits for the past couple of months ... time that I would much much rather have spent on stored procedures, new JDBC stuff, Java printing or whatever. And worst of all, just when I think I might be getting the hang of it, I read something else that forces me to rethink it all over again. What a brain/time waste!!! To make it even worse, I'm ready contradictory material - right here on Sun's site no less. Yuck!

abillconsla at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 23

> I've been reading up on Generics as much as time permits for the past couple

> of months ...

I wish I had spent time reading up on Java generics before using them. I recently made a decision to switch an open-source project of mine from C# to Java. It was at an early coding stage and I felt that Sun's decision to open-source Java, made shortly after Microsoft & Novell's now notorious agreement which I felt contaminated the open-source Mono project, coupled with the new features in Java 5 (generics, annotations, etc.), made Java a compelling language/platform choice. Java's tools (Eclipse, JUnit, CruiseControl, etc.) are far superior, and more mature, than Mono's too, IMHO. So, overall, I think I made the right decision.

Sadly, I just assumed that Java's generics were well implemented. Now I'm left with the feeling that generics were implemented in Java more for marketing purposes than to be useful in any pragmatic sense.

C'est la Vie! I guess...

MikeAllena at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 24
I like erasure. I do not like as much almost erasing. That does not seem so generic to me. Seems more like a template.
_dnoyeBa at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 25

> I like erasure. I do not like as much almost

> erasing. That does not seem so generic to me. Seems

> more like a template.

Maybe you haven't properly compared C# and Java yet.

The only reason Java is stuck with erasure is because it allows (albeit limited)

bytecode interoperability between pre-generics Java code and generics Java code.

I can dig up multiple references where the Sun developers explain and admit this.

C#'s generics implementation is better than C++ template

because it is type-safe with regard to the instantiating parameters.

C#'s generics is faster than Java because it can omit

the secretly-inserted down casts.

C#'s generics in fact only duplicates the virtual function table

for each choice of instantiating parameter. The runtime code is

completely shared, and so there is negligible memory overhead.

(And considering the secretly-inserted down casts also take up

many bytes, this means C# still uses less memory than Java)

KathyMcDonnella at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 26

> But whenever the compiler sees a call to G

> <SomeType>.getValue, it has to downcast the value

> (stored as an Object reference) back to a SomeType

> reference - with the associated run-time overhead.

OK I also didn't really read your explanation of the C# implementation before I posted that comment. I wasn't aware that was how they implemented it.

But one comments on this. The cost of a downcast is 0. There are no actual runtime instructions associated with this. The cost of an upcast in modern JVMs is very slight. It's actually very difficult to measure because it's so small.

> Now, if Java did generics in the same way that C#

> does - that is, preserving the actual types and not

> doing erasure - then there would be no need for

> upcasting and no need for downcasting - and no

> run-time overhead. That's what I meant by poor

> run-time efficiency.

There would be the cost of loading more classes would there not? There's actually a cost associated with calling methods that are not overridden on subclasses in Java. This is also very slight.

> If you're dealing with primitive types, then the

> boxing and unboxing of these types (say from an

> int to an Integer and back again, so

> that you can use int type parameters) makes

> matters even worse.

That's a completely different huge mistake in Java!

> > You haven't been paying attention. If you were

> hanging around

> > here a few years ago, you'd see a lot of

> complaining about how

> > things were shaping up.

>

> I'm in general agreement with your comments. But I

> maintain that something must be done about this

> feature - and I'm not seeing any progress, hence my

> comment about no-one doing anything about it. Go

> look on the JSR site and see if there are any

> proposals to fix generics. Sometimes the cure is

> worse than the disease - but, this "disease" is so

> bad, the cure has to be taken!

I guess I didn't make my point clear. A lot of people have given up on Java. I'm kind of getting there myself. Generics is part of it but there are other factors too. I think it makes a pretty good 'foundation' language but I've overused it in the past where other languages would have fit better.

dubwaia at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 27
clase a{private x =0;}
mqqqvpppma at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 28

> There would be the cost of loading more classes would

> there not? There's actually a cost associated with

> calling methods that are not overridden on subclasses

> in Java. This is also very slight.

Just one minor nitpick:

C# doesn't load more classes.

Instead, for example, when ArrayList<> is now used with a new type, let's say String,

C# creates a new virtual function table representing ArrayList<String>.

The code for ArrayList was already loaded and is reused as-is.

Assuming ArrayList has about 50 methods, then the new virtual function table is just 50 pointers.

KathyMcDonnella at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 29

> But one comments on this. The cost of a downcast is 0. There are no actual runtime

> instructions associated with this. The cost of an upcast in modern JVMs is very slight. It's

> actually very difficult to measure because it's so small.

I think you have them the wrong way around. The cost of an upcast (widening conversion) is 0, but a downcast (narrowing conversion) has non-trivial run-time overhead: see http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#25379 in which the Java Language Specification states: "Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. If not, then a ClassCastException is thrown." As for whether it's a slight cost or more significant, I'd say it depends upon how frequently this test gets executed.

MikeAllena at 2007-7-21 19:44:54 > top of Java-index,Core,Core APIs...
# 30

> > But one comments on this. The cost of a downcast is

> 0. There are no actual runtime

> > instructions associated with this. The cost of an

> upcast in modern JVMs is very slight. It's

> > actually very difficult to measure because it's so

> small.

>

> I think you have them the wrong way around.

I attempted to use the terms in the same way that you had. I may have mixed it up. I think you get the meaning. Which is up and which is down is an arbitrary distinction depending on whether you imagine trees going up from the root or down from the root.

> The cost

> of an upcast (widening conversion) is 0, but a

> downcast (narrowing conversion) has non-trivial

> run-time overhead: see

> http://java.sun.com/docs/books/jls/third_edition/html/

> conversions.html#25379 in which the Java Language

> Specification states: "Such conversions require a

> test at run time to find out whether the actual

> reference value is a legitimate value of the new

> type. If not, then a ClassCastException is thrown."

> As for whether it's a slight cost or more

> significant, I'd say it depends upon how frequently

> this test gets executed.

I don't see where the quoted section says it's non trivial. Throwing an exception is fairly costly but should be a rarity with respect to the casts inserted by the compiler with respect to generics. If you want to show some benchmarks that demonstrate that the ckeckcast operation is costly in non-failures please do so. I've already seen this and done it myself and recall that the cost was negligible.

dubwaia at 2007-7-21 19:44:59 > top of Java-index,Core,Core APIs...
# 31

> Just one minor nitpick:

>

> C# doesn't load more classes.

>

> Instead, for example, when ArrayList<> is now used

> with a new type, let's say String,

> C# creates a new virtual function table representing

> ArrayList<String>.

> The code for ArrayList was already loaded and is

> reused as-is.

> Assuming ArrayList has about 50 methods, then the new

> virtual function table is just 50 pointers.

The cost I was referring to was the time to load the classes. But given the above, does resolving the methods through the new virtual function table add runtime overhead or is it equivalent to the raw calls?

dubwaia at 2007-7-21 19:44:59 > top of Java-index,Core,Core APIs...
# 32

> Throwing an exception is fairly costly but should be a rarity

> with respect to the casts inserted by the compiler with

> respect to generics. If you want to show some

> benchmarks that demonstrate that the ckeckcast

> operation is costly in non-failures please do so.

> I've already seen this and done it myself and

> recall that the cost was negligible.

I see your point.

But even if the cost of casting is small, it is true that Java's erasure

means the compiler will always have to insert the type casts.

And C#'s implementation allows their compiler to remove the type casts from the byte code.

Anders Hejlsberg brilliantly summarizes the differences here:

http://www.artima.com/intv/generics2.html

> The cost I was referring to was the time to load the classes.

Ah. The first time ArrayList<String> is loaded, C# runtime loads ArrayList.

When ArrayList<Date> is needed, C# simply constructs a new virtual function table,

and does not need to reload ArrayList.

So, every time the runtime sees a new combination,

it creates a small data structure (maybe 1K in size)

to record this combination. Then all instances of ArrayList<Date>

will point to this little data structure.

> But given the above, does resolving the

> methods through the new virtual function table

> add runtime overhead or is it equivalent to the raw calls?

It is identical to a raw call, because it uses the same

method dispatch mechanism. The fact that the dispatch table

goes to a different location doesn't affect the efficiency of the dispatch lookup.

But more importantly, no typecast bytecodes are generated.

The compiler knows for sure that "String x = list.get(i)"

will always get a String object.

KathyMcDonnella at 2007-7-21 19:44:59 > top of Java-index,Core,Core APIs...
# 33

> But more importantly, no typecast bytecodes are

> generated.

> The compiler knows for sure that "String x =

> list.get(i)"

> will always get a String object.

Sound like a pretty good approach. One more question, since you seem to know all the answers:

Does C# prevent casting to a reified generic type? I assume they have to because the above would be very unsafe otherwise. Does this ever create programming inconviences and is it bulletproof? As I understand it, the lack of strictness in C++ templates is one of it's detractors biggest (and more defensible) complaints.

I wish Scala had reified generics.

dubwaia at 2007-7-21 19:44:59 > top of Java-index,Core,Core APIs...
# 34
Sorry I don't know the answer. Perhaps MikeAllen knows.Or maybe it might be explained by this excellent comparison interview http://www.artima.com/intv/generics.html
KathyMcDonnella at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 35

> Does C# prevent casting to a reified generic type?

I'm not entirely certain what you mean. If you mean, does C# disallow statements such as:

G <Thing> g = (G <Thing>) object;

Then no, it does not disallow such statements. This is perfectly legal in C#. Of course, you will get an exception at run-time if object is not an instance of G <Thing>, as you would if object is an instance of, say, G <Widget>.

> I assume they have to because the above would be very unsafe otherwise.

Why is that?

C# doesn't even use the term "reified" - that's a word that's only needed if a programming language forgets, er, things.

MikeAllena at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 36

> If you want to show some benchmarks that demonstrate that the ckeckcast operation is

> costly in non-failures please do so. I've already seen this and done it myself and recall that

> the cost was negligible.

If you use javap -c on the compiler's output, you will notice that you get a checkcast instruction every time you do a downcast. Uncessarary extra bytecodes are not what I'd call "negligible" (of course, they are necessary if you need to do a downcast). But whether it is significant or not, like I said before, depends upon how often this code executes. If you do the downcast only once in your program, then no worries. If you do it every time you call a function that executes millions of times, then that's unnecessary overhead. If it happens every time you use any generic objects, then I'd say that is unacceptable.

MikeAllena at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 37
> > I assume they have to because the above would be> very unsafe otherwise.> > Why is that?Well, I think that you cleared up my confusion. Since the type of the collection is known at runtime, it can be checked at runtime.
dubwaia at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 38

> > If you want to show some benchmarks that

> demonstrate that the ckeckcast operation is

> > costly in non-failures please do so. I've already

> seen this and done it myself and recall that

> > the cost was negligible.

>

> If you use javap -c on the compiler's output,

> you will notice that you get a checkcast

> instruction every time you do a downcast.

> Uncessarary extra bytecodes are not what I'd call

> "negligible" (of course, they are necessary if you

> need to do a downcast).

This is a non-sequiter. Or at least you'll have to explain your non-standard use of the term negligible.

> But whether it is

> significant or not, like I said before, depends upon

> how often this code executes. If you do the

> downcast only once in your program, then no worries.

> If you do it every time you call a function that

> executes millions of times, then that's unnecessary

> overhead.

Unnecessary doesn't mean significant. Millions of checkcast calls don't even add up to a millisecond of CPU time on a pretty average PC running an older JVM IIRC.

I just wrote a test and I can't even consisently get the checkcast to register a positive time cost i.e. it sometimes appears to be faster on average than not having the cast. Obviously, this doesn't make much sense and there are a few possible reasons this could be the case and they are not mutually exclusive.

1. Hotspot optimization is eliminating the cost of the checkcast

2. The checkcast call is so fast that it falls below the precision of the test.

Both of these are likely culprits. Evidence of the former is that the order in which these methods is called seems to correlate with speed much more than the checkcast instruction. For the latter, a faster operation would make the precision better but IO prevents the compiler from optimizing the loop away entirely.

In any event the fact that the cost of the checkcast is so hard to detect demonstrates that it is in fact negligible. It's beyond negligible. It's approaching being unmeasurable.

public class Test

{

final static int ITERATIONS = 10000;

final static int THRESHOLD = 100;

public static void main(String[] args)

{

Random r = new Random();

int tests = Integer.parseInt(args[0]);

long a = 0;

long b = 0;

for (int i = 0; i < tests; i++) {

if (r.nextInt(1) == 0) {

b += testB();

a += testA();

} else {

a += testA();

b += testB();

}

}

System.err.println("A:" + a);

System.err.println("B:" + b);

long diff = b - a;

System.err.println("B - A:" + (diff) + ": "

+ (((double)diff) / (tests * ITERATIONS)) + " millis");

}

public static long testA()

{

long time = System.currentTimeMillis();

String o = "testA";

for (int i = 0; i < ITERATIONS; i++) {

String s = o;

System.out.println(s);

}

time = System.currentTimeMillis() - time;

if (time < THRESHOLD) throw new RuntimeException("too few iterations");

return time;

}

public static long testB()

{

long time = System.currentTimeMillis();

Object o = "testB";

for (int i = 0; i < ITERATIONS; i++) {

String s = (String) o;

System.out.println(s);

}

time = System.currentTimeMillis() - time;

if (time < THRESHOLD) throw new RuntimeException("too few iterations");

return time;

}

}

> If it happens every time you use any

> generic objects, then I'd say that is unacceptable.

By what standard? This is something that definitely would be classified as a premature optimization.

dubwaia at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 39

I think you've missed my point. It may be "negligible" or "not significant" in your code, but I disagree.

> This is a non-sequiter. Or at least you'll have to explain your non-standard use of the

> term negligible.

I don't know what a "non-sequiter" is. Perhaps you meant non-sequitur? In either case, I'd disagree: my use of the term "negligible" was neither absurd nor a logical fallacy. However, I seem to recall that you used non-standard definitions of the terms "upcast" and "downcast" earlier in this thread. Now you're suddenly an expert on word definitions?

> Millions of checkcast calls don't even add up to a millisecond of CPU time on a pretty

> average PC running an older JVM IIRC.

Really? That's quite a statement and you'll need to prove it. Your test proves that a checkcast instruction is negligible compared to a System.out.println call (a very slow process indeed), an integer increment and an integer test operation - but not much else.

I modified your code as follows (to record the total number of tests, rather than output to the terminal):

import java.util.*;

public class Test

{

final static int ITERATIONS = 1000000;

final static int THRESHOLD = 1;

static long totalATests = 0;

static long totalBTests = 0;

public static void main(String[] args)

{

Random r = new Random();

int tests = Integer.parseInt(args[0]);

long a = 0;

long b = 0;

for (int i = 0; i < tests; i++) {

if (r.nextInt(1) == 0) {

b += testB();

a += testA();

} else {

a += testA();

b += testB();

}

}

System.err.println("A:" + a + ", tests: " + totalATests);

System.err.println("B:" + b + ", tests: " + totalBTests);

long diff = b - a;

assert totalATests == totalBTests;

// Percentage overhead compared to test A time.

double overhead = ((double) diff) * 100.0 / ((double) a);

System.err.println("B - A:" + (diff) + ": "

+ (((double)diff) / ((double) totalATests)) + " millis");

System.err.println ("Overhead: " + overhead + "%");

}

public static long testA()

{

long time = System.currentTimeMillis();

String o = "testA";

for (int i = 0; i < ITERATIONS; i++) {

String s = o;

++totalATests;

}

time = System.currentTimeMillis() - time;

if (time < THRESHOLD) throw new RuntimeException("too few iterations");

return time;

}

public static long testB()

{

long time = System.currentTimeMillis();

Object o = "testB";

for (int i = 0; i < ITERATIONS; i++) {

String s = (String) o;

++totalBTests;

}

time = System.currentTimeMillis() - time;

if (time < THRESHOLD) throw new RuntimeException("too few iterations");

return time;

}

}

I then ran this program using the command java Test 100. Here's the output I got:

A:795, tests: 100000000

B:926, tests: 100000000

B - A:131: 1.31E-6 millis

Overhead: 16.47798742138365%

So, you reckon that an instruction that causes a program to run 16.5% slower is "negligible" do you?

MikeAllena at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 40

> I'm afraid that you're not telling me anything that I

> do not already know. C# has a very good generics

> implementation. In fact, you can actually do generic

> programming in C#. You cannot do generic programming

> in Java - it's a bodged implementation with way too

> many restrictions and poor run-time efficiency.

> Sadly, no-one in the Java community seems to want to

> do anything about it.

I believe the explored alternatives would have required modifications to the VM specification. That is the basis of the problem rather than because no one wants to do anything about it.

The Sun VM should be shortly open sourced so you can implement your better solution at that time.

> Then again, fixing Java

> generics is going to bust a lot of code from early

> adopters. Erasure is a poorly thought-out disaster

> and it's going to ensure that many programmers with

> a choice are going to go elsewhere.

Excuse me?

You are going to choose C# basing that solely on the fact that you don't like generics?

I am rather certain that you will find that particular route will be a very, very lonely road.

> Personally, I'd

> like to see someone at Sun admit that they screwed

> up and put a plan in place to put things right as

> soon as possible. The longer this goes on, the

> worse it's going to get...

>

You are of course free to join JCP.

jschella at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 41

> Your test proves that a checkcast instruction is

> negligible compared to a System.out.println

I found it doubtful that you are going to be able to write any code using generics with the incurred cost and not use other instructions (those not involving casts) extensively.

>

> So, you reckon that an instruction that causes a

> program to run 16.5% slower is "negligible" do you?

Dubwai's code insured that the hotspot compiler didn't optimize out actual instructions.

Yours does not.

jschella at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 42

Although this might be an interesting theorectical discussion the vast majority of developement projects will never be impacted any small performance cost. Not even in a measurable way.

Given that requirements and design have orders of magnitude of impact on performance over even language choice (not certain small aspects of a single language) I can't see that it is reason to expect a great deal of concern about any performance cost as discussed in this thread.

In my current project I am much more concerned about the impact of network bandwidth, throughput through multiple systems including legacy systems, database usage and data storage that reasonably could reach terabytes in size. Not to mention other significant arenas such as high visibility and high attraction for criminal attacks.

And throw into that mix a very chaotic process control with a developement team that will soon grow to 50 developers. Wanna bet how many of them will write inefficient code particularily when I am basically the only one in the current group that actually creates full unit tests? Certainly the chaotic process control is the standard throughout the world.

So myself I am not going to get too concerned about a niche that is certain to a very minimal impact.

jschella at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 43

> You are going to choose C# basing that solely on the fact that you don't like generics?

Hmmm. Show me where I said I'm going to choose C# over Java. Indeed, I believe I made an argument for Java over C#. Also, I did not say that I "don't like generics". I love generics... ...when it's implemented properly. Java generics, for reasons that I've also elaborated on, is a joke.

MikeAllena at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 44

> I found it doubtful that you are going to be able to write any code using generics with the

> incurred cost and not use other instructions (those not involving casts) extensively.

Really? Where did you buy your crystal ball, chum?

> Dubwai's code insured that the hotspot compiler didn't optimize out actual instructions.

> Yours does not.

So why is there a significant, measurable difference between the two operations? Please back up your opinions with some facts. Anyone who makes an argument for putting "println" calls in the middle of a benchmark loop shouldn't be making observations about other's code.

Perhaps you could share the benefits of your profound wisdom with the rest of us and write a benchmark that measures the impact of a checkcast call to your satisfaction.

Edit: Update

I ran the test with the command java -Xint Test 100 - so that no optimisation is performed - and got these results:

A:15996, tests: 100000000

B:18335, tests: 100000000

B - A:2339: 2.339E-5 millis

Overhead: 14.62240560140035%

That's comparable to the non-opimised version. So I guess that my version doesn't optimise out the actual checkcast instruction after all. You're wrong, pal. Admit it.

MikeAllena at 2007-7-21 19:45:00 > top of Java-index,Core,Core APIs...
# 45

> Although this might be an interesting theorectical discussion the vast majority of

> developement projects will never be impacted any small performance cost. Not even in a

> measurable way.

If most developers have the same attitude to performance that you do, I don't doubt that for a second. Particularly if you can't even measure the difference properly...

> So myself I am not going to get too concerned about a niche that is certain to a very

> minimal impact.

So you say. Prove it.

MikeAllena at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 46

> I think you've missed my point. It may be

> "negligible" or "not significant" in your code, but I

> disagree.

I didn't miss your point. You are wrong.

> > Millions of checkcast calls don't even add up to a

> millisecond of CPU time on a pretty

> > average PC running an older JVM IIRC.

>

> Really? That's quite a statement and you'll need to

> prove it.

Your own results show the check cast takes about 1 nanosecond. Multiply that by a million an you get about one millisecond. Like I said, I was recalling it from memory and I was pretty close.

> ...

> So, you reckon that an instruction that causes a

> program to run 16.5% slower is "negligible" do you?

How many real world programs have you seen or written that do nothing but cast and increment?

Read this:

http://www-128.ibm.com/developerworks/java/library/j-jtp02225.html

What I'm saying that an operation that executes in: .00000000131 s (1 nanosecond) on fairly low end hardware is negligible.In almost no real world program will this ever make a difference. Your claim was that this would matter over one million operations. I've shown (and you have too) that one million checkcasts adds up to around 1 milisecond of CUP time. Do you consider this to be a great achievement? You could go to a billion operations and save a second. If you had a situation with completely optimized code (which is doubtful) and this kind of time difference mattered (even more unlikely) you'd be a lot better off using a language that compiled directly to machine code.

dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 47

> A:15996, tests: 100000000

> B:18335, tests: 100000000

> B - A:2339: 2.339E-5 millis

> Overhead: 14.62240560140035%

>

> That's comparable to the non-opimised version. So I

> guess that my version doesn't optimise out the actual

> checkcast instruction after all. You're wrong, pal.

> Admit it.

Actually the difference between the time of execution was more than an ordrer of magnitude greater than in your previous test.

dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 48
Just so we are all on the same page: the definition of negligible is - so small as to be meaningless; insignificant; "the effect was negligible"
dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 49

> > Although this might be an interesting theorectical

> discussion the vast majority of

> > developement projects will never be impacted any

> small performance cost. Not even in a

> > measurable way.

>

> If most developers have the same attitude to

> performance that you do, I don't doubt that for a

> second. Particularly if you can't even measure the

> difference properly...

Just give us an real world example from your own experience where saving a milisecond across a million operations is going to be noticeable. It's very difficult for us to prove this negative.

dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 50

I ran your version in 1.6 a few times.

C:\Program Files\Java\jdk1.6.0>bin\java Test 100

A:5704, tests: 1000000000

B:6327, tests: 1000000000

B - A:623: 6.23E-7 millis

Overhead: 10.922159887798037%

C:\Program Files\Java\jdk1.6.0>bin\java Test 100

A:5767, tests: 1000000000

B:6280, tests: 1000000000

B - A:513: 5.13E-7 millis

Overhead: 8.895439569967055%

C:\Program Files\Java\jdk1.6.0>bin\java Test 100

A:5804, tests: 1000000000

B:6258, tests: 1000000000

B - A:454: 4.54E-7 millis

Overhead: 7.822191592005513%

C:\Program Files\Java\jdk1.6.0>bin\java Test 100

A:5754, tests: 1000000000

B:6277, tests: 1000000000

B - A:523: 5.23E-7 millis

Overhead: 9.089329162321864%

An in this case, a million checkcasts does indeed execute in around half a millisecond. What kind of program do you write where this will matter?

dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 51

> I didn't miss your point. You are wrong.

Yes you did. The fact that a single instruction takes a nanosecond to execute doesn't prove me wrong at all. It depends upon how often such code executes. In a program that uses Java generics, compared to an ideal situation in which Java generics work and don't add the checkcasts, then you are going to see SIGNIFICANT memory and run-time overhead. Is it significicant? In my code, hell yes it is significant. You're free to disagree. Personally, I think this has been discussed to death. I'm not going to convince you, obviously, and you're not going to convince me. Let's leave it at that.

> Your own results show the check cast takes about 1 nanosecond. Multiply that by a

> million an you get about one millisecond. Like I said, I was recalling it from memory and

> I was pretty close.

Fair enough. You were right on that one. But you didn't prove it. As I recall, you couldn't even measure it.

MikeAllena at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 52
> Actually the difference between the time of execution was more than an ordrer of> magnitude greater than in your previous test.Er, that's because the code was interpreted. Did I not make that clear? However, the overhead was very comparable.
MikeAllena at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 53

> Just so we are all on the same page: the definition of negligible is - so small as to be

> meaningless; insignificant; "the effect was negligible"

I'd agree with that statement yes. Is the effect of the extra downcast "negligible"? In my opinion, no. In yours yes. Let's agree to differ, eh?

MikeAllena at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 54

> Just give us an real world example from your own experience where saving a milisecond

> across a million operations is going to be noticeable. It's very difficult for us to prove this

> negative.

I'd love to. I do simulations - that can run around the clock - and there are no spare clock cycles available. If I could save 16% off my run-time execution speed (admitedly, that's from a benchmark, not a real application), then I'd be very happy indeed. I'd love to write a complete simulation using generics (despite the fact, as I've pointed out, that I get a lot of additional overhead too - see the outcome of the first post in this thread), then hand-optimise the resulting code to remove the unnecessary checkcasts, then run the two and note the difference. Really, I would. But that would take a lot of time, and I don't have a lot of spare time.

So why use Java instead of C or C++? That's a complex answer, but suffice to say, that's the choice that was made.

Happy? I guessed not.

MikeAllena at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 55
> An in this case, a million checkcasts does indeed execute in around half a millisecond.> What kind of program do you write where this will matter?See my previous answer.
MikeAllena at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 56

OK. I'm done with this thread, there's a lot more hot air and opinion - most of it negative - and there's nothing new being added to the debate. Read what's appeared and make up your own mind. I got my initial query answered and I pointed out the deficiencies of Java generics. I'm now going back to continue on my application - for better or worse - using Java.

Thanks to KathyMcDonnell for your assistance and to abillconsl for adding some interesting points to the debate.

MikeAllena at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 57

> > Just give us an real world example from your own

> experience where saving a milisecond

> > across a million operations is going to be

> noticeable. It's very difficult for us to prove this

> > negative.

>

> I'd love to. I do simulations - that can run around

> the clock - and there are no spare clock cycles

> available. If I could save 16% off my run-time

> execution speed (admitedly, that's from a benchmark,

> not a real application),

This is pure nonsense. It's not going to save 16%. The only way that this would make a significant difference is if your application did almost nothing but checkcasts. If that's a real life application (or even method), I'd have to question the design.

> then I'd be very happy

> indeed. I'd love to write a complete simulation

> using generics (despite the fact, as I've pointed

> out, that I get a lot of additional overhead too -

> see the outcome of the first post in this thread),

> then hand-optimise the resulting code to remove the

> unnecessary checkcasts, then run the two and note the

> difference. Really, I would. But that would take a

> lot of time, and I don't have a lot of spare time.

You don't have to. It's obvious from the evidence at hand that it won't make any noticeable difference.You could however, count the number of checkcasts in your code and get an idea of how many are executed in a normal run. Then divide that by 1 billion. That's about how many seconds would be saved by removing them. Then divide the total exectution time of the simulation by this number of seconds.

I guarantee you there are innumerable ways that you could improve the speed of the application that will make much more difference than removing a nanosecond operation here and there. Beyond that, differences in runtime optimizations between the .NET (or mono) platforms and what version of the JVM or CLR you are running are surely going to have more impact on the speed of the code than removing this operation.

> So why use Java instead of C or C++? That's a

> complex answer, but suffice to say, that's the choice

> that was made.

Look, you aren't the first person that has made this logical error. I've probably seen and been involved in this conversation several dozen times on these forums alone. Your side always loses. Hell, I think I've even held your position at one point.

The reason I brought this up is that if you think this matters, there's a good chance actively prematurely optimize your code. This is a huge rookie mistake.

dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 58

> > An in this case, a million checkcasts does indeed

> execute in around half a millisecond.

> > What kind of program do you write where this will

> matter?

>

> See my previous answer.

It won't matter in that kind of application. Not an answer.

dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 59

> > I didn't miss your point. You are wrong.

>

> Yes you did. The fact that a single instruction

> takes a nanosecond to execute doesn't prove me wrong

> at all. It depends upon how often such code

> executes. In a program that uses Java generics,

> compared to an ideal situation in which Java generics

> work and don't add the checkcasts, then you are going

> to see SIGNIFICANT memory and run-time

> overhead.

Memory?

> Is it significicant? In my code, hell yes

> it is significant.

Sorry, that's total BS. Throughout this thread you've presented yourself as a expert but your arguments demonstrate a lack of experience. I'm pretty sure you've not been developing professionally for 5 years. Probably less.

dubwaia at 2007-7-21 19:45:05 > top of Java-index,Core,Core APIs...
# 60
dubwai: When you graduate from kindergarten, let me know. ;-)
MikeAllena at 2007-7-21 19:45:10 > top of Java-index,Core,Core APIs...
# 61

> dubwai: When you graduate from kindergarten, let me

> know. ;-)

Good one. Anyway, I know you realize that you are all wrong about this. You've only had this ID for this one thread. Just create a new one. No one will know and you'll not have to admit your error. Don't let pride get in the way of your professional development.

dubwaia at 2007-7-21 19:45:10 > top of Java-index,Core,Core APIs...
# 62

> > You are going to choose C# basing that solely on

> the fact that you don't like generics?

>

> Hmmm. Show me where I said I'm going to choose C#

> over Java. Indeed, I believe I made an argument for

> Java over C#. Also, I did not say that I "don't like

> generics". I love generics... ...when it's

> implemented properly. Java generics, for reasons

> that I've also elaborated on, is a joke.

> > You are going to choose C# basing that solely on

> the fact that you don't like generics?

>

> Hmmm. Show me where I said I'm going to choose C#

> over Java. Indeed, I believe I made an argument for

> Java over C#. Also, I did not say that I "don't like

> generics". I love generics... ...when it's

> implemented properly. Java generics, for reasons

> that I've also elaborated on, is a joke.

I quoted what you said in reply #4, so the context should have been clear.

You specifically said that due to "erasure" which you stated that generics has and on that you said "many programmers with a choice are going to go elsewhere."

Since you also claimed that C# has gotten it right is seemed likely that in the future you would make your choice based solely on that.

Myself I consider the impact (as proven here) so insignificant that I would probably laugh out loud if someone seriously suggested that it was worth considering.

jschella at 2007-7-21 19:45:10 > top of Java-index,Core,Core APIs...
# 63

> > Just give us an real world example from your own

> experience where saving a milisecond

> > across a million operations is going to be

> noticeable. It's very difficult for us to prove this

> > negative.

>

> I'd love to. I do simulations - that can run around

> the clock - and there are no spare clock cycles

> available. If I could save 16% off my run-time

> execution speed (admitedly, that's from a benchmark,

> not a real application), then I'd be very happy

> indeed.

I don't write benchmarks for a living. The vast majority of programmers don't. Of the remainder of those that do many are driven by marketing requirements to prove their product better than some one else's regardless of any possible objectivity.

So again the vast majority of programmers will never care about this.

And like others here I question your statement of your possible gain. If you were doing nothing but check casts then it might be possible, but such a benchmark could only be reasonable created based on marketing demands.

> I'd love to write a complete simulation

> using generics (despite the fact, as I've pointed

> out, that I get a lot of additional overhead too -

> see the outcome of the first post in this thread),

> then hand-optimise the resulting code to remove the

> unnecessary checkcasts, then run the two and note the

> difference. Really, I would. But that would take a

> lot of time, and I don't have a lot of spare time.

>

I have written simulations. I have optimized simulation code using profiling tools as well. And cast check times were never a factor. Nor even a reasonable consideration.

jschella at 2007-7-21 19:45:10 > top of Java-index,Core,Core APIs...
# 64

> > Although this might be an interesting theorectical

> discussion the vast majority of

> > developement projects will never be impacted any

> small performance cost. Not even in a

> > measurable way.

>

> If most developers have the same attitude to

> performance that you do, I don't doubt that for a

> second. Particularly if you can't even measure the

> difference properly...

I have been using tools to profile applications for something like 15 to 20 years.

So yes I have 'some' understanding about where likely choke points in applications might show up.

And yours isn't even close. The closest I have ever seen is when the type of collection choosen was incorrect. The implementation of the collections have never had any impact at all.

I have however seen more than a couple people insist that a language (not limited just to java) 'must' change because it wasn't optimal for their very small niche in the programming world. And their insistance that.

- Everyone would be better off

- Their niche wasn't small

- That their solution was the only possible correct one.

- That their opinion was the only one that mattered.

One might suppose that some of those people simply didn't know what they were talking about.

Oddly enough I have never seen a single one that was willing to pay, either with time or money, to actually produce and validate the change that they insisted was so critical. While more reasoned voices in markets that definitely weren't niche were more than willing to do so.

jschella at 2007-7-21 19:45:10 > top of Java-index,Core,Core APIs...