| Computer Gripes | documenting the down side of computer stuff |
|
HomeSearchMerchandiseAboutMichael HorowitzMy CNET Blog
|
| Index: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ALL |
![]() |
Java GripesJava is a programming language |
![]() |
| This page has the following Java gripes: Wrong Results On Purpose, Small Number Math, Applets, First Impression, If Tests, What Version of Java is a Web Browser Using?, Divide By Zero, Static Fields, Executing class files in Windows, Quirk with Inheritance, classpath, Servlets and cookies and Other Gripers. |
October 26, 2007. I expanded on the point below in my CNET blog. See Why Java can't do addition correctly.
February 9, 2001. Java 2 version 1.3.
The Java code below produces the wrong results. This is not
a bug or an ancient Java compiler at work. It was done on purpose by the
designers of the language. The code compiles fine with Java2 version 1.3. It
produces no error indication at run time.
int var1, var2, var3; // declare three integer variables
var1 = 2111000333; // assign a value to var1
var2 = 1000222333; // assign a value to var2
System.out.println("var1=" + var1);
System.out.println("var2=" + var2);
var3 = var1 + var2; // add two numbers
System.out.println("var3=" + var3);
Running the above code produces the following:
var1=2111000333
var2=1000222333
var3=-1183744630 <--Wrong!
The largest integer number in Java is 2,147,483,647 (just over 2 billion). The values assigned to var1 and var2 in the example above were chosen so that when added together they would exceed the maximum capacity of an integer variable. Rather than return an error, Java adds two positive numbers and returns a negative number, the wrong answer. Proponents of Java tout the fact that it is a strongly typed language. Well yes, but...
Criticism is sometimes leveled at scripting languages for not being strongly
typed. Below is VBScript code equivalent to the Java code above. Note than
VBScript, variables are declared with a dim statement but no reference is made
to the type of data the variables will hold. This contrasts with Java where, in
the example above, the variables were declared to hold 32 bit integer values
(int).
<%
dim var1, var2, var3 'declare three
variables
var1=2111000333
var2=1000222333
response.write "var1 = " & var1 & "<br>"
response.write "var2 = " & var2 & "<br>"
var3 = var1 + var2 ' add two
numbers
response.write "var3 = " & var3 %>
When the above code was under Active Server Pages, it produced the correct
answer:
var1 = 2111000333
var2 = 1000222333
var3 = 3111222666
And what of Java's namesake, JavaScript? The below JavaScript code was run under Internet Explorer version 5.
<script language="javascript">
var var1, var2, var3; //declare three
variables
var1=2111000333;
var2=1000222333;
document.write("var1 = " + var1 + "<br>");
document.write("var2= " + var2 + "<br>");
var3 = var1 + var2;
//add two numbers
document.write("var3= " + var3 + "<br>");
</script>
It too, produced the correct results:
var1= 2111000333
var2= 1000222333
var3= 3111222666
Java has a byte data type for 8 bit numbers.
If you add two byte variables and store the result in a byte variable you get a
compile time error. This is an operation analogous to the prior gripe which
compiled fine (think "consistent"). The reason is that Java does the
addition using 32 bit integers (int) despite the
fact that the variables are 8 bit bytes. This code:
byte x, y, z;
y=10; z=30;
x = y + z;
results in a "possible loss of precision" error. The compiler is warning
that something can go wrong moving a 32 bit int
variable into an 8 bit byte variable. This is
true. Who asked it for a 32 bit int in the first
place?
You can get around this compiler error, by telling Java to force the 32 bit
temporary field into your 8 bit field as such:
x = (byte) (y + z); //casting
This compiles just fine.
The largest positive number that Java allows in a byte
field is 127. Changing the values of the y and z variables such that the sum is
larger than 127 results in incorrect output, much like the prior gripe. The code
below:
byte x, y, z;
y=120; z=10;
x = (byte) (y + z);
results in the x variable having a value of -126.
In summary, if you do everything correctly (byte variable plus byte variable = byte variable) the Java compiler objects. When you work around the compilers objection, you get wrong results and no error indication. The exact same situation exists with 16 bit integers (short). February 9, 2001. Java 2 version 1.3.
The following is a quote from the book Core Java 2 Fundamentals Volume 1 by Cay Horstman and Gary Cornell. The book was copyrighted 2001 by Sun Microsystems and covers J2SE version 1.3. Chapter 10 is on Applets. On page 580 it says:
"If you are not on an intranet, don't use applets."
Pert near heresy. The authors discuss the fact that each web browser supports a different and inevitably old JVM. Although, Sun has a Java plug-in that shoehorns a brand new JVM into an old web browser, the user effort to deal with this is extensive. The programmers effort to deal with the Java plug-in is not trivial either. The authors conclude that it is "probably unreasonable" to expect non-technical visitors to a web site to install the Java plug-in.
In place of Java applets, the authors suggest client side scripting (JavaScript most likely) for validating data, animated GIFs for animation effects and plain old HTML forms for data entry. (March 3, 2001)
Java does not make a good first impression to someone writing their first
"Hello World" program. First there is the baggage of declaring a class
and defining the program entry point with "Public
Static Void Main (String[], args)." Then comes compiling and
executing the program.
javac HelloWorldProgram.java
java HelloWorldProgram
The java compiler is javac. Fine, makes plenty of sense. The java run time environment however is not javar (Java Runtime) or javae (Java Execute) or even JVM (Java Virtual Machine). All of these would make sense, at least to me. Instead, its java. Not the most self-descriptive name. Using its own terminology, java is overloaded. It's both the name of the language and the command used to execute compiled Java programs.
Compiling the program HelloWorldProgram.java creates a class file called HelloWorldProgram.class. Because of this standard, when you execute a program with the java command you don't have to type the ".class". Ok. But you can't type the ".class" if you wanted to. Why would you want to? To be consistent. You must type the ".java" at the end of the program name when compiling the program. It is impossible to be consistent, that is, have both commands specify the suffix or both commands not specify the suffix. Sure most Java programmers use an IDE and don't deal with this, but it does not make a good first impression.
If you make a suffix related mistake the error messages are not the most
useful. Leaving off the ".java" when compiling a program, results in
invalid argument:
HelloWorldProgram
Adding the ".class" when executing a compiled program results
in:
Exception in thread "main" java.lang.NoClassDefFoundError:
HelloWorldProgram/class
Not the most obvious error messages.
Then there is case sensitivity, which is fine in the language itself, but with Java it even applies to file names when the host Operating System doesn't care about case in file names. February 21, 2001. Java 2 version 1.3.
On a related note, when a Java applet is included in a web page using the <APPLET> tag, the source of the applet is the full file name, including the ".class" extension. Consistently inconsistent. March 3, 2001
| if (a=b) | does not work in Java. Instead |
| if (a==b) | is the required syntax. You must use two equal signs. Why? Many other programming languages have compilers that are smart enough to differentiate between IF statements and assignment statements. |
| February 9, 2001. Java 2 version 1.3 . |
What Version of Java is a Web Browser Using?
This question is much harder to answer than it should be. Towards this end, I created a web site called Java Tester that explains what I know about determining and testing the version of Java on your computer. Java Tester has a test that will tell you if your web browser can run Java applets. If it can, there is an applet there that displays the Java version from the horse's mouth. It also includes instructions for installing Java. ( March 3, 2001, revised January 12, 2003)
A web browser that supports Java applets, runs them inside a web page. The browser includes a Java Virtual Machine (JVM) that interprets and executes the Java applets. There have been many different versions/releases of Java and JVMs. As far as I can tell Internet Explorer 5 says nothing anywhere about the JVM it is using. A Help->About in Netscape Navigator 4.x says it uses Java, but nothing about the version/release.
A Help->About Plug-ins in Navigator 4.x shows confusing information about a Java plug-in, assuming the JDK has been manually installed on the computer. A copy of Navigator 4.72 under Windows NT4 there were three separate plug-in entries all identified as "Java Plug-in 1.3 for Netscape Navigator". A copy of Navigator 4.75 under Windows 98 showed the same thing. A copy of v4.73 on a brand new Windows 2000 machine (with no JDK installed) said nothing at all about Java.
This brings up another gripe: which version 1.3? Old Java was called version one and had a version that was at the time, called 1.3. New Java is called Java2 and it too has a version 1.3. When something like Navigator says it is version 1.3 there is no way to know if it is version 1.1.3 (old) or version 2.1.3 (new). (February 13, 2001)
David Strom wrote about this in The Trouble with Java. December 28, 2002. Quoting: "Sometimes you need a full client copy of Java, sometimes it comes to you care of your Web browser, and sometimes it comes as part and parcel of the operating system. And sometimes you don't just know, and have to play Java Detective."
In the Langa List newsletter of January 13, 2003, a reader wrote of problems with the Microsoft JVM. His Windows 98 JVM got corrupted, and he uninstalled it...only to learn later that Microsoft no longer provides a JVM for Windows 98. He then downloaded the Sun JVM from their web site and all was well. Until, that is, he applied an urgent patch from Microsoft. The patch was to the Microsoft JVM which he didn't have. This caused problems that seem to be unfixable.
The Java2 v1.3 compiler accepts dividing an integer by zero:
int x = 2;
x = x / 0;
A gripe could be made that the compiler should be able to detect this and
issue an error.
At run time however, this fails, as expected, with an arithmetic exception of
divide by zero.
The same compiler also accepts dividing a floating point number by zero:
double d = 2.2;
d = d / 0.0;
At run time however, this does not fail. To better illustrate, consider
this code
double d = 2.2;
d = d / 0.0;
System.out.println("d="+d);
d = d + 1.1;
System.out.println("d="+d);
Which produces this output:
d=Infinity
d=Infinity
At a minimum, the gripe is that Java is not consistent. In my opinion, division by zero should be an error. (February 13, 2001 Java 2 version 1.3)
As shown
above, Java allows arithmetic with infinity. The example above adds a floating
point number to infinity, it also lets you add integers to infinity
(resulting in infinity). I find it bizarre that Java lets you
cast infinity to other data types without producing an error.
Here are some casting results:
infinity cast to short
results in
-1
infinity cast to int
results in 2147483647
infinity cast to long
results in 9223372036854775807
Conceivably, a programmer could fail to initialize a numeric variable
and it would be assigned Java's default of zero. If floating-point division
were done with this number, there could be an infinite result. If the result
were cast to an integer, everything would look just peachy.
(February 26, 2001 Java 2 version 1.3)
The book Core Java 2 Volume 1 Fundamentals (J2SE Version 1.3) by Cay S. Horstmann and Gary Cornell has a gripe about static fields on page 143. The authors note that what Java calls static fields are called class fields in most other object oriented languages. Quoting: "The term 'static' is a meaningless holdover from C++." (February 20, 2001)
Executing .Class Files Under Windows
Under all versions of Windows, you can double-click on a file and either execute it or bring up its associated application. Not so with Java class files. These gripes could be more with Windows than with Java.
After installing JDK 2.1.3 under Windows NT4, there was no associated application for ".class" files. I then told the operating system to open these files with the java.exe program in the bin subdirectory of the main JDK directory. Double clicking on a ".class" file now brings up a DOS window which (pretty much) immediately shuts down.
When I view the list of known File Types and their associated programs, there nothing Java related. The association I just made for ".class" files does not appear under any name. I then try to make a new file type and associate it with the extension ".class", but this produced the following error.

