Skip to main content

"string" primitive

72 replies [Last post]

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jwenting
Offline
Joined: 2003-12-02

Maybe the + operator wasn't such a good idea, but that doesn't mean we should want MORE bad ideas implemented...

podlesh
Offline
Joined: 2004-07-26

Reply to original post:
> I would consider it more a convenience function. I
> know there are:
> .equals(String)
> but 9/10 times when I want to compare strings I am
> doing an value comparison, not object comparison.

There is much, much better proposal on this forum: introducing new operator, something like:

if (s1 eq s2) ...

which whould expand into:

if ( ((s1==s2) || (s1!=null && s2!=null && s1.equals(s2))) ) ...

This is sensitive proposal: it doesn't break anything (except it introduces new keyword), it doesn't cause confusion, it's simple and saves typing/space. Question is , if it's really needed (I think that it isn't, but it's still better idea then autoboxing in 1.5).

fuerte
Offline
Joined: 2004-11-22

I still think that == is a natural syntax for comparing values for primitives and built-in primitive-like objects. Point is, that currently == can't be used with built-in types, because it is too unpredictable:
[code]
Integer i = 1;
Integer j = 1;
System.out.printf("1: %s\n", i >= j);
System.out.printf("2: %s\n", i <= j);
System.out.printf("3: %s\n", i == j); // SUCCEEDS BECAUSE OF CACHED VALUE
i = new Integer(1);
j = new Integer(1);
System.out.printf("4: %s\n", i >= j);
System.out.printf("5: %s\n", i <= j);
System.out.printf("6: %s\n", i == j); // FAILS BECAUSE DIFFERENT OBJECT
i = 123456;
j = 123456;
System.out.printf("7: %s\n", i == j); // FAILS BECAUSE VALUE OUT OF CACHED RANGE
Boolean b1 = true;
Boolean b2 = true;
System.out.printf("8: %s\n", b1 == b2); // SUCCEEDS BECAUSE OF CACHED VALUE
b1 = new Boolean(true);
b2 = new Boolean(true);
System.out.printf("9: %s\n", b1 == b2); // FAILS BECAUSE DIFFERENT OBJECT
String s1 = "asdf";
String s2 = "asdf";
System.out.printf("10: %s\n", s1 == s2); // SUCCEEDS BECAUSE OF CACHED VALUE (IN MODULE)
s1 = new String("asdf");
s2 = new String("asdf");
System.out.printf("11: %s\n", s1 == s2); // FAILS BECAUSE DIFFERENT OBJECT
s1 = s1.intern();
s2 = s2.intern();
System.out.printf("12: %s\n", s1 == s2); // SUCCEEDS BECAUSE OF CACHED VALUE (IN RUNTIME)
[/code]
Changing == would not break any (working) programs.

pholthuizen
Offline
Joined: 2005-02-12

No, please don't. Go coding C# there you have value types, I hate them as it just introduces bugs, really. The difference in behaviour between reference and value types is just errorprone.

I would rather opt for compiler warnings on the operators "=" and "==" within expressions (with annotation support of course).

I rather want to have no primitive types at all and use .equals everywhere.

fuerte
Offline
Joined: 2004-11-22

+9999999999999

Of course I agree! :-)

But it would be better if the regular String would work this way. The point is, that it would not break any (working) code if it worked this way. It would not break any (working) code if String and Integer comparison with == and != compared the value instead. == already compares the value for *some* Strings and *some* Integers, why not for all?

And String is a kind of primitive anyhow, because the language has "" for creating them, just like 123 for creating primitive ints.

fred33
Offline
Joined: 2005-08-16

