insanity of Java

Started by meems, August 19, 2018, 14:19:16

Previous topic - Next topic

meems

following on from my capita thread. I've been doing Java training. I'm learning the dark secret mysteries of Java, and it makes me realize what a terrible language it is.

Consider this...

public static void main(String args[])
{
String s = "hello";
if (s == "hello") System.out.print(s) ;
}


it prints hello as expected.

public static void main(String args[])
{
String s = "hello";
s=s+" world"
if (s == "hello world") System.out.print(s) ;
}

This doesn't print hello world, because even though strings are supposed to be immutable, and all changes to strings create new strings that reside in the string pool, somehow there's a difference between s and "hello world" because s was created by string manipulations rather than just a single statement.
Its just plain stupid. == is supposed to check primitive equality and object identity. To get round this the equals method is used to do the job of == for strings.

TomToad

That is because strings are an object in Java.  You are comparing references, not the actual contents. It works in the first case because the java compiler optimizes the two string literals into the same object. Fails in the second case because concatenating the two strings creates a new object.
The correct way to compare strings is with the equals() method.
if (s.equals("hello world") )System.out.print(s) ;

C is the same way. You need to use the strncmp() function. C++ is a bit different, as the== operator has been overridden in the string class to operate as expected.
------------------------------------------------
8 rabbits equals 1 rabbyte.

meems

>C is the same way.

hard to believe until seen. C doesn't mess with a string pool does it?
Another thing with this String fuzziness is

public static void main(String args[])
{
String s = "hello"+" world"
If (s=="hello world") System.out.print(s)
}


outputs hello world. Just to mess with the if its concatted it doesn't work rule. It does work sometimes.


TomToad

What I meant about C being the same way is that the variables actually hold a pointer to the string instead of the string itself.  If you did If(string1==string2) in C, you would not get the results you expected.  Instead, you need to use if(strncmp(string1,string2) to compare the two strings.  I don't believe C optimizes the strings the same way that Java does, so if(s=="hello world" would probably fail.

As for your last example, the string is actually not being concatenated when ran.  The compiler sees 2 string literals being added together and just makes them into one long string in the executable.  It's similar how a=2+3 gets optimized to just a=5.  This output of the compiled code from my hex editor shows that the string is compiled already concatenated.
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

000000A0  0B 48 65 6C 6C 6F 20 57 6F 72 6C 64 07 00 1A     .Hello World...
------------------------------------------------
8 rabbits equals 1 rabbyte.

therevills

Strings are pretty complex objects.

Oh and for Java it is best practice to compare the string before the object:

if ("hello world".equals(s)) System.out.print(s);

Matty

Yes..as has been said-strings are unusual.  It's not insane....just a step up from blitz languages where strings are easy.

meems

> It's not insane

Ha! gotcha, now i can rant on at all the insane things in Java.

public static void main(String[] args)
{
  Byte a = 1;
  Byte b = 1;
  Byte c = a+b;
}


won't even compile because to do arithmetic operations Java converts bytes and shorts to ints, and doesn't bother converting them back, so get a can't convert int to byte error. Totally dumb. Perhaps in Java 10 Java converts bytes to strings to add them together.

TomToad

This is almost the same with C.  When adding 2 bytes, an int is used to prevent overflow.  However, when that int is cast back to a byte, there is a risk of incorrect result.  The difference between C and Java is that Java will not allow the implicit downcasting, forcing you to explicitly cast the result.  If you compile and run this C program here:
#include <stdio.h>

int main() {
char a = 100;
char b = 100;
char c = a+b;

printf("%d %d %d %d %d\n",a,b,a+b,sizeof(a+b),c);
}

you will get this result. 100 100 200 4 -56
The first two numbers are what is stored in a and b.  The third is the result of a+b without downcasting.  The fourth value shows the size of a+b. As you can see, the result is an int (4 bytes).  The fifth number is the result of a+b being stored in c.  As you can see, the last result is incorrect due to the fact that 200 is larger than can be held in a char (-128 to 127).  The fact that Java forces you to cast the result is a good thing, as it will prevent potential bugs such as this.

The correct way to do this in  Java is:
//A Very Simple Example
class ExampleProgram {
public static void main(String args[])
{
byte a = 1;
byte b = 1;
byte c = (byte)(a+b);
System.out.println(c);
}
}

One thing I don't like about java is lack of unsigned types, especially unsigned bytes.  In C, you have unsigned char for values from 0 to 255.  In Java, you need to use a short.
------------------------------------------------
8 rabbits equals 1 rabbyte.

Steve Elliott

#8
Please don't dis C.  C is very consistent and compact.  There are no surprises with C, if you know what you're doing - unlike some other languages.
Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb

TomToad

Not trying to dis C.  Just trying to point out that many of the problems in Java also exists in other languages.  Sometimes not even a problem, but often a solution to an existing one.  Yeah, it might seem annoying to have to cast your bytes when you want to do math on them, but spending a few minutes typing (byte) can save a few hours of wondering why your math formula is returning incorrect results.
One isn't necessarily better than the other, C was created for systems programming and needs the flexibility.  Java was originally created for 'applets' to be run on a network, so bug prevention and security are a priority.  Every language have there little idiosyncrasies, you just need to learn what ones your chosen language has, and why.
------------------------------------------------
8 rabbits equals 1 rabbyte.

Steve Elliott

#10
Quote
Not trying to dis C.  Just trying to point out that many of the problems in Java also exists in other languages.

No they don't.  C is consistent, while other languages build upon C and try and take the glory.  So some lead to chaos lol.
Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb