Compile (declared) type: any expression in Java has a type known by the compiler Object o = new Integer(); the declared type of the variable o is Object. Runtime: the real type of an object is only known by the "interpreter" --because the object is created only when the program is executing. The (runtime) type of the object pointed by o is Integer. Overloading: several methods with the same name has a different list of paremeters. The compiler yields error if they have the same name and the same list of parameters. Because overloding methods are really different methods, there is not relationship between their return types. There is not relationship between their exception throws clauses either. Overloading is possible also among a class and its subclass: Object.toString() Integer.toString(int) Integer.toString(int, int) All of them are overloading methods. Overloading gets that methods that should have the same name, because they perform a similar operation on distinct paramers, can be equally named. You do not have to made up a different name for each combination of parameters.
Overriding: (the magic of polymorphism) An instance method is declared in a class Object.toString() (overridden) An instance method is declared in a subclass. It has the same name, return type and argument list than the one in its superclass. It can declare any checked exception that was declared in the superclass, or any of its subexceptions. But it cannot declare any other checked exception. Integer.toString() (overridding) Hmm... same name, return type, argument list and conforms to declared checked exceptions. I would say both methods are the same. Yes they are, they really apply the same operation to father-son objects. The operation is the same, but the implementation of the methods vary according to the runtime/real type of the object. Not the declared type of the variable that points the object: Object o = new Object(); o.toString() will call the method toString declared in Object, while Object o = new Integer(); o.toString() will call the method toString declared in Integer. The overriding method Integer.toString has specialized the implementation of Object.toString to adjust the print operation when invoked on an Integer instance. This is polymorphism, the same name/operation (toString/printing) applied to hierarquically related objects, but adjusted to the nature of them. Also known as behaviour dependent on type.