In object oriented terms, when you program to an interface (i.e. implement an interface or extend an interface), you can not be more restrictive than the interface. However, you can be less restrictive. So, in your example, the interface's method may or may not throw a FileNotFoundException and/or InterruptedException, but your implementation' method will not throw an exception. Note that if your implementation's method throws a FileNotFoundException and/or InterruptedException, it is perfectly alright, but if it throws some other exception it won't be allowed. This means your implementation can be equal to or less restrictive than the interface, but it can not be more restrictive.
Also note, when someone uses your method f() through a variable of the extending interface type (C) or through a variable of class' type (Test), they don't need to handle the exception. However, if they use your method f() through a variable of interface types A or B, they need to handle the exception.
A obj = new Test();
obj.f(); // need to handle FileNotFoundException
B obj = new Test();
obj.f(); // need to handle InterruptedException
C obj = new Test();
obj.f(); // don't need to handle any of the exceptions
Test obj = new Test();
obj.f(); // don't need to handle any of the exceptions
More clarifications:
The reason why C.f() doesn't throw an exception is that it's parent interfaces throw different exceptions. So, according to the argument "interface's implementation or extension can not be more restrictive but can be less restrictive", the only way for C.f() to be less restrictive is by not throwing an exception. Otherwise, it will be more restrictive than at least one of it's parent interfaces.
On the other hand, if both of C's parents threw the same exceptions, then C.f() also needed to throw those exceptions. However, the implementation can still choose to not throw an exception.
import java.io.FileNotFoundException;
interface A{
void f() throws FileNotFoundException;
}
interface B {
void f() throws FileNotFoundException;
}
interface C extends A, B {
}
public class Test implements C {
public void f() {
System.out.println("Hello world");
}
public static void main(String[] args) {
C obj = new Test();
obj.f(); // Compilation error, unhandled exception
Test obj = new Test();
obj.f(); // No error
}
}