3

I have a class (Say FOO) and it has a method with default visibility, like below :

void sayHi() {}

Now, If a override this method in extending class I cannot decrease it's visibility. So I can only use default or public.

public class MyClassTest extends FOO {
    @Override
    // Or I can use public void sayHi()
    void sayHi() {
        System.out.println("Overriden sayHi");
    }
}

Now if I write an Interface in Java 8 with a default method like below :

public interface InterfaceX {

    // Java-8 defalu method
    default String printName() {
        System.out.println("Interface1 default metod");
        return "Interface1 default metod";
    }
}

Now, if I override this method in a class It should compile if a keep overridden method's visibility default.

public class Java8InterfaceTest implements InterfaceX{
    @Override
     void printHello() {
        System.out.println("Printing..!");
        Interface1.super.printName();
    }
 }

It says

Cannot reduce the visibility of the inherited method from InterfaceX

I already know that every method in interface in public by default, but in the above example we are using default which I think is one of the access modifier in java.

I have following questions:

  1. Is default in interface different from default visibility which is provide when no access modifier applied?
  2. If it's different then how it's different?
Ele
  • 33,468
  • 7
  • 37
  • 75
Mehraj Malik
  • 14,872
  • 15
  • 58
  • 85
  • Why down-voted? It might be an silly questions but still I think it is a confusing question. – Mehraj Malik Dec 05 '17 at 13:05
  • 1
    I can imagine you got that for lack of prior research. And just for the record: I reworked my answer. Hopefully you find it more helpful by now. Because honestly: as correct as the two other answers are - they miss the *real* problem in your whole question. – GhostCat Dec 05 '17 at 19:27

3 Answers3

7

default has nothing to do with default visibility. A default method in an interface is a method that has a default implementation within the interface.

The visibility of that method is still public.

Therefore the method implemented in your Java8InterfaceTest class must have public visibility:

public void printHello() {
    ...
}
Eran
  • 387,369
  • 54
  • 702
  • 768
  • So, are there two `default`s : one is for `interface default method` and one is for visibility? – Mehraj Malik Dec 05 '17 at 13:02
  • 1
    @MehrajMalik the `default` keyword is never used in Java for default visibility. Default visibility has no keyword in Java. – Eran Dec 05 '17 at 13:04
  • @MehrajMalik *"So, are there two defaults"* - Yes and No. We have only one *key word* `default` which is connected to the *default method in an interface* and we have the *default visibility* where we have no keyword at all. – Timothy Truckle Dec 05 '17 at 13:06
  • @Eran `If a class has no modifier (the default, also known as package-private)` as per java docs https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html – Mehraj Malik Dec 05 '17 at 13:07
  • 2
    @MehrajMalik I didn't say there's no default visibility in Java. I said default visibility has no keyword, and therefore not related to the `default` keyword. – Eran Dec 05 '17 at 13:08
  • @Eran It seems that I've been confused with `no modifier` to `default`.. OMG... We all have been taught it's `default` ... **OH GOD! WHAT A SURPRISE** – Mehraj Malik Dec 05 '17 at 13:10
  • 2
    @MehrajMalik: it rather seems that you have been confused by the fact that all Java keywords have a literal meaning in the English language. There is also the concept of a “default constructor” which is entirely unrelated to the `default` keyword. Further, “default behavior”, found in a lot of specifications, is unrelated to said keyword. Unlike annotation default values, which use the `default` keyword but still are unrelated to `default` methods. – Holger Dec 05 '17 at 14:09
4

I think that if you write your interface as :

interface Test {
    default public void go() {

    }
}

it would make sense. default methods are still public; nothing to do with "default" visibility.

Eugene
  • 117,005
  • 15
  • 201
  • 306
2

The other answers nicely outline that "syntactical" flaw in your assumption about default being a "visibility" thing.

But there is a conceptual problem behind that worth a dedicated answer: it is not sound to reduce the visibility of methods.

Keep in mind: the pubic "API" of a class or an interface declares a contract for client code to work with. Like: having a method eat() on a base class/interface Animal.

The whole point is that different subclasses/implementations can provide their own implementation of eat(). So that you can have:

Animal whatever = ...
whatever.eat();

And no matter what ... is actually creating (could be Cat, Dog, Unicorn) - it is valid to call whatever.eat().

Your idea is to say: I want to "hide" eat() for a specific subclass Donkey. If you could do that - all of a sudden the above code might be invalid. Because whatever.eat() is no longer a valid call when whatever happens to be an instance of Donkey.

Long story short: read about the Liskov Substitution Principle to understand why "taking away" public is not a good idea - completely independent from mixing up "default package protected visibility" and the default keyword in interfaces.

GhostCat
  • 137,827
  • 25
  • 176
  • 248