Java String compare

Programming, for all ages and all languages.
B.E

Java String compare

Post by B.E »

Hey,

Why am i getting these values

Code: Select all

         String s1 = "Hello";
         String s2 = "Hello";
         String s3 = new String("Hello");
         String s4 = new String("Hello");
      
         System.out.println((s1 == s2));
         System.out.println((s3 == s4));
         System.out.println((s3 == s1));
         System.out.println((s1.equals(s2)));
prints

Code: Select all

true
false
false
true
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Java String compare

Post by Colonel Kernel »

B.E wrote:Why am i getting these values

Code: Select all

true
Because s1 and s2 refer to the same object.

Code: Select all

false
Because s3 and s4 refer to different objects.

Code: Select all

false
Because s3 and s1 refer to different objects.

Code: Select all

true
Because s1 and s2 contain the same sequence of characters. This is trivially true since they are actually the same String object. A more interesting test would have been s3.equals(s1), which also would have returned true.

To explain why these results happen:

Code: Select all

         String s1 = "Hello";
This assigns s1 to refer to a String object containing the string constant "Hello". The instantiation of this String object is invisible to you -- the compiler and run-time cooperate to make it happen AFAIK.

Code: Select all

         String s2 = "Hello";
The compiler (or runtime, not sure which) is smart enough to notice that this "Hello" is the same as the previous "Hello", so it assigns s2 to refer to the same object as s1. This is called "interning".

Code: Select all

         String s3 = new String("Hello");
This allocates a new string object on the heap and gives it the value "Hello". The compiler/run-time can't intervene here, because you explicitly asked to create a new String object.

Code: Select all

         String s4 = new String("Hello");
Same case as for s3.

By the time all is said and done, you have three objects -- s1/s2, s3, and s4.
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
B.E

Re:Java String compare

Post by B.E »

thank you.

My teacher today said that

Code: Select all

s1 == s2
wouldn't work, but when we tried it, it didn't work. The teacher didn't know why, so he asked us to work it out.
JoeKayzA

Re:Java String compare

Post by JoeKayzA »

B.E wrote: thank you.

My teacher today said that

Code: Select all

s1 == s2
wouldn't work, but when we tried it, it didn't work. The teacher didn't know why, so he asked us to work it out.
I wouldn't rely on this behaviour, I think it's not _guaranteed_ by the java language/runtime explicitly.

Let's assume you have a two strings in two different source files, which are both initialized like

Code: Select all

 String s = "Hello"; 
then comparing them with "==" will probably return false (I didn't test it right now, but I believe it does). The only situation where "==" is defined to return true is when the compared variables got assigned exactly the same object. (like: "s1 = "Hello"; s2 = s1"). When you want to compare the string's contents, you should always use the "equals"-method anyway.

cheers Joe
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Java String compare

Post by Solar »

There's your problem with Java. They tell you it's better than e.g. C++ because it doesn't have pointers, but as a matter of fact, it does, and you are better off understanding pointers if you want to understand the fine print of what is happening.

Here is a good article on the subject. In short: equals() compares whether two strings have the same content. The operator "==" compares whether two strings are identical, i.e. are the same instance. In C++, that would be the difference between comparing *x == *y / x == y, respectively, if x / y were pointers to type string.
Every good solution is obvious once you've found it.
chasetec

Re:Java String compare

Post by chasetec »

Solar wrote: There's your problem with Java. They tell you it's better than e.g. C++ because it doesn't have pointers, but as a matter of fact, it does, and you are better off understanding pointers if you want to understand the fine print of what is happening.
Depends on who "They" are :) I'm a Sun Java instructor and pointers are one of the first things I talk about after covering the really basic stuff like hello world, methods, and loops. I tell everyone that if they heard Java didn't have pointers that they have been mislead. We just have pointers that you can't do arithmetic on and don't have to dereference. Since we can't do that stuff we like to call them references but one of evey first errors every Java programmer will run into is a runtime error of a NullPointerException.

To the OP: Also look at the intern method http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern()
B.E

Re:Java String compare

Post by B.E »

I've been doing java for 3 weeks now, I'm not really liking java.

Moreover, Java lacks the fundamental "features" that most languages have. for example it don't have default arguments, Which kind of sucks because I loved using them in C/C++ and Delphi and until recently java didn?t have a "easy" way of getting input from the keyboard(terminal). But to Java's credit it does have RTTI(Runtime Type Identification) and the ability to find out all kinds of information about a class, like it's fields and methods(which i can't see any reason to do so). Also the garbage collector is very helpful

