here while calling the process method
we have to use a try catch block but
if i store the object of C in
reference variable of C only i.e. C
a=new C() then try catch block is not
needed.Can anyone tell me the reason
why?
You need to keep in mind that the run-time type of a reference is not necessarily the same as the declared type. For example:
Number n = new Integer(1);
This declares n to be a reference of declared type java.lang.Number to reference a subclass of java.lang.Number of specific class/type java.lang.Integer.
Information about the actual run-time type is (typically) only available at run-time. But the compiler only operates at compile time. At compile time, the compiler (typically) only knows about the declared types.
Since it typically only knows about declared types, it can only go with that for making decisions on what can compile and what cannot. That is, javac can only enforce rules based on what it knows (or can infer) at compile time.
Going back to your code example:
The compiler is looking at the declared type of the reference (in this case the reference a is of type B). Based on that, the compiler knows that the method B.process() throws a checked exception that it needs to enforce.
That is, either
B a=new C();
or
B a=new B();
declare a of being of type B whose process() method throws a checked exception. However, if you have the following:
C a = new C();
then, the declared type of a is C, not B. Since subclasses can weaken the preconditions of its inherited methods, then C is free to weaken the preconditions of process(). Namely, it can declare C.process() to throw a subset of the set of exceptions thrown by B.process (and in C.process() case, it is the null set.)
This is somewhat related to the Liskov substitution principle and Design by Contract, with the former (thanks wikipedia) stating the following principles (3 and 4 being directly related to what you observed in your java code):
- Contravariance of method arguments in the subtype.
- Covariance of return types in the subtype.
- No new exceptions should be thrown by methods of the subtype, except
where those exceptions are themselves
subtypes of exceptions thrown by the
methods of the supertype.
- Preconditions cannot be strengthened in a subtype.
- Postconditions cannot be weakened in a subtype.
- Invariants of the supertype must be preserved in a subtype.
The Java compiler is simply attempting to enforce some of these principles, and by practical purposes, it uses the declared types of reference variables to determine how to enforce them.