In 2005 Joel Spolsky wrote an article The Perils of Java Schools. The main point of the piece "is that Java is not, generally, a hard enough programming language that it can be used to discriminate between great programmers and mediocre programmers. " He goes on to list two of the characteristics of C that make it a good touchstone for a programmer's skill: pointers and recursion.
Pointers and recursion require a certain ability to reason, to think in abstractions, and, most importantly, to view a problem at several levels of abstraction simultaneously.
I'm not quite sure why he picked recursion, since the "recursive powers" of Java and C are pretty much identical--neither supporting tail recursion--so that leaves pointers.
My first minor disagreement with Joel's thesis is in that he feels pointers are a difficult enough topic to identify great programmers. Here is a great 5-page paper written by John Tsiombikas that clearly presents pretty much everything you need to know about C pointers. Basically, compared with pretty much any of the other topics in a rigorous undergraduate engineering education--differential equations, linear algebra, Fourier transforms, discrete mathematics, orders of growth, etc.--pointers are downright cake. It's not that they're trivial, but next to the hard stuff they're pretty simple.
That leads me to the biggest issue I have with the whole anti-Java movement: blaming the language for a perceived decline in the quality of CS graduates, and for an inability to distinguish good and bad programmers who program in Java.
I used to be able to tell the smart kids because they could rip through a recursive algorithm in seconds, or implement linked-list manipulation functions using pointers as fast as they could write on the whiteboard. But with a JavaSchool Grad, I can't tell if they're struggling with these problems because they are undereducated or if they're struggling with these problems because they don't actually have that special part of the brain that they're going to need to do great programming work.
Does that mean in the old days if a candidate knew C pointers he got hired without further ado? Hmm. How about asking the JavaSchool grad a question that tests his intelligence and programming acumen without being tied to an implementation language? Ask him to write some code in whatever language for an insertion on a red-black tree. I'd pit my army of "red-black hires" against the army of "C pointer hires" any day. And if red-black trees are too snooty (which they probably are) then heapsort or mergesort will probably do; and if mergesort is too snooty, then you should stop complaining about JavaSchools altogther.
It seems that people are blaming the quality of students on the language in which they are taught rather than the declining standards of computer science knowledge to which they're held. And students also are coming to view Java as the source of feelings of dissatisfaction with their education, for instance here.
Java does not need to hold back a programmer in the least!
Want to see some hardcore, low-level programming, like implementing an optimizing, JIT-compiling virtual machine? How about implementing one in Java? Yes, the Jikes RVM does just that, producing a self-hosting competitive performance JVM with pretty much everything, even GC, implemented in Java. Once you write a native-code compiler, whatever its implementation language, the whole world of systems programming is at your reach.
MIT's undergrad compiler class is taught in Java. The lecturer, Saman Amarasinghe, whose research specialties include compiler optimizations, computer architectures, and parallel computing, is certainly no n00b who chose Java because he didn't think his students could handle pointers or because he didn't know better. In my earlier days, when I was a C zealot, I asked him why he chose Java and he said it was because dealing with memory ownership (that is, which subsystem "owns" and thus has to free memory allocated on the heap) in a compiler was such a hassle that using Java let the students implement better compilers in the time allotted to them. Not a language bigot.
Even operating systems: take a look at JNode.
How about Donald Knuth's take on languages? (This interview is found here.)
Knuth: All through my life, I've always used the programming language that blended best with the debugging system and operating system that I'm using. If I had a better debugger for language X, and if X went well with the operating system, I would be using that.
[... Goes on to describe the horrors of the IMP language at Cray...]
It was not a great language or compiler.
However... it was still my language of choice, because it fit that operating system perfectly. The arrays would be named in a way that you could easily see in the debugger, and you could know where the storage was being allocated, you knew what was going on, and you could actually get your program running reliably, because IMP blended with the operating system. You couldn't do that with any of the other languages. You might be writing with a better language, but you would get your work done a couple of weeks later, instead of getting answers. I used IMP.
His superlative knowledge of data structures and algorithms and mathematics makes implementation language a less important aspect of his work. He'd have no qualms about using Java if its tool support were the best--and often it is. (Though admittedly he'd use a WEB compiler for Java so he could continue his practice of Literate Programming). Remember that he chose Pascal to write TeX and Metafont--and he said that he avoided the use of pointers because they weren't as portable as the other parts of Pascal (see section 3 of TeX: The Program).
In the end, what matters about a program is what it does, and how quickly and correctly, not in what language it was written.
So basically, don't blame students' degrading quality on Java - if you feel like blaming, maybe blame colleges for not being more demanding in their coursework. And if you're an employer, just put a little more effort into designing a better technical screening process. But are JavaSchools even in their unflattering sense a bad thing? Do we have fewer brilliant programmers now than we did a decade ago? Or just more mediocre ones? Would the brilliant programmers take the somewhat tedious CRUD webapp jobs that our Internet age has created a demand for?
Addendum:
From the discussion on Reddit, I learned of a cool book, "Elements of Computing Systems: Building a Modern Computer from First Principles", which teaches you the levels of abstraction from "NAND gates to Tetris". Knowing all of that will certainly give any programmer low-level perspective, and anyone who finishes it will have about zero trouble understanding pointers, I am sure. Incidentally, the book's accompanying software is in Java...