Home

News: Joshua Bloch: the Strangest Thing in the Java Platform

  1. Joshua Bloch gives an interesting interview (http://java.sun.com/developer/technicalArticles/Interviews/bloch_effective_08_qa.html) on java.sun.com, promoting the revised version of “Effective Java” wherein he talks about generics, enums, annotations, the under-use of Java libraries, the importance of minimizing the accessibility of classes and members and minimizing mutability, and other matters. But the one question I’d never heard asked was, “What’s the strangest thing about the Java platform?” His answer: “I'm going to say that the strangest thing about the Java platform is that the byte type is signed. I've never heard an explanation for this. It's quite counterintuitive and causes all sorts of errors.” Two questions. Does anyone have an explanation as to why the byte type is signed? And what is your candidate for the strangest thing about the Java platform?

    Threaded Messages (44)

  2. If Joshua Bloch doesn't know the reason God forbid who does:-) But any way he worked for SUN and his colleagues were the creator of JVM (Gosling), may be some other folks e.g Tim Lindhom, Graham Hamilton etc who might influenced Java. I wonder what they have to say about it. RJ
  3. poor Unicode support[ Go to top ]

    The Strangest Thing in Java is poor Unicode support. Char type with 16 bits can represent only the BMP (Basic Multilingual Plane) set of Unicode chars. But the number of characters in Unicode 3.2 is 95,221. And the total number of designated code points is 234,803. Well, in Java 1.5 Sun invented some tricks that allow to process the whole range of 32-bit code points. But they didn't introduce 32 bit chars. So, there is no good Unicode support in Java. It's very strange, because Java is often being promoted as "platform with complete Unicode support".
  4. A hint[ Go to top ]

    may be found in this inteview: http://www.gotw.ca/publications/c_family_interview.htm
    Gosling: For me as a language designer, which I don't really count myself as these days, what "simple" really ended up meaning was could I expect J. Random Developer to hold the spec in his head. That definition says that, for instance, Java isn't -- and in fact a lot of these languages end up with a lot of corner cases, things that nobody really understands. Quiz any C developer about unsigned, and pretty soon you discover that almost no C developers actually understand what goes on with unsigned, what unsigned arithmetic is. Things like that made C complex. The language part of Java is, I think, pretty simple. The libraries you have to look up.
    Obviously Gosling throught that unsigned arithmetic would be too complicated.
  5. Re: A hint[ Go to top ]

    Obviously Gosling throught that unsigned arithmetic would be too complicated.
    Sorry if I'm being dense here but what is complicated about unsigned arithmetic? I agree with Josh Bloch that this doesn't make much sense. It seems doubtful to me that many developers are doing much arithmetic on bytes anyway and if they are, they probably don't need them to be signed. That byte is signed is a big pain in the ass because signed bytes are almost worthless and Java makes you jump through hoops to get the integer value from a byte that represents an unsigned number. It also means we have to have to remember which shift operator to use to avoid goofy signed shifts. On a side note, char is an unsigned number type in Java. byte b = -1; System.out.println(b); System.out.println((int) b); System.out.println((int) (char) b); outputs: -1 -1 65535
  6. char is unsigned...[ Go to top ]

    ... because there are no chars with an ascii value less than zero http://www.asciitable.com/
  7. Re: char is unsigned...[ Go to top ]

    ... because there are no chars with an ascii value less than zero
    That's obvious if you replace 'ascii' with 'unicode'. The point is that Java has an unsigned 16 bit primitive number type but almost no one uses in that capacity.
  8. Re: A hint[ Go to top ]

    Obviously Gosling throught that unsigned arithmetic would be too complicated.
    SPARC chips didn't do unsigned arithmetic, so the only unsigned in Java is the 16-bit unicode character (called "char"). Peace, Cameron Purdy Oracle Coherence: Data Grid for Java, C++ and .NET
  9. A Hint[ Go to top ]

    So, Java was designed for a specific platform (SPARC) and thus not platform independent at all!
  10. There are some clues here.
  11. The problem with this argument is that the char type *is* unsigned. I honestly do not know why char is unsigned and byte is not. As for Cloneable, Frank Yellin (who was there at the time) told me that removing the clone method from Cloneable was removed in a misguided attempt to improve the security of the platform. (Those weren't his exact words, but that was the message.)     Josh
  12. Clearly it's part of the security model. ;)
  13. "Clearly it's part of the security model. ;)" Best theserverside comment ever.
  14. My vote for the Strangest Thing in the Java platform goes to the fact that java.lang.Cloneable does not contain clone() method!
  15. My vote for the Strangest Thing in the Java platform goes to the fact that java.lang.Cloneable does not contain clone() method!
    Probably because until recently, you couldn't define covariant return types in interfaces.
  16. My vote for the Strangest Thing in the Java platform goes to the fact that java.lang.Cloneable does not contain clone() method!


    Probably because until recently, you couldn't define covariant return types in interfaces.
    Why would that matter? The clone method returns Object. There's no reason why it couldn't have been defined in the interface. And it is truly idiotic because an Object 'marked' as cloneable cannot be cloned unless you cast to a concrete type where clone is defined as accessible. In other words, you have to know the concrete type and if you know that, the Cloneable interface doesn't tell you anything extra.
  17. And it is truly idiotic because an Object 'marked' as cloneable cannot be cloned unless you cast to a concrete type where clone is defined as accessible.
    Yeah. I've worked around this by defining my own ReallyCloneable interface.
  18. My vote for the Strangest Thing in the Java platform goes to the fact that java.lang.Cloneable does not contain clone() method!


    Probably because until recently, you couldn't define covariant return types in interfaces.


    Why would that matter? The clone method returns Object.

    There's no reason why it couldn't have been defined in the interface. And it is truly idiotic because an Object 'marked' as cloneable cannot be cloned unless you cast to a concrete type where clone is defined as accessible. In other words, you have to know the concrete type and if you know that, the Cloneable interface doesn't tell you anything extra.
    The reason for that is, that you might want to forbid the outside cloneing of your object. (clone() method on Object is protected! Btw, the signed bytes are could be real pain. Cheers, Tamas
  19. Btw, the signed bytes are could be real pain.
    Could be? Signed bytes are a real pain. I've never needed to use signed arithmetic with bytes. It's something that I have to work around. It doesn't provide value.
  20. Re: Cloneable[ Go to top ]

    My vote for the Strangest Thing in the Java platform goes to the fact that java.lang.Cloneable does not contain clone() method!


    Probably because until recently, you couldn't define covariant return types in interfaces.


    Why would that matter? The clone method returns Object.

    There's no reason why it couldn't have been defined in the interface. And it is truly idiotic because an Object 'marked' as cloneable cannot be cloned unless you cast to a concrete type where clone is defined as accessible. In other words, you have to know the concrete type and if you know that, the Cloneable interface doesn't tell you anything extra.
    The thing is: Cloneable does not mean what you would expect. It does not mean: this class has a clone() method that returns a copy of the current object. Implementing Cloneable achieves a single thing: it tells Object.clone() that it can of an object by copying the values of all instance variables. (Yes, I know it's silly, but that's the way it is.) Cloneable should have been an annotation (which didn't exist back then), together with Serializable (which is even stranger than Cloneable IMHO).
  21. Re: Cloneable[ Go to top ]

    My vote for the Strangest Thing in the Java platform goes to the fact that java.lang.Cloneable does not contain clone() method!


    Probably because until recently, you couldn't define covariant return types in interfaces.


    Why would that matter? The clone method returns Object.

    There's no reason why it couldn't have been defined in the interface. And it is truly idiotic because an Object 'marked' as cloneable cannot be cloned unless you cast to a concrete type where clone is defined as accessible. In other words, you have to know the concrete type and if you know that, the Cloneable interface doesn't tell you anything extra.

    The thing is: Cloneable does not mean what you would expect. It does not mean: this class has a clone() method that returns a copy of the current object.

    Implementing Cloneable achieves a single thing: it tells Object.clone() that it can of an object by copying the values of all instance variables. (Yes, I know it's silly, but that's the way it is.)

    Cloneable should have been an annotation (which didn't exist back then), together with Serializable (which is even stranger than Cloneable IMHO).
    I know how it works, I just think it's stupid and broken (as does Josh Bloch, BTW.) If you want to clone something, you call clone on it. If you don't want to clone something, you won't call clone. It's just a hoop that you are required to jump through. Cloneable acts like a safety switch. It's only possible purpose is to prevent the developer from calling something that they didn't really mean to call.
  22. Re: Cloneable[ Go to top ]

    If you want to clone something, you call clone on it. If you don't want to clone something, you won't call clone. It's just a hoop that you are required to jump through. Cloneable acts like a safety switch. It's only possible purpose is to prevent the developer from calling something that they didn't really mean to call.
    Yup. I covered the topic in "The Seven Habits of Highly Dysfunctional Design III":
    So Object has a protected method named clone() that you can call on yourself (i.e. an instance method can call this.clone()) but if you do call it on yourself it will throw an exception. A checked exception. So if you want to call your own method to do what it is built to do, you additionally have to implement an interface named Cloneable that has no methods. Let's think about this: * Since clone() is protected, only you can call it on yourself. (This is not entirely true, since protected access implies package access as well, but that particular design mistake can hardly be the reason for screwing up clone().) * Calling clone() on yourself will cause a checked exception to be thrown. * Implementing the no-method Cloneable interface changes the behavior of your own clone() method. * Even having implemented the Cloneable interface, no one else can clone you. In fact, Java does not have a Cloneable interface that allows an object to expose its cloneable capability to other objects; the best you can do is override the clone() method and mark it as public.
    Peace, Cameron Purdy Oracle Coherence: Data Grid for Java, .NET and C++
  23. Re: Cloneable[ Go to top ]

    instance variables. (Yes, I know it's silly, but that's the way it is.)

    Cloneable should have been an annotation (which didn't exist back then), together with Serializable (which is even stranger than Cloneable IMHO).
    There's a good reason Serializable is not an annotation (apart from historical). Sometimes you'd like your contract to ensure you will get passed Serializable (say for remoting purposes). There's no way to ensure that the object being a method parameter is annotated with given annotation (compile time), while there's an easy way to declare a method like: void send(Serializable s);
  24. cloning[ Go to top ]

    My vote for the Strangest Thing in the Java platform goes to the fact that java.lang.Cloneable does not contain clone() method!
    That's because putting it in the interface would have forced it to be public, and they felt that clone() should be protected, so they stuck it on Object instead. (Yes, bad design.) Peace, Cameron Purdy Oracle Coherence: Data Grid for Java, C++ and .NET
  25. I mean, no elegant way. In older Java versions some people used horrible constructions like this: new Exception().getStackTrace()[0].getMethodName() As of Java 1.5 one can use a bit nicer code: Thread.currentThread().getStackTrace() It's not so bad, but still is not elegant enough. And that is one of the Strangest Things in Java. Support of Runtime Information is really missing.
  26. modifier     private[ Go to top ]

    Many developers believe, that "private" attributes and methods can be accessed only by the object itself. However that is not true. Quite common examples are methods like "clone()" and "equals()". private String name; protected Object clone() ... { Foo clone = (Foo) super.clone(); clone.name = this.name; return clone; } Attribute "name" is declared as "private". But nevertheless object "this" accesses this private attribute of object "clone". This simple example only illustrates the problem. In the reality more sophisticated cases are possible. But the point is clear. "private" is not really private! That is one of the Strangest Things in Java.
  27. Re: modifier     private[ Go to top ]

    Many developers believe, that "private" attributes and methods can be accessed only by the object itself. However that is not true. Quite common examples are methods like "clone()" and "equals()". [...] But the point is clear.

    "private" is not really private!

    That is one of the Strangest Things in Java.
    "The private modifier specifies that the member can only be accessed in its own class." Source Never mix class with object. They are not compatible terms! Cheers, Tamas
  28. Re: modifier     private[ Go to top ]

    Exactly! See my words "Many developers believe ...". There are a lot of people, who does not distinguish these things. Nevertheless, there is no modifier, that means "instance-private", not "class-private".
  29. Re: modifier     private[ Go to top ]

    The 'private' operator just means it is limited to the *class*, not the *instance*
  30. Stack extending Vector Properties extending Hashtable
  31. Private is not really private.[ Go to top ]

    Worse than accessing different instances but inner classes can access private members of outer classes and visa-versa.
  32. RE: Private is not really private.[ Go to top ]

    Worse than accessing different instances but inner classes can access private members of outer classes and visa-versa.
    That's a really great feature. If you don't make use of it you aren't realizing the full potential of inner classes. What are you worried about? If someone has access to the source of a class, they can do whatever they want with it. What value would be gained by adding a restriction against this? It seems pretty pointless to me.
  33. Arcane syntax[ Go to top ]

    The strangest thing to me in Java is still that they modeled the syntax after C and C++. The C syntax was designed for the purpose of making it simple to compile even if it meant making it hard to write and read. A good decision at the time as the compiler technology was rather simple. A bad decision at the Java design time with modern compilers. Eiffel and other languages had shown new ways that didn't even seem to be considered. Then C++ came along apparently based on the idea that programmers couldn't learn a new syntax and the arcana continued. The Java designers seemed to live on in the old times. It all could have been so much better, but a lot of people don't even realize it because they are too used to their hardships. It's a strange world.
  34. Re: Arcane syntax[ Go to top ]

    The strangest thing to me in Java is still that they modeled the syntax after C and C++.
    Well, one might think that C and C++ syntax is strange, but the decision to model Java after it is certainly not strange, just very clever. The world didnt really need another smalltalk, but a "better" C with objects, garbage collection, and some protection against runtime errors, was just what the doctor ordered.
  35. the unreliability of gc( )[ Go to top ]

    According to Sun, System.gc( ) is not 100% reliable: "When control returns from the method call, the virtual machine has made its best effort to recycle all discarded objects." Notice the wording ("best effort"). There is no guarantee that gc() will actually force a garbage collection. The problem is, when you really need to use gc(), you really need it to work. If a method is not guaranteed to do what you expect it to do, then it becomes worthless (or at best dangerous). So therefore why offer gc() at all? Offering a method that *may* work encourages casual use of the method (i.e., it encourages using it under NON-critical conditions, when you don't particularly need it to work reliably). Ironically, explicit garbage collection is discouraged by Sun. So I say again: Why offer a gc() method at all? When you're coding, you either you need gc(), or you don't, and if you need it, you definitely need it to work.
  36. Re: the unreliability of gc( )[ Go to top ]

    [...] Ironically, explicit garbage collection is discouraged by Sun. So I say again: Why offer a gc() method at all? When you're coding, you either you need gc(), or you don't, and if you need it, you definitely need it to work.
    I agree that is a bit vague, but it is an interface. If it offers something, must be maintained for a long time... Tomcat 4.1 used to call it regularly, but they stopped doing it, since it caused way more overhead than paralell-gc. (At least this is what I measured) Anyhow, gc() is not a blocking method and only a hint for the VM, that there might be a good idea to run. And as far as I see they tend to honor it. Cheers, Tamas
  37. Re: the unreliability of gc( )[ Go to top ]

    [...]
    Ironically, explicit garbage collection is discouraged by Sun. So I say again: Why offer a gc() method at all? When you're coding, you either you need gc(), or you don't, and if you need it, you definitely need it to work.


    I agree that is a bit vague, but it is an interface. If it offers something, must be maintained for a long time...

    Tomcat 4.1 used to call it regularly, but they stopped doing it, since it caused way more overhead than paralell-gc. (At least this is what I measured)

    Anyhow, gc() is not a blocking method and only a hint for the VM, that there might be a good idea to run. And as far as I see they tend to honor it.


    Cheers,

    Tamas
    You said "they tend to honor it." Well, "tend to" is exactly the problem. If you can't rely on the method to do what it's supposed to do (and if failure to behave consistently could have side effects for your program), why is such a method put out there for programmers to use (and possibly get in trouble with)? If its behavior is intermittent or non-deterministic, how can I reliably use it in a situation where I genuinely *need* to use it? Sun, btw, says "When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects." Note the phrase "when control returns." I take this to mean you lose control until it returns, i.e. it's a blocking call. So your statement that it is not a blocking method would appear to be incorrect.
  38. Re: the unreliability of gc( )[ Go to top ]

    <blockquoteYou said "they tend to honor it." Well, "tend to" is exactly the problem. If you can't rely on the method to do what it's supposed to do (and if failure to behave consistently could have side effects for your program), why is such a method put out there for programmers to use (and possibly get in trouble with)? If its behavior is intermittent or non-deterministic, how can I reliably use it in a situation where I genuinely *need* to use it? I've only seen developers using System.gc() because they don't know how the GC works and they _believe_ that it's for some obscure reason necessary to play with the GC manually. Which situation do _you_ have, where you genuinely need to use it? My imagination may be a little bit restricted, but I honestly can't think of a situation where you do.
  39. 1. A default constructor is added to your class if you don't declaring one and if you do declare one, this default constructor suddenly disappears 2. If you implement java.io.Serializable, you suddenly have readObject and writeObject as methods, just like the Clonable above 3. Implementing java.io.Serializable produces a warning if you don't add a final static serialVersionId field 4. Not be able to get the actual type in generics 5. Overflow of values. Integer.MAX_VALUE + 1 should give an exception, but it doesn't. 6. int i = 100, j = 0; float k = 100, l = 0; i / j -> Overflow exception k / l -> No exception etc etc etc etc etc
  40. No interface for Input/Ouput Stream[ Go to top ]

    I never got it why java.io.InputStream is an abstract class and not an interface... It is hard to "marry" things like Remote + InputStream in Java (in RMI sense of those things) MX
  41. Re: No interface for Input/Ouput Stream[ Go to top ]

    I never got it why java.io.InputStream is an abstract class and not an interface...

    It is hard to "marry" things like Remote + InputStream in Java (in RMI sense of those things)

    MX
    Very true. To solve this problem, we created an InputStreaming interface (same methods) and a concrete InputStream sub-class that delegates to an InputStreaming instance. Peace, Cameron Purdy Oracle Coherence: Data Grid for Java, .NET and C++
  42. compare() and equals() contradiction[ Go to top ]

    When A.compare(B) == 0does it mean following? A.equals(B) == true Not necessarily! "compare()" makes semantical comparison. Whereas "equals()" compares objects technically. E.g. "A" and "B" are BigDecimal. A = 1.2345 x 10^2 B = 1234.5 x 10^-1 Semantically both mean 123.45, so "A.compare(B) == 0". But they have different internal attributes, e.g. different scale factor. That's why "A.equals(B) == false"! This leads (or misleads?) to further problems. Many Collection-based classes use "equals()" to compare objects. E.g. to determine index of object in the list, or to check if a map contains given key. Especially it becomes interesting in Hash-classes (HashSet, HashMap). If we implemented "equals()" in such a way, that it means semantical comparison, then "hashCode()" must return the same value for two equal objects with different attributes. Surprised? Well, the solution could be to calculate "hashCode()" for normalized form of the object. It means some overhead.
  43. The advantage of the signed types[ Go to top ]

    the citation from: http://en.wikipedia.org/wiki/Two%27s_complement "The two's-complement system has the advantage of not requiring that the addition and subtraction circuitry examine the signs of the operands to determine whether to add or subtract. This property makes the system both simpler to implement and capable of easily handling higher precision arithmetic. Also, zero has only a single representation, obviating the subtleties associated with negative zero, which exists in ones'-complement systems."
  44. "The two's-complement system has the advantage of not requiring that the addition and subtraction circuitry examine the signs of the operands to determine whether to add or subtract. This property makes the system both simpler to implement and capable of easily handling higher precision arithmetic. Also, zero has only a single representation, obviating the subtleties associated with negative zero, which exists in ones'-complement systems."
    That's the advantage of using a Two's Complement encoding (e.g. -128 to +127) over a sign bit (-127 to +127 with both a +0 and -0). Unsigned integer arithmetic is obviously not more complex than two's complement arithmetic, by definition. Consider that two's complement simply uses the same circuit design as does unsigned integer arithmetic for most of the simple operations. Peace, Cameron Purdy Oracle Coherence: Data Grid for Java, .NET and C++
  45. The strangest thing? Well I stumbled upon this signed byte some years ago - pretty awkward, but lately I found something else: How to derive from a class? class A extends B How to implement an interface? class A implements I How to implement multiple interfaces? class A implements I, J so far so good .. How to request a generic parameter with a given type? Note: extends might suggest a class but really does not differentiate! How to request the parameter implements multiple interfaces? WTF: Why introduce a new symbol when we clearly have the ',' to separate interfaces in a situation like this! How to tell that a generic parameter must extend a class AND implement some interfaces? WTF++: See any difference? - If you might wonder: the class (obviously there can only be one) must be the first argument! I mean - don't get me wrong - I love the possibility to do something like this, but I would have chosen either or at least Happy Halloween everyone! Thomas aka Pauli