aspose file tools*
The moose likes Java in General and the fly likes Can your object override the = instead of .equals? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Can your object override the = instead of .equals?" Watch "Can your object override the = instead of .equals?" New topic
Author

Can your object override the = instead of .equals?

Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
I know that when someone calls myobj.equals() I can override the .equals so it uses my method of checking. Is there any way for me to change the "rules" similarly when some calls "myobj ="? (I know it's slightly diff. from the first since the first is a check for equality and the second is an assignment of reference) Is there any way to grab the action being done on the object?
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
No, you're talking operator overloading here, and Java (still?) doesn't implement this stuff.
kind regards
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
Really? That stinks, are you 100% sure though?
For anyone out there not totally getting what I'm asking, in C++ imagine I'm doing this:
myTFoo = yourTFoo;
Well, what does that do? Believe it or not, I can defin that:
TFoo&
TFoo:perator=(const TFoo& that)
{
//...do stuff here ...
}
In Java that above code might look like this:
TFoo =(final TFoo that)
{
}
Of course, I'm making that up, but there may be a way to do it?
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
Yes I'm sure about that and I know how it works in C++ and it can be quite convenient here and there, but Java does not support operator overloading (yet?). Sorry again ...
kind regards
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15299
    
    6

Just here to confirm Jos in case you still don't believe him after he told you twice.
I got your back Jos.


GenRocket - Experts at Building Test Data
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
Lol. Sorry guys. Jos, no I knew YOU knew what I was talking about but since you said:
and Java (still?)

I thought you weren't 100% sure so I wanted to see if anyone else knew (and to be sure they knew what I was talking about).
Thanks! (and darn! I WISH I could do that!)
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4702
    
    7

Originally posted by Robert Paris:
(and darn! I WISH I could do that!)
Syntactical differences aside, what's wrong with just overriding equals()? IMHO, it's a lot simpler to limit == to reference comparisons and have equals() do logical comparisons. It helps keep you from shooting yourself in the foot (and others from shooting you, too).


Junilu - [How to Ask Questions] [How to Answer Questions]
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
Syntactical differences aside, what's wrong with just overriding equals()? IMHO, it's a lot simpler to limit == to reference comparisons and have equals() do logical comparisons.

Junilu,
you misunderstood my question, I'm not interested in comparison, just assignment.
As I stated in my post:
I know it's slightly diff. from the first since the first is a check for equality and the second is an assignment of reference)

I was just using equals() as an example/analogy. Sorry if that was confusing!
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4702
    
    7

My bad Should have read the whole thread first...
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
You can't override assignment. (C# supports this.) The problem is that it introduces too many uncertainties into the code. What does this mean?
Date d = MyButton;
This could be legal in C# even though it makes absolutley no sense. In Java, you would supply a method to do what you want.


Associate Instructor - Hofstra University
Amazon Top 750 reviewer - Blog - Unresolved References - Book Review Blog
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4702
    
    7

You could always provide a "copy constructor", e.g.:

Or you could use the Jakarta Commons BeanUtils library to copy properties of one object to another.
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
I hear you, but it does make sense. I have no control over the code which calls the assignment operator. So what will happen is if the code is called again, I can't deny the attempt, nor could I add that object as a sub-object to a collection or whatever. This is what I want to do. I also can't use a proxy because again, i can't control how they call that method (not my code).
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
Originally posted by Robert Paris:Lol. Sorry guys. Jos, no I knew YOU knew what I was talking about but since you said:
still?
I thought you weren't 100% sure so I wanted to see if anyone else knew (and to be sure they knew what I was talking about).

Well, the 'still?' was a shorthand for asking myself whether or not version 1.5, 1.6 etc. would support operator overloading; rumours say that generics (cf. the C++ STL) were going to be implemented and 'aspects' are in the vicinity also. But for now, no ( third time, I'm writing this, so it must be true ) there's no operator overloading available in the Java language.
Don't forget though, Java is a small language with a humongous load of pre-implemented classes that comes with it, while C++ is a humongous language with just a small amount of (generic) classes implemented as well as a severly hurting appendicitis of C legacy stuff coming with it ...
kind regards
[ February 13, 2003: Message edited by: Jos Horsmeier ]
Neil Laurance
Ranch Hand

Joined: Jul 18, 2002
Posts: 183
Java does have one instance of operator overloading, namely the + operator, when one of the operands is a String object
What exactly are you trying to do? If you are trying to get assignment to add a newly created object to a list of objects, you could do this with code like:

Though this may be inefficient in terms of garbage collection.
Cheers, Neil
[ February 13, 2003: Message edited by: Neil Laurance ]
Gopi Balaji
Ranch Hand

Joined: Jan 23, 2003
Posts: 84
Originally posted by Jos Horsmeier:

'aspects'

Well, the current implementation of AspectJ can capture assignments of member variables.
-GB.
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Generics and covariant return types are definitely part of version 1.5 of the SDK (codename Tiger). As are a foreach construct for easy iteration, boxing of primitives, enumerated types and a concurrency library I think metadata is in, too. Operator overloading seems to be out, though
Looking forward to it, myself
- Peter
[ February 14, 2003: Message edited by: Peter den Haan ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Well I'm not sure about the "definitely" - there was a time generics were supposed to be in 1.4 too, but they got pulled because there were too many bugs or unresolved issues. It does seem pretty likely they'll be in 1.5 at this point, but I wouldn't want to jinx it or anything...


"I'm not back." - Bill Harding, Twister
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
That's all well and good, but to me the BEST addition is auto-boxing and auto-unboxing. That's HUGE. Especially given that reflection and Enumerations use objects only. No longer will you have to discover what it is and convert it to/from a primitive. I hope they implement this correctly across the whole jre.
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
auto-boxing has some implications that I'm not thrilled with. First off, there is a hidden cost in using a primitive as an object that might not be obvious.
There is also the issue of losing Java's tight data typing. If I use a primitive in a method that is looking for an object, auto-boxing will convert the primitive to an object. So I pay the price for conversion plus it may not be want I wanted to do in the first place!!!
Look at this:
int i = anObjectMethod(35);
We could have two hidden box/unboxes in that statement.
Personally, I would be very happy not to have auto-boxing of primitives added to the language.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I agree with Robert that autoboxing of primitives should be pretty cool overall. I still want foreach and generics more, but they're all cool - and complementary in many ways.
If I read the currently proposed spec correctly, auto-unboxing would not be supported - unboxing would require a cast. So

will not compile until you change it to

It seems that would help slightly in offsetting Thomas' concerns, by drawing attention to the code where unboxing occurs, without being too inconvenient for the user. Though the (draft) spec does note that the expert group may also consider adding auto-unboxing if it's not too disruptive.
Perhaps the best solution for Thomas' concerns would be to allow users to enable/disable boxing/unboxing with a compiler flag? As we do for assertions? I guess it had to be done there for backward compatibility - older code could use "assert" as an identifier, and now it's a keyword. For autoboxing the situation's not the same - adding autoboxing doesn't break any old code, but it allows some things to compile that were previously errors. So it's not necessary to make it disablable (new word?) - but might be nice.
It seems that autoboxing/generics/foreach all share the property that they make Java easier to use, at the cost of hiding implementation details that may be inefficient, and losing some benefits of compile-time type safety. My feeling is the benefits will substantially outweigh the problems, but it's true we'll have to keep an eye out for new problems.
Incidentally Peter's list seems to overlook one other minor addition I like: static imports. This would allow things like:

Maybe not as powerful as the other additions, but still nice for trimming some annoying method signatures.
For those interested, here is a link to all JSRs. Most of our favorite goodies are in JSR 201.
[ February 14, 2003: Message edited by: Jim Yingst ]
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Another scary thought with boxing:
Imagine I have a class with this method:
int myMethod(Object obj) { return 0; }
You run it using:
int i = myMethod(35);
This will auto-box and everything proceeds normally.
A couple of months later I decide to add a new method to my class:
Object myMethod(int i) { return null; }
Now your program fails to compile. Or worse, if auto-unboxing is enabled, your program will compile but crash when it runs since null can't be converted into an int!!!
This creates an OO violation in my opinion. I haven't changed my program's interface and yet your program is toast.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
This creates an OO violation in my opinion. I haven't changed my program's interface and yet your program is toast.
But you have changed the interface - you've added a new public method with a more specific method than the one I'm using, so my program picks it up accidentally. You can create this situation even without autoboxing. Start with a method:

and later add a more specific overload with different return type:

This is perfectly legal, and can break client code the same way. Adding a overloading method to a publicly-released API is already dangerous.
Now your program fails to compile
Only because you released new code without testing it well enough.
[ February 14, 2003: Message edited by: Jim Yingst ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Re: the original question about operator overloading. This is something that Gosling et al intentionally did not want in the language, feeling that it was one of the things in C++ that created more problems than it solved. A few years ago Gosling seems to have reconsidered somewhat, based on his talks with folks interested in doing serious numerical computations with Java. You can see discussion of this here. Basically he now proposes that a + b be mapped to a.plus(b) in cases where a is an Object (other than String I suppose). Or something like that. Might be a nice addition. I haven't seen any followup discussion of this though, so I dunno if it will ever actually make it into Java. Almost certainly not in 1.5 anyway; they've got enough on their plate already.
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Your example doesn't work. It would still run the int version not the long version. It will only run the long version if I specifically passed it a long in the first place. And then it wouldn't have compiled in the earlier version because I can't auto-cast a long into an int.
Let's see:
the method looks like this:
public int myMethod(int i) { return 0; }
You run it with:
int i = myMethod(45);
Now you add:
public Object myMethod(long l) { return null; }
It still runs the original version.

If we start with this:
public int myMethod(long l) { return 0; }
and then add this:
public Object myMethod(int i) { return null; }
Then we have a potential problem. But it is a clear, easily identifiable problem that should rarely come up in the real world. When you start with a method that takes parameters with a wider range, you should avoid adding methods with a smaller range.
With boxing, another rule is added... you can never create a method that takes a primitive if the class already has a method with the same name that takes an Object.
[ February 14, 2003: Message edited by: Thomas Paul ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Yeah, I reversed the order in which the two methods should be used to create a problem. Thanks for the catch. But as you see, the basic "flaw" already exists in Java.
With boxing, another rule is added... you can never create a method that takes a primitive if the class already has a method with the same name that takes an Object.
"Never" is an overstatement, isn't it? I think you should avoid this, just as you should in the int/long example - and if you do it, you should take particular care not to change the return type to something incompatible. (Which I think means, don't return something wider/more general.) I'd have been inclined to avoid changing return types when overloading anyway - it seems like it just creates more opportunities for confusion. If we want to change the behavior of the method that much, we can just use a different name. (Though I'll have to think about this some more if covariant return types are allowed as part of generics...)
Also your "new rule" just seems like a generalization from the existing rule, if we consider Object wrappers as "wider" than primitives. (Which is supported by the new casting and conversion rules - boxing conversion is invoked in the same sorts of circumstances as widening conversions, and unboxing is likewise comparable to a narrowing conversion.) When you start with a method that takes parameters with a wider range (like an Object), you should avoid adding methods with a smaller range (like a primitive). It doesn't seem like a vastly different rule than the previous one, not to me anyway. YMMV of course.
[ February 14, 2003: Message edited by: Jim Yingst ]
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
Jim,
It's good that you suggested it:
"Perhaps the best solution for Thomas' concerns would be to allow users to enable/disable boxing/unboxing with a compiler flag?"
I was about to when I read that in your post. I agree, but not completely. I think that putting it in the compiler is NOT good enough. Remember that more and more people (and APIs/Architectures) are using runtime byte-code engineering. So I think this would need to be a runtime flag. I can easily create bytes without compiling anything and we'd still run into the problem.
In addition, with byte-code engineering at runtime, the VM will have to reject the definClass attempt if you create a class with both an object signature of that method and a primitive version. However, now that I think about it, there are times when you DO want:
public void doSomething(Integer i);
public void doSomething(int i);

to be distinct. Which is why I think a flag would be good:

public void doSomething(autobox Integer i);
public autobox Object getIt();

Why not? No different in syntax than putting:

public void doSomething(final Integer i);
public final Object getIt();

And it avoids the problems Thomas (do you prefer Tom?) brought up. It's clear and lets everyone know the API's intentions. As well, it allows you to treat it as not changing the signature whereas the current idea they're talking about DOES change the signature, because of the forced rules upon method signature of a method taking int and Integer but otherwise being the same. To me that CHANGES the signature and rules of signature. I don't like that.
What do you guys think? I'm sure you guys have more pull than I do, maybe you guys could lobby for the autoboxing keyword?
oh, one other plus of the autoboxing keyword? All old Java code will still work 100% as written! While the current idea for autoboxing would make this previously written code, to not work:
public class Test
{
public void foo(Integer fooey){}
public void foo(int fooey){}
}
[ February 14, 2003: Message edited by: Robert Paris ]
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by Jim Yingst:
But as you see, the basic "flaw" already exists in Java.
The more I think about it the more I hate the way that was implemented in java. They should have forced you to provide the types of the exact parameter list. It would have avoided all those "ambiguous method" errors and would have prevented problems of adding methods causing interface contracts to break. Maybe it's time for java#.
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by Robert Paris:

oh, one other plus of the autoboxing keyword? All old Java code will still work 100% as written! While the current idea for autoboxing would make this previously written code, to not work:
public class Test
{
public void foo(Integer fooey){}
public void foo(int fooey){}
}

Why would this code not work? Wouldn't auto-boxing occur only if no matching int message signature was available? The above would work fine in C#.
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
But Tom, I was going by your quote:
With boxing, another rule is added... you can never create a method that takes a primitive if the class already has a method with the same name that takes an Object.

From that, the example code is invalid! With your above quote, you could not define a class of:
public class Test
{
public void foo(Integer fooey){}
public void foo(int fooey){}
}
Because it would not know to which method you meant to send it, i.e. did you want for autoboxing to occur, or not?
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
My rule has to do with causing code that once worked to stop working. In the case of auto-boxing, the non-boxing version would always be given preference. The problem occurs if ina world with boxing you have a method that boxes and then later on you add a method with the primitive. Suddenly all the users of your code unknowingly switch to the primitive version which could introduce strange errors into their code.
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
Sure, but wouldn't my idea of introducing the keyword "autobox" fix that problem? If there's no autobox keyword, it doesn't box anything. So old working code would have no problems or vagueness.
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
I don't really see the need to expand a language that is purposefully kept as small as possible to fix a problem that has been around for ages and is not widely perceived to be a problem in the first place, that only happens with broken overloading, and which can also be fixed (albeit only on an ad-hoc basis) with simple type coercion which already is part of the language. So I guess this means I must be missing something?
- Peter
[ February 17, 2003: Message edited by: Peter den Haan ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Robert - old working code will continue to work under the proposed autoboxing scheme (without the need for a keyword). It's only when you add new code to it that you have the opportunity to make the old code not work, if you're not careful. Which is to say, adding bad code is the problem, not adding autoboxing.
[Robert]: I think that putting it in the compiler is NOT good enough. Remember that more and more people (and APIs/Architectures) are using runtime byte-code engineering. So I think this would need to be a runtime flag. I can easily create bytes without compiling anything and we'd still run into the problem.
Well, I only know a little about BCEL, but I'm sorta inclined to think that people who are creating their bytecodes on the fly like this are on their own. I mean, aren't they responsible for understanding how the existing code works before they change it? There are any number of new errors that might be introduced when you change code - if you bypass the compiler, I think those errors are just going to have to be detected at runtime the old-fashioned way. I.e. in the case of adding a poorly-chosen overload (one with a more specific parameter but a more general return type) you get a ClassCastException (or possibly NullPointerException if the object to be converted is null). If you bypass the compiler, you lose the benefit of compile-time checking - but you still get run-time checking. Adding an autobox keyword might make things a little easier for the BCEL folks in this one area, but it seems like there are so many other things that can go wrong if they don't understand the code they are modifying - the benefit of the new keyword would be nearly insignificant.
Of course, I may well be completely misunderstanding how BCEL is used. So corrections are welcome.
Robert Paris
Ranch Hand

Joined: Jul 28, 2002
Posts: 585
Robert - old working code will continue to work under the proposed autoboxing scheme (without the need for a keyword). It's only when you add new code to it that you have the opportunity to make the old code not work, if you're not careful. Which is to say, adding bad code is the problem, not adding autoboxing.

Jim - can you explain a bit more about this? i'm not sure I see how that could be the case. Consider the following:
1. In a language/run-time environment with autoboxing (as I understand the manner in which Java will implement this) it is not allowed for a class to have two methods with method signatures that differ only by a parameter where one method has it as the primitive (say "int") and the other as the boxed version of that primitive (say Integer).
2. We have a class with two methods which in our non-boxing current JRE/JVM works with no ambiguities:
public int add(Integer num);
public int add(int num);
In an auto-boxing JVM, with NO autobox indicator, how will the JVM know which method to use? Well, as Tom pointed out, it would switch people who were previously getting their code sent to one method to the other:
The problem occurs if in a world with boxing you have a method that boxes and then later on you add a method with the primitive. Suddenly all the users of your code unknowingly switch to the primitive version which could introduce strange errors into their code.

(UNLESS, what I'm missing is that the new spec calls for compilers to put the autoboxing keyword in, but that the Java language does not include it?)

I mean, aren't they responsible for understanding how the existing code works before they change it?

Well, yes, but remember that I can write byte-code altering/creating components, that someone else purchases, which generates that code on the fly and does not know beforehand what code it will be generating. Rather than have to rely on creators of byte-code generators to implement those rules and mutiple checks, aren't we going to have more stable JVMs (and applications) if we simply make it a modifier (i.e. the language guarantees the stability and compliance)?
And really, if my first question is cleared up, I think this answers itself. I don't think it's a problem of people generating bytecode but of the ambiguity of a language that has autoboxing (and needs backwards compliance) but has non-indicator autoboxing.
[ February 17, 2003: Message edited by: Robert Paris ]
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Robert Paris:
We have a class with two methods which in our non-boxing current JRE/JVM works with no ambiguities:
public int add(Integer num);
public int add(int num);
In an auto-boxing JVM, with NO autobox indicator, how will the JVM know which method to use? Well, as Tom pointed out, it would switch people who were previously getting their code sent to one method to the other:
No they won't. The add(int) method is more specific than the add(Integer) method, so it's still the non-boxing method that will be called if you have an int argument. As unboxing is not automatic, there's no danger of calling add(int) when you wanted to call add(Integer).
This is different from Tom's illustration that you quoted. He adds a method taking a primitive and some invocations might switch to that method (when recompiled). But that, as has been pointed out, is nothing new whatsoever. When you overload a method with another that takes a more specific subtype, this is what happens. It hasn't caused any major confusion and disarray so far, and I don't see it causing us problems simply because we get some new type conversions.
- Peter
[ February 17, 2003: Message edited by: Peter den Haan ]
David Weitzman
Ranch Hand

Joined: Jul 27, 2001
Posts: 1365
Since this thread has been hijacked anyway: In 1.5 I'm also going to appreciate smaller downloads thanks to JSR 200.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Can your object override the = instead of .equals?