As for pointers, I think java does implement them the right way. Java is a cross platform language. Meaning unlike C/C++ you don't have to recompile the program for each OS, which means that you don't have to distribute your source code. Anyway because there isn't any pointers. it means that the soft way can run on any architecture without recompilation. Another fact about pointers that it they are a security risk, meaning that with traditional languages, buffer overflows could occur with lazy programmers. which means that well crafted data could make the program execute any code.

As I am writing this, i am starting to like it now.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Java String compare

Post by Solar »

Misplaced (and misinformed) language bashing.
Every good solution is obvious once you've found it.
Kemp

Re:Java String compare

Post by Kemp »

Also the garbage collector is very helpful
If you can't be bothered doing it youself, yeah...
buffer overflows could occur with lazy programmers
Laziness again...

As far as I'm concerned, the only advantage of Java is that it'll run on any system that has a JVM. Of course, that's only "in theory", the history of Java is full of buggy, incomplete and not-quite-compliant JVMs.

If you want something cross-platform and actually useful then consider Python. And yes, I *am* bashing Java, but having been forced to use it for far too long I have at least a temporary right to :P
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Java String compare

Post by Colonel Kernel »

Kemp wrote:
Also the garbage collector is very helpful
If you can't be bothered doing it youself, yeah...
buffer overflows could occur with lazy programmers
Laziness again...
Bah, I'm so tired of hearing this argument... >:(

<rant preamble="This is not a rant in favour of Java, but rather in favour of GC">
Do not ascribe moral characteristics to the use of a particular tool, especially one as useful as GC.

Am I lazy because I set mousetraps instead of sitting in front of the hole in my wall with a butcher knife? There are reasons why we invented tools -- to make our lives easier.

Ok, maybe it's a bad analogy because to the best of my knowledge GC doesn't kill other living creatures, but hopefully you get my point. ;D

GC has a ton of benefits besides making life easy for "lazy" programmers:
  • Non-lazy, but rather tired overworked programmers might not notice the presence of memory leaks or double-deletion bugs in their code. Not a problem with GC.
  • GC makes the implementation of certain lock-free techniques significantly easier. Ever heard of "hazard pointers"? This is the kind of brittle stuff you have to invent if you want to do lock-free programming in a language like C++ that lacks GC. Ick.
  • GC is the mechanism of choice for making dynamic memory allocation possible in type-safe languages. It's not the only way, but it is certainly the easiest and most well-established way (i.e. -- other techniques are still the subject of active research).
  • GCs can work in tandem with OSes to make much smarter decisions about virtual memory management (this is not true of mainstream OSes, yet).
I could go on, but I have real work to do. In short, I'm really @#)$(*@ tired of being tarred with the same brush as "lazy programmers" just because I happen to like GC. So knock it off.
</rant>
As far as I'm concerned, the only advantage of Java is that it'll run on any system that has a JVM. Of course, that's only "in theory", the history of Java is full of buggy, incomplete and not-quite-compliant JVMs.
Even more of a problem is the lack of consistent APIs if you're trying to do anything of reasonable complexity. Right now I'm working on a web service that does a lot of custom serialization, and lo and behold the same APIs that work on JBoss don't work on WebSphere... Ack! I don't mind Java-the-language so much (although I like C# better), but I really hate J2EE!
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
Kemp

Re:Java String compare

Post by Kemp »

Of course there are legitimate reasons for garbage collection to exist, but in general you have to be doing pretty good things to make the points relevant (locks, dynamic mem alloc). Problem is that if people start in Java before having to do these things in a non-collected language then they don't get exposed to the potential problems and often have no idea the potential problems exist as "it all just works". Then they try it in a language like C and things start going wrong. I've come up against that a lot, and had to solve more than my fair share of memory leaks due to the person not realising that it doesn't "just work" in a non-collected language. Luckily this was at university level and not out in the real world where there might have been real problems. Then of course, I know people who use Java purely because they can'tbe bothered with memory stuff even in relatively simple projects.

Sorry if I caused offense, I know there are legitimate uses, I've just seen too much of the opposite.
chasetec

Re:Java String compare

Post by chasetec »

Solar wrote: Misplaced (and misinformed) language bashing.
LOL, I think you gave permission for the language bashing to start :)
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Java String compare

