-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 =pod Java's type system sucks. It is overly verbose (C<< MyClass foo = (MyClass) some.method() >>), and doesn't even prevent type errors (NullPointerException). Don't even get me started on "type erasure". With that in mind, I came up with another reason why the type system sucks -- it doesn't actually prevent you from doing anything bad. Any type safety that your program has is a product of programmer competence (or luck, in the case of most Java developers), not a product of the compiler assuring it for you. Allow me to provide you with some examples; first, a simple one. Consider this class hierarchy: lang:Java public class Foo { public int a = 42; public int addToA(int b) throws Exception { return a = a + b; } } public class Bar extends Foo { public int addToA(int b) throws Exception { if(b < 0) throw new Exception("OMG B IS NEGATIVE"); return super(); } } This is probably not a very useful class hierarchy, but I think you see the point. We have violated the Liskov Substitution Principle. We can no longer replace instances of Foo with Bar, but Java's type system would be perfectly happy to let us do it anyway. (If this isn't making sense, consider what happens when you write C instead of C.) Any type safety provided by the static type system is now gone. That means that any type safety in your program exists because you, the programmer, happened to manually ensure type safety. (This is how programs written in dynamic languages work. The compiler isn't going to stop you from writing C<< $r = 2 + "foobar" >>, but it isn't a problem because you wouldn't get yourself into that situation.) The logical extension of this is that Java is actually equivalent to a dynamically-typed language. Imagine we have a class called "Anything" that implements every interface, and has every possible identifier as a method, which accept and return Anythings as their arguments: public class Anything implements A, AOL, Aachen, Aaliyah, ... { protected Anything[] instanceState; // maybe add a malloc function to manage this public Anything[] a(Anything[] args) throws Anything {} public Anything[] aol(Anything[] args) throws Anything {} ... } Now we can subclass this and really have some fun. public class Number extends Anything { public Number(Anything a) { ... } public addTo(Anything[] args) { ... } // ensure that there is only 1 arg, etc. } public class String extends Anything { public String(Anything a) { ... } } For the purposes of this exercise, let's assume that built-in types are also subclasses of Anything, and that it is not possible to perform addition on numbers and strings. Anyway, let's use those Numbers and Strings: Anything num = new Number(42); Anything str = new String("oh hai"); num.addTo(str).print(); This will blow up, but at runtime, not compile time. This is very similar to what happens in a dynamic language: $num = 42; $str = "oh hai"; print $num + $str; The only difference between the dynamic language and Java here is that Java makes you type the types, even though they don't mean anything. Writing Java really justifies the expense of my $300 keyboard. Anyway, the point of this article is not to encourage you to write code like the "Anything" class. The point is that Java does not provide any type safety, and if that's why you're using it, you might like Perl or Python or Lisp or something else better. And if you do want type safety, you really want ML or Haskell. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkk+GqYACgkQ2rw+dVvzZm2sMwCeNn/4bl6w/4oYuvB2cxEnW3Qn bUsAoIoztCsuodiv4aMT+xtbtIvkOs9K =RLNN -----END PGP SIGNATURE-----