Just to clear up a few confusions here, in Java, Strings are not primitive, in any form. As with arrays, Strings are full fledged instances of Object. Claiming String is a kind of primitive simply isn't true. The 'String a="hello";' syntax you refer to is just a shortcut that is built into the language to avoid having to do something like 'String a=new String(new char[] {'h','e','l','l','o'});'. If this wasn't in the compiler, Java would have been dumped before it even got to the 1.0 stage. ints, longs, etc. ARE true primitives, but Strings are objects like Integers. When you write the shortened version, the compiler replaces it by creating a String class constant of the same value, and then replacing all occurences of that String with a reference to the pre-made object. The nearest in Java source is the following:

public class Ex1 {

public void meth1() {
String b="hello";
String c="hello";
}
}

is converted to:

public class Ex1 {

private final static String a=new String(......);

public void meth1() {
String b=a;
String c=a;
}
}

which is why when you create Strings in this way, the == operator will always return true if their contents are the same since they point to the same object (oops I forgot, Java doesn't have pointers ;-).

Unfortunately, changing String to work the way you describe could actually break a far amount of code, since if two String objects have been created, they are different objects, and MUST be distinguishable (i.e. a!=b) even if their contents are the same. Think databases objects and other non-unique identifiers, if the language suddenly started to report distinct objects as being the asme just because their members are the same, whole applications could fail.

Saying that == already compares the value for some Strings and Integers is also bunkem. The == operator (again as specified in the language spec) NEVER does value comparisons and as far as I know, NEVER has, and lets hope to god it never does in the future. All this operator ever does is a identity comparison, i.e. is one object reference refering to the same instance as another. The reason it seems to work for some strings is as I explained above, the compiler creates constants for literal strings then makes the references point at the same object. You can prove this by running this example:

String a=new String("hello");
String b=new String("hello");

System.out.println(a==b);

which will return false even though the Strings contain the same characters. This happens because using the String constructor explicity forces the runtime to create two separate objects so comparing the identities gives false. This is also true of Integers. The only time I can think of when comparing different Integer objects will return true, even though they are apparently different objects is if autoboxing is in use in Java 1.5, where the Integer class maintains a cache of "common" Integer values like 1 to 100 so only one ever gets created to save memory, so:

Integer a=5;
Integer b=5;
System.out.println(a==b);

could conceivably return true, though I haven't tested this particular example.

fuerte
Offline
Joined: 2004-11-22

Your message just points out the problems in Java. Saying that

String a = "asdf";

is different than

String a = new String("asdf");

is crazy, because without knowing the internal workings of Java, the programmer would expect them to mean exactly same. And because the following works for string literals, then it should work in *every* case.

String a = "asdf";
String b = "asdf";
if (a == b) printf("true");

The case is exactly the same with autoboxed and cached integers. It is crazy that Integer works differently with some values.

If Java was designed from scratch now, String and Integer comparison with == would *always* compare the values, not just sometimes.

tsinger
Offline
Joined: 2003-06-10

> Saying that
>
> String a = "asdf";
>
> is different than
>
> String a = new String("asdf");
>
> is crazy, because without knowing the internal
> workings of Java, the programmer would expect them to
> mean exactly same.

I can't follow your argumentation. Any developer will know, that "new Anything()" creates a new object. If if you are teached that the == operator for objects compares the references, (s)he would know that the resulting comparison always will be false.

> The case is exactly the same with autoboxed and
> cached integers. It is crazy that Integer works
> differently with some values.

For me it is crazy, that auto(un)boxing was added to Java, it is just a source of subtle bugs built-in for lazy developers.

My 0.02EUR
Tom

fuerte
Offline
Joined: 2004-11-22

> > Saying that
> >
> > String a = "asdf";
> >
> > is different than
> >
> > String a = new String("asdf");
> >
> > is crazy, because without knowing the internal
> > workings of Java, the programmer would expect them
> to
> > mean exactly same.
>
> I can't follow your argumentation. Any developer will
> know, that "new Anything()" creates a new object. If
> if you are teached that the == operator for objects
> compares the references, (s)he would know that the
> resulting comparison always will be false.

So are you saying that

String a = "asdf";

does not create a new object?

sjasja
Offline
Joined: 2004-08-15

> String a = "asdf";

That line indeed does not create any objects.

When a class containing that line is loaded, the class loader creates a String object that contains the string "asdf". When the above line is executed, the reference to the String object created by the class loader is assigned to the variable "a".

If you execute that line a million times in a loop, only one object is created, not a million. And that object creation happens when the class is loaded.

fuerte
Offline
Joined: 2004-11-22

> > String a = "asdf";
>
> That line indeed does not create any objects.
>
> When a class containing that line is loaded, the
> class loader creates a String object that contains
> the string "asdf". When the above line is executed,
> the reference to the String object created by the
> class loader is assigned to the variable "a".
>
> If you execute that line a million times in a loop,
> only one object is created, not a million. And that
> object creation happens when the class is loaded.

Semantics. Indeed a string object is created, but not in the same way as

new String("asdf")

but that could change, if the compiler would be optimized a bit, as happened with JDK 5.0 cached integers.

sjasja
Offline
Joined: 2004-08-15

> Semantics.

Yes, exactly! No new object is created; a reference to a previously created object is assigned to a variable. That is the semantics, i.e. meaning, of the code fragment.

Semantics (n): the study of meanings.

> Indeed a string object is created

Execution ot the line creates no objects. You can try it yourself:
[code]
public class Test
{
public static void main(String args[])
{
String previous = "asdf";

while (true) {
String a = "asdf";
if (a != previous)
System.out.println("a new object was created!");
previous = a;
}
}
}
[/code]
Let us know if that suddenly starts creating new objects.

> but that could change, if the compiler would be
> optimized a bit, as happened with JDK 5.0 cached
> integers.

No. "new String()" creates a new String object. You can try it yourself:
[code]
public class Test
{
public static void main(String args[])
{
String a = "asdf";
String b = new String(a);
if (a != b)
System.out.println("a new String was created");

Object x = new Object();
Object y = new Object();
if (x != y)
System.out.println("a new Object was created");
}
}
[/code]
Both println's will be executed in Java. Changing that would not be optimization, it would be a change in the semantics (= meaning) of Java. Program transformations that break language semantics are not valid optimizations.

Cached integers work by not invoking the "new" operator.

Check out chapter 15.9 of the Java Language Specification 3rd ed to see what "new" does. 15.9.4 discusses the run-time semantics.

fuerte
Offline
Joined: 2004-11-22

Okay, let me take another approach... :-)

