Unlike C++, in Java, we cannot have just function declarations in the class and definitions outside of the class. Why is it so?
Is it to emphasize that a single file in Java should contain only one class and nothing else?
I believe the answer is, per Wikipedia, that Java was designed to be simple and object oriented. Functions are meant to operate on the classes they are defined in. With that line of thinking, having functions outside of a class doesn't make sense. I am going to leap to the conclusion that Java doesn't allow it because it didn't fit with pure OOP.
A quick Google search for me didn't yield much on Java language design motivations.
|show 2 more comments|
The real question is what would be the merit of continuing to do things the C++ way and what was the original purpose of the header file? The short answer is that the header file style allowed for quicker compile times on large projects in which many classes could potentially reference the same type. This is not necessary in JAVA and .NET due to the nature of the compilers.
See this answer here: Are header files actually good?
The difference between C++ and Java is in what the languages consider their smallest unit of linkage.
Because C was designed to coexist with assembly, that unit is the subroutine called by an address. (This is true of other languages that compile to native object files, such as FORTRAN.) In other words, an object file containing a function
C++, despite all of its additional fanciness, works the same way. The compiler shoehorns namespaces, classs and methods/members/etc. into this convention by flattening the contents of classes into single names that are mangled in a way that makes them unique. For example, a method like
Java is a different beast that lives in an insulated world with its own object file format, the
If you haven't figured it out already, all of this safety comes with a tradeoff: anything you link to a Java program has to be Java. (By "link," I mean anytime something in one class file refers to something in another.) You can link (in the native sense) to native code using JNI, but there's an implicit contract that says that if you break the native side, you own both pieces.
Java was big and not particularly fast on the available hardware when it was first introduced, much like Ada had been in the prior decade. Only Jim Gosling can say for sure what his motivations where in making the class Java's smallest unit of linkage, but I'd have to guess that the extra complexity that adding free floaters would have added to the runtime might have been a deal-killer.
A Java file represents a class. If you had a procedure outside the class, what would the scope be? Would it be global? Or would it belong to the class that Java file represents?
Presumably, you put it in that Java file instead of another file for a reason - because it goes with that class more than any other class. If a procedure outside a class was actually associated with that class, then why not force it to go inside that class where it belongs? Java handles this as a static method inside the class.
If an outside-class procedure were allowed, it would presumably have no special access to the class whose file it was declared in, thus limiting it to a utility function that doesn't change any data.
The only possible down-side to this Java limitation is that if you truly have global procedures that are not associated with any class, you end up making a MyGlobals class to hold them, and import that class in all your other files that use those procedures.
In fact, the Java importing mechanism needs this restriction in order to function. With all the API's available, the java compiler needs to know exactly what to compile and what to compile against, thus the explicit import statements at the top of the file. Without having to group your globals into an artificial class, how would you tell the Java compiler to compile your globals and not any and all globals on your classpath? What about namespace collision where you have a doStuff() and someone else has a doStuff()? It would not work. Forcing you to specifiy MyClass.doStuff() and YourClass.doStuff() fixes these issues. Forcing your procedures to go inside MyClass instead of outside it only clarifies this restriction and does not impose additional restrictions on your code.
Java got a number of things wrong - serialization has so many little warts that it is almost too difficult to be useful (think SerialVersionUID). It can also be used to break singletons and other common design patterns. The clone() method on Object should be split into deepClone() and shallowClone() and be type-safe. All the API classes could have been made immutable by default (the way they are in Scala). But the restriction that all procedures must belong to a class is a good one. It serves primarily to simplify and clarify the language and your code without imposing any onerous restrictions.
I think it's an artifact of the class loading mechanism. Each class file is a container for a loadable object. There is no place "outside" of class files.