Post by Solar »

This is like the "stable API/ABI" Linux kernel discussion, or Open Source vs. earning money, or C vs. C++... you never get to hear new arguments, and you get to the point where you cannot bear to hear the old ones. ;)

But since we're at it, someone give me a GC system that a) deterministicly calls my destructors when an object goes out of scope so I can actually do something useful in them, b) allows me to pointer around to my heart's content when I happen to do hardware-oriented programming, c) doesn't add additional overhead and random performance hits when the GC starts up, and I'll be a happy camper.

Since that isn't about to happen, I will continue to use the one perfect programming language, which is either the one my employer tells me to use, or the one best suited to my project. ;D

I like Perl and its GC when I'm about to sift through gigabytes of log files. C is the perfect language to write a kernel in IMHO. I generally prefer C++ because it has string, vector, namespaces, classes, and because I like the "geek" feeling it gives me to call the ugliest mainstream language alive my "primary" language. I loathe Microsoft, but C# is a nice thing if you have to come up with a GUI for a Windows app real quick, and isn't too shabby in other regards either. Nothing beats a quick shell script to automate repetitive tasks. Java paved the road for JIT, GC and other nice technologies, but it ain't the Holy Grail either. I wish I knew enough of Python and Lisp to add them to the list.

Can we get over the "my language is better than yours", and return to the state of grown-up developers quickly, please? 8)
Every good solution is obvious once you've found it.
Kemp

Re:Java String compare

Post by Kemp »

Well my part in the argument is over, my points are easy to make and already made :)

In terms of learning Python, you really should. It's incredibly quick to pick up and is very very powerful once you learn some of the more neat tricks. I would advise learning from samples and suchlike though as the online documentation isn't too helpful. As an example of one neat trick, take this for returning a coordinate from a function:

Code: Select all

def GetCoord:
  # Do stuff here and assign parts of coord to x, y and z
  return x, y, z

# Code and stuff here, and then in whatever piece of code...

x, y, z = GetCoord()   # these x, y and z are different to the above ones btw

# Or if you have a list containing the coordinate...

x, y, z = coord[:3]
It may not look like much, but the ability to return and assign completely arbitrary groups of things is a lifesaver in some cases and reduces the code considerably in quite a few cases. Then you have all the usual stuff like general-purpose iterators, arbitrary lists and other useful little bits that let you just write what you want it to do rather than writing stuff that you don't really care about.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Java String compare

Post by Colonel Kernel »

Solar wrote:But since we're at it, someone give me a GC system that a) deterministicly calls my destructors when an object goes out of scope so I can actually do something useful in them, b) allows me to pointer around to my heart's content when I happen to do hardware-oriented programming, c) doesn't add additional overhead and random performance hits when the GC starts up, and I'll be a happy camper.
Sorry, I know you wanted this discussion to end, but I'm going to take this bait and have a big hook in my mouth. Maybe I'm just a masochist. ;)

a) You've touched on the one thing about most GC systems that I am vehemently opposed to -- finalizers. Finalizers suck. They cause overhead, they make no guarantees about when your resources will be freed, etc. They are just a Bad Idea. I think the best mix is GC for memory only, and a scoped RAII-like idiom (or ref-counting) for managing non-memory resources (files, network connections, etc.). Java totally lacks this alternative -- at least C# has the using statement, and of course C++ has destructors and smart pointers.

b) When you're doing hardware-oriented programming, you're probably going to be doing things that violate any guarantees about type safety. The best solution to this that I've seen is C#'s "unsafe" block. Inside an unsafe block, you can use pointers to your heart's content. The only requirement is that if you want to "pointer around" in a GC'd data structure, you need to "pin" it first. C#'s "fixed" statement pins an object on the GC'd heap in a scoped manner. "unsafe" in C# allows the compiler to distinguish between "pure" verifiably type-safe code and potentially unsafe code. This is how the Singularity guys managed to write 95% of their kernel in C# and still have most of that be verifiably type-safe.

c) I hear you... compacting collectors do not fit this bill. The best I've heard of is the GC in .NET, which can do a collection in the time it would take to service a hard page fault -- still too long for real-time applications. However, there are other kinds of GC that are designed for real-time applications (e.g. -- the concurrent mark-sweep collector in the Singularity kernel). I haven't looked at them extensively, so I can't really add anything more.

But yes, by all means keep using C++ if that floats your boat... :)
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
Post Reply