Question: When do you use == with Strings or Integers?

Answer: Never.

That's why == should be fixed to compare the value instead. Because >= and <= already works with Integers, so should ==.

(And because == already works in some cases, but not always.)

fred33
Offline
Joined: 2005-08-16

> Okay, let me take another approach... :-)
>
> Question: When do you use == with Strings or
> Integers?
>
> Answer: Never.

How about when checking static final constants similar to an int enumeration pre 1.5? Or when I want to see if two Strings are the same object?

> That's why == should be fixed to compare the value
> instead. Because >= and <= already works with
> Integers, so should ==.
>
> (And because == already works in some cases, but not
> always.)

>= and <= works when comparing Objects? don't think so. This is yet another example of syntax enhancements like autoboxing fogging what is actually happenning with the Integers you are comparing. If you are finding parts of your code that are working with the == operator and not with others then again, go and read the API spec for Object.equals() and the language spec for the == operator. If you want value comparisons use the .equals() method, this will ALWAYS work for this purpose with Strings, as it has since 1.0 That is why its there. Also remember that value comparisons take a lot more time than simply comparing references, so from a performance point of view, if == always dived into a method to compare all a classes members, some programs would take a massive hit.

fuerte
Offline
Joined: 2004-11-22

> > Okay, let me take another approach... :-)
> >
> > Question: When do you use == with Strings or
> > Integers?
> >
> > Answer: Never.
>
> How about when checking static final constants
> similar to an int enumeration pre 1.5?

