User:Tentor

From TheoryOrg
Jump to navigation Jump to search

Java sucks because:

Syntax

  • Overly verbose.
  • Java has unused keywords, such as goto and const.
  • There's no operator overloading... except for strings. So for pseudo-numeric classes, like BigInteger, you have to do things like a.add(b.multiply(c)), which is really ugly.
  • There are no delegates; everytime you need a function pointer you have to implement a factory design.
  • Before Java 7, catch clauses can contain only one exception, causing a programmer to rewrite the same code N times if she wants to react the same way to N different exceptions.
  • The return statement is not valid within initialization blocks.
  • Arrays don't work with generics: you can't create an array of a variable type new T[42] or of a parameterized type new ArrayList<String>[42]
  • No properties. Simple class definitions are 7 to 10 times as long as necessary.
  • Before Java 7, there is no automatic resource cleanup; instead we get have five lines of "allocate; try {...} finally { cleanup; }"
  • No array or map literals.

Model

  • No first-class functions and classes.
  • Checked exceptions are an experiment that failed.
  • There's int types and Integer objects, float types and Float objects. So you can have efficient data types, or object-oriented data types.
    • Number base-class doesn't define arithmetic operations, so it is impossible to write useful generics for Number subclasses.
  • Using only interfaces to implement multiple inheritance doesn't allow to share common code through them, unlike "mixins".

Library

  • Functions in the standard library do not use consistent naming, acronym and capitalization conventions, making it hard to remember exactly what the items are called:
    • java.net has URLConnection and HttpURLConnection : why not UrlConnection or HTTPURLConnection or HttpUrlConnection?
    • java.util has ZipOutputBuffer and GZIPOutputBuffer : why not ZIPOutputBuffer or GnuZipOutputBuffer or GzipOutputBuffer or GZipOutputBuffer?
  • The design behind Cloneable and clone is just broken.
  • Arrays are objects but don't properly implement .toString() (if you try to print an array, it just prints hash code gibberish) or .equals() (arrays of the same contents don't compare equal, which causes a headache if you try to put arrays into collections)
  • Useful methods like sorting, index of, binary search, etc. are not part of Collection classes, but part of separate "utility classes" like Collections and Arrays
  • Why is Stack a class, but Queue an interface?
  • Code is cluttered with type conversions. Arrays to lists, lists to arrays, java.util.Date to java.sql.Date, etc.
  • The Date API is considered deprecated, but still used everywhere. The replacement Calendar is not.
  • No string join function.
  • The reflection API requires multiple lines of code for the simplest operations.

Disputed

Some points in this section have been disputed on the discussion page.

  • Nearly everything is wrapped with objects and many things must be buffered, even those things that don't really need to be objects or be buffered. (examples?)
  • Some interfaces such as Serializable and RandomAccess are used just like annotations: they are empty, and when implemented their only purpose is to indicate some semantics.
    • An interface describes how an object can be used, even if it does not add any methods. From an OO perspective, there is nothing wrong with that.
    • They were introduced before annotations.
    • It is not possible to un-implement the interface, though.
  • Initialization blocks (both static and non-static) can't throw checked exceptions.
  • Arrays are not type safe: Object[] foo = new String[1]; foo[0] = new Integer(42); compiles fine but fails at runtime
    • array covariance exists in other statically typed languages as well
  • Unicode escapes can have unexpected effects, because they are substituted before the code is parsed, so they can break your code, for example: (1) if a line-end comment contains a \u000A (line return), the rest of the comment won't be on the same line, and thus won't be in the comment anymore; (2) if a string literal contains a \u0022 (double quote), it ends the string literal, and the rest of the string is now in the actual code; (3) if a \u appears in a comment, and it is not a valid escape (e.g. "c:\unix\home"), it will cause a parsing error, even though it is in a comment
    • Easily solved by using an IDE with syntax highlighting (or not using unicode escapes).
  • Convenience functions must be overloaded for every fundamental type (e.g. max(float,float), max(double,double), max(long,long))
    • Overloads for long and double are sufficient.

(removed)

  • Interface method implementations are necessarily public, preventing to make an interface implementation accessible only to subclasses and same package classes. and You can't inherit a class as protected or private, your classes must publicly show everything they inherit.
  • RuntimeException inherits from Exception, but it doesn't make sense: checked exceptions are a special case of unchecked ones, not the contrary. Otherwise said, if I have to catch all the checked exceptions, why don't I have to catch the unchecked ones?
    • Does make sense, see Liskov Substitution Principle. If CheckedException would extend RuntimeException a method that throws only (unchecked) RuntimeExceptions might also throw checked exceptions. That would be broken. Think of it as every method declaring throws RuntimeException; thus, unchecked exceptions are the special case.
  • Many standard classes do parameter checking and manually throw unchecked exceptions such as NullPointerException and IllegalArgumentException. No problem; but what are the assertions for, then?
    • assertions are intended for internal consistency checks, can be disabled at runtime, and throw assertion errors. Thus, they must not be used for argument validation-
  • Every, single, object, has its own synchronization monitor, even those that you never synchronize on, resulting in unnecessary resource consumption. If you declare the dummiest ArrayList<Integer>, each element of your array will have a synchronization monitor; and of course you will never synchronize on them. Do you have an idea of how many (totally useless) synchronization monitors there are in an instance of the virtual machine running a medium Java program? And in a big program, such as Eclipse or NetBeans?
    • performance argument is BS. There are zero useless monitors because the VM creates them only when they are needed.
  • Instance initialization blocks cannot throw checked exceptions, there must be a no-arg constructor throwing those exceptions in its signature.
    • Duplicate
  • Can somebody in the universe explain me why the heck the clone method belongs to the Object class instead of the Cloneable interface??
    • Yes, but it's not important. Removed as duplicate to "clone is broken"
  • Cloning is a major pain, because the variable you are cloning must have a type that has a public clone() method (Object's clone() method is protected), which only exists for actual implementation classes, so you can't clone something of an abstract type (which kills abstraction). Also, all the clone() methods in the Java library return type Object for some ungodly reason (instead of the class's own type), so you have to cast it.
    • replaced with link to article
  • Enums in Java 1.5 are cool, but to use them you have to prefix the enum type, like MyEnum.SomeValue, because they exist in the enum class's namespace, so they are less convenient than just defining int constants
    • Enum constants belong to the enum, just like int constants belong to whichever class they are defined in. import static MyEnum.* solves the problem.
  • Wouldn't it be better to make boxed type (Integer, ...) as efficient as the primitives (int, ...)
    • They are as efficient as the value objects in any other OO language
  • No meta-programming.
    • not true.
  • Programmers can be significantly more productive in Python than in Java
    • Source is highly biased, many arguments are disputable. The overall argument of productiveness is a result of the individual points listed above. Productiveness is not the only criterion for a language (or C would be dead by now).