-
Why does == work when comparing other data types but I need to use .equals with Strings?
-
Strings are immutable meaning one entered it cannot change. But I’ve written programs where a variable containing a string can change so what exactly does it mean that a String is immutable?
-
Are the above 2 related?
-
I grew up as a procedural programmer and now am adapting to OOP. I get the sense that there’s more than just a difference in programming philosophy and I’m thinking that my idea of an object as a class with its data and methods encapsulated is missing something. What am I missing or am I over thinking this?
-
Umm, “==” is for reference equality testing for objects. That is, if the pointer is to the same object. Some times you can get away with using “==” instead of “.equals()” but it is a mistake if you really just want to compare values. (Note that Java is schizoid on operator overloading. Some operators are overloaded suitably, some aren’t. Gosling was very opposed to operator overloading, except when he wanted to do it.)
-
“Immutable” means you can’t change a character in a string, add something to it, etc. without making a whole new string. E.g., to change one character in a string a new string is created and the old one is garbage collected. This is done to prevent Very Bad Things from happening to naive programmers. But it’s a pain for more careful ones.
-
Nope.
-
Simple classes is just the tip of the iceberg for OOP. Inheritance, polymorphishm, and such is where the real fun begins. Get a good book on OOP (in C++ or other fully OOP language, not Java) and start trying it out. I enjoy it so much better than earlier styles.
Just a bit more detail than** ftg** provided for point 1.
Strings are objects.
String x = “abc”.
String y = “abc”.
x and y are different objects, therefore x != y
however, x.equals(y) == true
So going over number 1 again, when I type (countvar == 8)… or (scoreold == scorenew) what is really being compared since they (at least var = value) seem to work and are used in loops/conditional examples AND should I really use .equals() instead?
The schtick is that “Object”-type variables (i.e. anything other than int, long, double, boolean, and probably something else I’m forgetting) do not “contain the object”. What they contain is a reference to the object. If you’re familiar with pointers from other languages, that’s basically the same concept.
The “==” operator only compares the references so it will only return true if what you are comparing are two references to the exact same object. The “.equals()” method, depending on the class, can also compare for *semantic *equality. Basically, “does this object represent the same data as the other object”.
Each variable that represents an Object is actually a pointer to that object in memory, while for a primitive (like int, char, long, double, etc) that variable actually holds the primitive. What == does under the hood is compare just the values at that memory location. So, when doing a == b for int, that might be comparing 4 and 5, but if a and b are Strings, you’re comparing 0x23487234 and 0x78923487. The equals method (which is part of every Object and overridden for String) actually checks the values of a particular object instead of (or sometimes, in addition to) the memory location.
This can be especially confusing for students because of something called string interning, where sometimes == will work, but sometimes not. Generally though, always use equals; the first part of equals checks the object reference anyway and breaks out if they’re the same.
That means that the data inside of a particular String object can’t change, but the reference that points to the String can. This means your variable is not pointing at the same string anymore. This might be easier to see in the following example:
String a = “foo”;
String b = “bar”;
String c = a; //points to “foo”
c = b; //points to “bar”, “foo” unchanged.
a = a.toUpper();//points to “FOO”, “foo” is around until garbage collection.
Not really, I mean they both involve pointers, which you may remember from C or C++, but not other than that.
You can certainly program and never use interfaces, superclasses, inheritance, and polymorphism, but that’s like saying you could build a house without ever using power tools. True, but not the best way to do it.
Note that in this case, because of an obscure optimization that java compilers are required to make for literal strings, x == y is actually true here.
Use any other object type, like:
Integer x = new Integer(7);
Integer y = new Integer(7);
to get the result.
Primitive types, like int, long, float, double, are not objects. They behave like you’d expect numbers to behave. “==” works fine. You’ll get a compile error if you use 1.equals(1).
int i = 2;
i == 2 //OKAY
i.equals(2) //compile error
And yeah I’m doing COBOL right now so myJava is a bit rusty. heh
You seem to be contradicting the OP’s statement that .equals must be used with Strings then?
I can’t try it unfortunately. I’m just a COBOL programmer
EDIT YellowjacketCoder actually explained this clealy
OK I think I got it. A primitive variable holds the value while an object variable holds the pointer. So with primitives == is comparing the values and on objects it compares the memory location.
Not entirely. All String literals in the source code get put into a master String table for the class and all vars directly assigned from literals get references to the same instance from the String table. But strings that don’t originate from source code literals (e.g. from user input, or read from files) can be the same as one of the String table strings, without being the same instance.
I even thing you can do:
String x = new String(“abc”);
String y = new String(“abc”);
to break this, but I’m not totally sure of that without trying.
My condolences.
Yes, that’s the way you should think about it. Note that the equals() method as defined on class “Object” does the same thing as “x == y”. It is overridden by many classes such as “String” to provide a more useful test. Should you override it, there is a basic contract your method should adhere to, which is mostly common sense:
Do not overlook overriding the hashCode() method as well when you do so.
Note also that the equals method also defines how objects are tested in the various collection classes.
[etc]
Depending on the starting point, a programmer may want to consider learning a bit of “C” first, before jumping into anything else.
Spolsky says that learning how the machine actually does stuff never hurt anybody, and ordinary “C” (not C++) is a good way to learn about pointers, etc. without having to learn assembler.
I think that OOP also has to be approached in stages. Procedural programmers probably understand methods immediately, but the idea that methods and data are both aspects of a class may seem strange, especially when a programmer tries to figure out where to “start”.
My friend is a professional in computer education, and reads a lot of (peer-reviewed) research on effective methods for teaching it. It’s been shown that hiding the computer from the student is generally better. C is better as a second or third language than a first, the best first languages are things like Python and Java. Further, it’s been shown that students that start with OOP tend to do better than students that start with purely procedural languages do when they start to learn OOP.
I’ll try to get some cites, but it really depends on how busy she is right now.
ETA: Not to mention the OP mentioned he’s a procedural programmer anyway. So he probably does understand things like pointers, but was confused because Java obfuscates what he’s used to.
Alan Kay, of course, invented Smalltalk, which is entirely based on message-passing OO and doesn’t really have a non-message-passing way of doing anything. Even math is based on passing messages around.
Why do you put C in quotes? You’re not the only one I see do it, and I’m curious.
I am not the biggest fan of Java, but in what way is it not fully OO? Do you consider multiple inheritance to be essential?
Also, IMO people new to programming probably shouldn’t start with C++. It’s a dog’s dinner now.
That’s not to turn this into a language war; I’m a fan of C++, but I’m glad I didn’t have to learn coding through modern C++.
Yeah, to reference C++ as a proper OO language is to do OO a serious disservice. Lots of C++ programmers think C++ is proper OO, but as the above quote from Alan Kay indicates, it isn’t, and real OO people regard C++ as something between bastard son and abomination.
Smalltalk is the original OO language, and it remains the reference point in many ways. Java semantics were heavily influenced by Smalltalk, but took on the C style syntax, which I suspect confuses people into thinking that it has more in common with C++ than it actually does. C++ continues to graft more an more bits onto itself, in weird ways. But it provides no intrinsic pointer security, no intrinsic automatic memory management, and many other add ons only work if you are careful not to do anything adventurous.
It is interesting to note that Smalltalk defines each of the integers as an individual object. If you have two variables, and set each to the number 1, each contains a pointer to the object representing the integer one. The operations on the number one are defined by its class, and messages get passed as needed to effect arithmetic. Clearly from an implementation point of view this has some serious drawbacks, especially on the 16 bit machines Smalltalk was originally implmenleted on. So there were under the hood optimisations and tricks. But the semantics were clear, and unvarying. Equality was always pointer equality.
Because it’s just a name (of a programming language in this case), and names are just arbitrary character strings?
/s/ Senegoid, arbitrary character string.
But he put C in quotes and not C++, which is an odd inconsistency.