On
a Windows 98 machine with both the Java2 SDK v1.3 and JBuilder Foundation v4.0
installed, double-clicking on a ".class" file produced the
error:
"Cannot find myprogram.class or one
of its components. Make sure the path and file name are correct
and that all required libraries are
available."
The class files were associated with program jbuilderw.
Figuring the problem had something to do with JBuilder, I manually changed the
file association so that .class files were opened with c:\jdk1.3\bin\java.exe.Now
it works just like the NT4 machine described above, a DOS window opens and then
closes immediately. (February
23, 2001)
On a related topic, on an NT4 machine (SP3) with JBuilder Foundation v4.0 installed, double clicking on a .Java file starts JBuilder. How this works beats the heck out of me. I wanted to change it to invoke a text editor. Looking at the file type associations in Windows Explorer, there was no file type for .Java anywhere in the list. (March 3, 2001)
Also on a related topic, the error messages you get when running a class file
that does not exist are not very descriptive. In the example below, the correct
class file name is "TCPClient". I typed it, incorrectly, as "TCPclient".
These are the resulting error messages: (Windows NT4, Java2 v1.3, March
24, 2001)
C:\MYDIR\java TCPclient
Exception in thread "main" java.lang.NoClassDefFoundError: TCPclient (wrong name: TCPClient)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
For the purposes of this discussion, assume that (superclass) ducks have two legs and two feet and that (subclass) lame ducks have one leg and one foot.
Java
lets you declare an object variable for a superclass and then assign to it a
reference to a subclass. For example,
Duck someduck;
someduck = new LameDuck();
The theory is that since a subclass (LameDuck) is a superclass
(Duck) it can substitute for it. I think Java would be better not
allowing this as you have basically lied to the compiler and created a logically
fuzzy situation. The following illustrates a specific problem with it.
A lame duck is and isn't a duck. The LameDuck class probably has methods that the Duck class does not. Likewise, the LameDuck class probably has member fields that Duck does not. Methods in LameDuck only are not visible when you lie to the compiler in this fashion. So to with member fields, if they are only in the LameDuck class, they will not be visible when the LameDuck object is assigned to a Duck variable.
But what happens when a method or member field is in both the Duck and the LameDuck class? You could say its an ugly situation. But that would be an ugly duckling. The code below illustrates what happens in this case. Java is not consistent and you end up with a duck with one leg and two feet.
public class Duck
{
int feet = 2;
public int legs() {return feet;} }
public class LameDuck extends Duck {
int feet = 1;
public int legs() {return feet;} }
public class DuckTester {
public static void main(String[] argzz){
Duck d = new Duck();
System.out.println("duck.legs="+d.legs()); // 2
System.out.println("duck feet="+d.feet); // 2
LameDuck ld = new LameDuck();
System.out.println("lameduck.legs="+ld.legs()); // 1
System.out.println("lameduck feet="+ld.feet); //
1
Duck someduck;
someduck = new LameDuck(); //give a child where parent expected
System.out.println("someduck is "+someduck.getClass());//class LameDuck
System.out.println("someduck.legs="+someduck.legs()); // 1
System.out.println("someduck feet="+someduck.feet);}} // 2!!!
Three factors conspire to result in lame ducks with 1 leg and 2 feet.
FYI: Declaring feet protected in the Duck
class, still results in lame ducks with one leg and two feet.
This is an expanded explanation of an issue that I first ran across in A
critique of Java by Harold Thimbleby (see Other
Gripers below). (February 25, 2001. Java2 v1.3)
When I
tried to compile my first Java servlet, I had classpath problems under Windows
2000 SP2. The servlet was to run under the stand-alone version of Jakarta Tomcat v3.2.3.
Servlets require access to servlet.jar. My CLASSPATH was set to
c:\jdk1.3;c:\jakarta-tomcat-3.2.3\lib\servlet.jar;.;
Try as I might to compile a simple servlet, it kept failing because the compiler
could not find the required servlet classes. All the while the source code was
on the C disk (NTFS). Out of guesses, I copied the source code to the F disk, a
local FAT disk partition. It compiled. Same source code, same classpath, same
computer.
To make a long story short, the CLASSPATH environment variable is case sensitive. Changing the references to the C disk from lower case to upper case, fixed the problem. (October 14, 2001)
The HttpServletRequest interface (version 2.2) includes a method isRequestedSessionIdFromCookie() that returns a boolean. The API documentation says it "Checks whether the requested session ID came in as a cookie" and returns true if the session ID came in as a cookie; otherwise, false.
The problem is that Internet Explorer 5 (maybe IE4 and IE6 too, I haven't checked) has separate settings for persistent cookies and temporary cookies. If you turn temporary cookies on and persistent cookies off, the method returns true, since the sessionid is stored in a temporary cookie. However, you will not be able to store persistent cookies on the client. As far as I know, there is no way for a servlet to know whether persistent cookies are supported on the client. (October 21, 2001)
If you catch an exception in the method that threw it, there is no way to spit out an error message and go right back to the try block. The Eckels book talks about how you can lose an exception, something that C++ does not allow.
What is the future of Java? It is sometimes noted that Java has serious momentum on the server side. To this Robert X. Cringely says: "Java GUI is dead. Go to Best Buy and look for Java apps. They aren't there. Java's platform independence was all about satisfying a million clients running Windows, Unix, Mac, etc. and then we abandoned Java on the client because it was too slow and klunky. Now we tout Java platform independence on the server as if we never had the foresight to buy the right server in the beginning. Or even if we must upgrade, we must upgrade to a radically different architecture. Sure, platform independence on the server is great, but is nowhere near as grand as the original vision of PI on the client." The article is Caught in a .NET Don't Expect Microsoft to Give Up One Weapon Without Acquiring Another -- How .NET Assures the Continuation of Monopoly November 8, 2001.
Sharper Than Ever. Microsoft's C# Language Might Be the Death of Java, but Sun's the One to Blame. By Robert X. Cringely. November 1, 2001. Quoting from the article: "I predict that Microsoft is about to beat the bejeezus out of Java...Java was to have been the Microsoft-killer... Sun's cross-platform, write-once run-anywhere language was going to free us all from the tyranny of Microsoft and Visual BASIC, but it simply hasn't happened. For this, I blame Sun and nobody else."
So long, Java! How Sun screwed itself by suing Microsoft. David Coursey, ZDNet Anchor Desk. July 19, 2001. Quoting: Sun never produced a version of Java that really lived up to the "write once, run anywhere" promise. Java was a child prodigy that never reached its true potential. Java is a great idea whose potential has never been reached ... when history makes its judgment as to why this occurred, it will be as more Sun's fault than anyone else's.
Java: Slow, ugly and irrelevant.
Jan. 8, 2001. By Simson Garfinkel in Salon. Quoting: I hate Java. As a programmer, I hate Java, the language, for what it has done to the field of programming. As a journalist, I hate the relentless hyping of Java by its supporters, as well as their unending excuses as to why Java has failed to deliver. And as a technologist
... I hate the complications that Java has caused.
Java fans fight back
January 18, 2001. By Simson Garfinkel in Salon. OK, Sun's programming language does have some good points, but it's still a long way from
perfect.
A critique of Java By Harold Thimbleby at Middlesex University. December 18, 1998. The abstract of this paper says: "Our experience of using Java is disappointing: as a programming language ... Java itself leaves much to be desired. This paper discusses a few serious problems with Java's design, which leads us to suggest that the language definition should have been an integral part of the design process rather than, as appears, a retrospective commentary." The author says the purpose of the paper is to "warn Java programmers of certain weaknesses in the language: they may therefore be able to take suitable precautions."
There used to be Java gripes at www.obfusco.com/javanotes.html but the web site seems to have died (December 26, 2002).
Java Gotchas By Roedy Green. Actively updated. Quoting from the web page in describing itself: "Java Gotchas are quirks in the language or standard libraries. Some might call them bugs, some features, some nasty surprises." This is a large web page. Here is another quote on the topic of Java dates: "The people who wrote Date and Calendar were just learning English. They seem to think day, date, time and timestamp are synonymous." There is also a list of Java compiler error messages that provides assistance in translating from what the compiler says to the likely real problem.
Read also my gripes regarding a Java book from Prentice Hall where it took much nagging to get them to replace a defective CD-ROM disc.
A study from the Gartner Group found that 70 percent of initial Java projects have been unsuccessful. They estimate that .NET will have the same failure rate. ZDNet Australia, Nov. 15, 2002.
I can not verify this. The web site internalmemos.com has, what it claims is, a Sun internal memo on the problems in their JVM. February 10, 2003.
Java needs an overhaul
by Russell Beattie. August 24, 2007.
![]()
| Page created: February 2001 | Page last updated: October 26, 2007 |
| Prior updates: September 29, 2007 | February 15, 2003 | |
|
|
Search | Merchandise | About | Griping by: Michael Horowitz | TOP |