Take the 2-minute tour ×

When Java was developed, it's designers chose to discard an unusual amount of the conventional wisdom established in the UNIX and C oriented toolchains. For one (and in my view) the most major example, they chose to discard the practice of header files and Makefiles and tried to build a monolithic, dependency-aware compiler instead. Later on, ant was developed to partially remedy the (obvious?) deficiencies of this process, and effectively re-implemented the makefile logic.

It's not like I resent old-style make and #include going overboard. However, their usage was reinvented in the Java world with ant and splitting each class into an Interface and an Implementation class, which is pretty close to the header file/source file pattern. I'm fairly sure the people behind Java knew of the existing tools and patterns and their purpose, so the decision to first do away with them and then reimplementing everything from scratch without even a hint of it in the language design is what astonishes me. Less costly ways would have been available (like parsing the source file and auto-generating a header file, which would have been fairly easy after pruning the C syntax a bit), but weren't taken, and I would love to know about the reason.

Similar forks were performed in most other places, at considerable development costs and the considerable cost of a splitted community. Nowadays, Java-world and C++-world developers often have a hard time communicating and collaborating due to a split that seems disproportionate to the actual differences between the C/C++ language and the Java language. While I can see the basic motivation behind the process (everyone loathes Makefile syntax and changing header files manually), I still can't grok the magnitude of the change.

Are there historical references about the motivation and reasons of this process? Are there any design documents or interviews with the people who drove this fork?

share|improve this question
You see the discarding of Makefile, header files and #include as a deficiency??? –  Péter Török Oct 26 '11 at 9:43
@PéterTörök: No, of course not, they are a pretty shabby system. OTOH, having interface and implementation in the same file and having the compiler find out which files need recompilation didn't seem to work out so well, either. That seems to be the reason "make 2" AKA ant was invented. –  thiton Oct 26 '11 at 9:49
@thiton: Actually ant didn't originally even support tracking dependencies. It was implemented when it was realized, that preparing a software package involves other tasks than just compiling the source code. The source code is still passed to javac in one big invocation by ant and javac finds out what it needs to regenerate. –  Jan Hudec Oct 27 '11 at 7:42
add comment

2 Answers

You should actually look at it from a different perspective: In Java you can have header files in form of interfaces. Whereas you actually need header files in C/C++.


See ant as a tool to get things done, e.g. build your application, deploy it or publish Javadoc, instead of a necessary tool for building Java applications. Also, Java is not bound to ant. In a similar way, C/C++ is not bound to makefiles (although it's a de facto industry standard). In the Java world there is a noticeable movement towards other build tools, namely Maven and Gradle, which provide additional functionality like dependency management and configuration by exception.

I believe that the step from makefiles to ant has been driven by superior support for getting the tasks done. Additionally, why would you require header files when they are not required by compiler or developer?

This probably doesn't answer your request for design documents and interviews, but hopefully gives you some ideas why this has been a natural development.

share|improve this answer
Thanks for the answer. I'm still not sure, though, that the Make-Ant transition is a "step", and that's probably the point where my understanding of the process stops. If it really were a step, C/C++ people would be using ant nowadays, wouldn't they? So it seems rather like an evolutionary fork to me. –  thiton Oct 26 '11 at 10:12
@thiton: I actually suspect it's partly the fact the problem set in Java is very different from C/C++ and partly because of the strong NIH syndrome of Java people (well, yes, if it's all in Java, it's as portable as Java, but the most portable applications are still written in C to these days). –  Jan Hudec Oct 26 '11 at 10:27
add comment

No other language beyond those that include C (C++ and Objective C) uses headers. Neither languages that predate C nor any of the newer ones.

It's because headers violate the very important "Don't Repeat Yourself" principle—all the information is actually there in the source file, so the compiler should just generate the information itself.

In fact, headers are probably an afterthought for C as well. In early versions of C you would just call functions without prototypes and C still caries rules on how arguments are marshalled in such case (and they are still important for variadic functions). Than prototypes were added and preprocessor was abused to pull them in and that stuck. Partly because it turned out to allow playing dirty tricks on the compiler that come in handy when doing low level work in the operating system and standard library. Those tricks are not generally useful for higher level programming.

Now if you don't have headers, you have three options:

  • generate all interfaces first and than compile the implementation bodies
  • compile in order of dependencies, but that precludes circular references
  • compile all modules in one compiler execution

Java chose the last one. C# did as well as did many other languages.

share|improve this answer
Ada is an exception to your first sentence. –  mouviciel Oct 26 '11 at 10:32
add comment

Your Answer


