Abstract: A long time ago, James Gosling wrote Oak, which was later renamed to Java. Some of the quirky Java restrictions, for example only one public class per file, can be traced back to Oak. This newsletter looks at the Oak 0.2 specification.
Welcome to the 55th edition of The Java(tm) Specialists' Newsletter sent to 4461 Java Specialists in 85 countries. We had a good growth in the last two weeks, thanks to your concerted effort in forwarding this newsletter to your friends. There are three people in particular that I want to thank, although many more would be worthy of a mention:
javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.
A few weeks ago I was talking to someone about the origins of Java, and it occurred to me that I had big gaps in that part of world history. History had never been my forte, at school this was my weakest subject at 35% (at my worst level). Perhaps I should add that I was very weak with South African history, which at the time of me going to high school supposedly started with the white settlers arriving on the shores, and consisted almost entirely of remembering dates. I found such parrotting frivolous, and so my marks were not too hot.
Trying to fill my gaps of Java's history, I started digging around on
Sun's website, and eventually stumbled across the Oak Language
Specification for Oak version 0.2. Oak was the original name of what
is now commonly known as Java, and this manual is the oldest manual available
for Oak (i.e. Java). For more history on the origins of
Java, please have a look at The Green
Project and Java(TM)
Technology: An Early History. I printed the manual and kept
it next to my bed in case of insomnia (so I thought). When I started
reading it, I discovered answers to ancient questions: Why can we have
only one public class per .java file? Why are
protected members also accessible from the same package? Why do short
fields use as much memory as int
fields (at least
pre-JDK 1.4)?
In this newsletter I want to highlight the differences between Java 0.2 (i.e. Oak 0.2) and what we have now. For your reference, I will include the section numbers in the Oak 0.2 specification.
This is a question that I have frequently been asked during my courses. Up to now I have not had a good answer to this question. In section 1, we read: "Although each Oak compilation unit can contain multiple classes or interfaces, at most one class or interface per compilation unit can be public".
In the sidebar it explains why: "This restriction is not yet enforced by the compiler, although it's necessary for efficient package importation"
It's pretty obvious - like most things are once you know the design reasons - the compiler would have to make an additional pass through all the compilation units (.java files) to figure out what classes were where, and that would make the compilation even slower.
Oak had the ability to write a one-line JavaDoc comment.
public class OneLineJavaDoc { //* The number of lines allowed in a document. public int numberOfLines; }
This is fortunately not supported in Java as it is quite confusing.
Oak had some additional keywords that are not currently used in Java:
ushort
, string
, Cstring
and
unsynchronized
were already obsolete in version 0.2 of
Oak. Isn't it amazing how quickly things become obsolete in our
industry?
clone
, const
and goto
were keywordsprotect
and unprotect
were nasty keywords
for writing terrible exception code. More about that later...enum
was a keyword, but in the sidebar it said:
enum
isn't implemented yet. So, in answer to the
question: Why does Java not have enum? The answer is not some
heavy object-oriented philosophical answer about polymorphism
and strategy patterns. It is simply that James Gosling didn't
implement it in time and his management forced him to push
the language out of the door before he could finish the
feature :-)
The specification says: "The four integer types of widths
of 8, 16, 32 and 64 bits, and are signed unless prefixed
by the unsigned
modifier.
In the sidebar it says: "unsigned
isn't implemented
yet; it might never be." How right you were.
In my newsletter on Determining Memory Usage in Java, I noted that when you have a data member of byte or short, that they still use up at least 4 bytes of memory. This was changed in JDK 1.4, but the historical reason is found in the Oak spec:
"A variable's type does not directly affect its storage allocation. Type only determines the variable's properties and legal range of values. If a value is assigned to a variable that is outside the legal range of the variable, the value is reduced modulo the range."
I wish I had known that when I wrote my first Java program. I spent a lot
of time deciding which data types I wanted to use in order to save memory,
but I was actually wasting my time. Please note that this has changed as of JDK 1.4,
so now
it does help to use byte
s and short
s to reduce
the memory footprint.
In Oak, you were able to declare arrays as follows:
int a[10]; a[5] = 1;
However, we were also able to declare an array in the current Java
fashion, with new
. I think having two ways
of doing the same thing causes confusion, so I am very pleased
that this way of making new arrays has been removed.
It appears that final
was initially only meant to be
used for classes and methods, and that const
was used
for making fields constant.
This is the most surprising part of Oak 0.2. There were only three access levels as opposed to our current four. There was private which did not require a keyword, and which equated to our current "package private" or "friendly" or "package access" type of access level. All classes in a particular package could use all variables and methods declared in the classes in that package, regardless of public, protected and private declarations. I am very glad that they introduced a more private version of private, one that was only accessible within the class.
The lack of private as we know it today explains why when a member is protected, it is also accessible from within the same package. When Oak was written, protected was obviously accessible within the package because their private (our "package access") was the most restrictive access level. I seem to remember that in JDK 1.0 we had a fifth access level called "private protected", which meant that only subclasses could access the member.
This piece of surprising history also explains why fields are not private by default - they actually were "private" originally when private meant different things.
I don't need to emphasize how pleased I am that we now have the more restrictive "private" modifier. Without that, our industry would be in even more trouble.
Abstract methods were defined as in C++:
public interface Storing { void freezeDry(Stream s) = 0; }
Unfortunately the assertions in Oak 0.2 were not implemented in time, so they were thrown out to satisfy the release deadline. In case you think that assertions are back in JDK 1.4, have a look at the power that "those" assertions gave you:
class Calender { static int lastDay[12]= {31,29,31,30,31,30,31,31,30,31,30,31}; int month assert(month>=1 && month<=12); int date assert(date>=1 && date<=lastDay[month]); }
While objects are not required to obey the legality constraints within methods, the constraints are enforced at the entry and exit of every public and protected method.
I wish that James Gosling had worked a few extra weekends (if
that were possible) to finish the implementation of assert
as it appeared in the original Oak spec. Preconditions and Postconditions
were also loosely defined, but were also kicked out due to time pressure. Pity.
In Oak, you were able to post-increment a String. You could literally say s1++;
,
which was equivalent to s1 = s1 + 1;
. The post-increment statement is often (if
not always) implemented as +=1
so it seems that this also was true for
Strings. Fortunately this is not allowed in Java anymore.
Of course, being based on C, Oak included the infamous goto
statement.
Fortunately this is not in Java.
Where does the name RuntimeException
come from? Aren't all
exceptions thrown at runtime? These are exceptions
which are thrown by the runtime system.
In Oak 0.2, all exceptions were unchecked, meaning that there was no
throws
clause. My guess is that checked
exceptions were only added once the whole exception hierarchy had
already been set in wet concrete. I would have had a separate branch
for checked exceptions, something like:
public class Throwable { } /** Serious errors in the virtual machine */ public class Error extends Throwable { } public class CheckedException extends Throwable { } public class IOException extends CheckedException { } public class UncheckedException extends Throwable { } public class NullPointerException extends UncheckedException { }
This way you would avoid catching unchecked exceptions when you
catch CheckedException
. However, as it appears,
the exception class hierarchy was developed before the idea of
checked vs. unchecked exceptions, so we are stuck with an exception
mechanism that will cause headaches for generations to come.
If your program gets an asynchronous exception, you are dead. A few
weeks ago I was looking at a program that was throwing OutOfMemoryError.
This can happen at any time really, which is why it is called an
asynchronous exception. Another place where this can happen is
with Thread.stop()
. As you can imagine, this is inherently
dangerous, that is why it is deprecated. In Oak, life was even more dangerous. You
could cause an
asynchronous exception in another thread using Thread's
postException()
method. Now that was dangerous!
Imagine if other threads could cause asynchronous exceptions at
any place in your code!
In order to safeguard your code, you could "protect" it. If you wanted to indicate that you had some critical code which could not handle asynchronous exceptions, you did the following:
protect { /* critical section goes here */ }
And code that was quite happy with asynchronous exceptions did the following:
unprotect { /* code that can afford asynchronous exceptions */ }
There was a note in the sidebar saying that the default would probably be changed to not allow asynchronous exceptions except in explicitly unprotected sections of code.
I'm very glad that this feature was binned. I cannot imagine how complex our Java programs would have become with it in place.
That's it. The rest of the manual was filled with a Glossary and an Index, to push the manual to 38 pages.
Even though this manual was written way back in 1994, it provided for fascinating reading, even late at night ;-)
Until next time ...
Heinz
We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.