That is depreceated. There is a better enum feature in 1.5.

> Or when I want to see if two Strings are the same object?

Why would you? Then you can cast to object.

> > That's why == should be fixed to compare the value
> > instead. Because >= and <= already works with
> > Integers, so should ==.
> >
> > (And because == already works in some cases, but
> not
> > always.)
>
> >= and <= works when comparing Objects?

Yes, it works with Integers.

> don't think
> so. This is yet another example of syntax
> enhancements like autoboxing fogging what is actually
> happenning with the Integers you are comparing. If
> you are finding parts of your code that are working
> with the == operator and not with others then again,
> go and read the API spec for Object.equals() and the
> language spec for the == operator. If you want value
> comparisons use the .equals() method, this will
> ALWAYS work for this purpose with Strings, as it has
> since 1.0 That is why its there. Also remember that
> value comparisons take a lot more time than simply
> comparing references, so from a performance point of
> view, if == always dived into a method to compare all
> a classes members, some programs would take a massive
> hit.

But programs do not use == with Integers and Strings, so there would be no hit.

sjasja
Offline
Joined: 2004-08-15

Lots of people have learned to compare strings using:

.EQ. in Fortran.
strcmp() in C.
string= in Common Lisp.
string=? in Scheme
= in Pascal.
== in C#.
equals() in Java.
etc etc.

If a programmer has trouble learning such a simple thing and instead insists on the world changing to his pre-set mind, he is not going to have an easy career ahead of him.

Compare strings using equals(). Learn the simple fact that when applied to objects, == compares object identities. "Problem" solved. The ability to learn such things will help learn other languages too.

fuerte
Offline
Joined: 2004-11-22

It's not that. I have programmed with most of those languages with no difficulties, but I just wanted to make Java syntax better, more beautiful.

Also, == would not mean .equals(). It would mean:

1) return true if both object references are equal (non-null or null)

2) return false if either one is null

3) only then compare values, and return true if values are equal

See the difference? == would work with null strings, there would be no null exceptions ever.

fred33
Offline
Joined: 2005-08-16

> It's not that. I have programmed with most of those
> languages with no difficulties, but I just wanted to
> make Java syntax better, more beautiful.

A beautiful language is one with clearly defined semantics where things have one purposem, I just can't see how that is going to happen if == suddenly starts taking a new meaning. This is precisely the reason I despise this:

Integer a=5;

fuerte
Offline
Joined: 2004-11-22

> A beautiful language is one with clearly defined
> semantics where things have one purposem, I just
> can't see how that is going to happen if == suddenly
> starts taking a new meaning. This is precisely the
> reason I despise this:
>
> Integer a=5;

But == already compares the value with primitives. It already has two meanings. The suggestion with Integers and Strings is that == would compare the value only if the object references are different. It just would make the life easier, and the syntax simpler. Think about the following:

if (s != null && s.equals("test"))

How many times have you seen that? Why not write it simply:

if (s == "test)

makeworld
Offline
Joined: 2005-08-21

> Think about the following:
>
> if (s != null && s.equals("test"))
>
> How many times have you seen that? Why not write it
> simply:
>
> if (s == "test)

Normally it should be written

if ( "test".equals ( s ) ) {

}

Clean coding conventions are not just about style

podlesh
Offline
Joined: 2004-07-26

More civil reply: no, this is not a good idea. What you suggest is just syntactic sugar, type-sensitive preprocessor.

BTW: Strings are not primitives. String is composite type.

jwenting
Offline
Joined: 2003-12-02

-100000000000000000000

If you want string primitives use a non-OO language. I'd rather see ALL primitives dropped than see more of them introduced.
And no, I am not screaming for that to happen. If I want that I'll use a language that has no primitives.

Learn to use the tools you have instead of whining and screaming for destroying the language by turning it into something else entirely.