Why `private static` field is not allowed in Java 8 interface?
Asked Answered
Z

5

16

When I'm trying to compile the following code

public interface SomeInterface{
    private static Logger logger = Logger.getLogger();

    public default void someMethod(){
        logger.info("someMethod: default implementation");
    }
}

I get an error

Illegal modifier for the interface field SomeInterface.logger; only public, static & final are permitted

When I delete private modifier, code compiles, but I don't want other classes from the package to see this field.

Why Java doesn't allow me to do such thing when it actually does make sense?

Zavras answered 16/7, 2015 at 10:50 Comment(6)
what if you override the someMethod method?Larrikin
@Larrikin I will provide new implementation. What if I don't override it?Zavras
Logically speaking, interfaces are meant to provide a way of generalizing the behavior of several different classes. That is - what the user has to do to control the behavior of that class. Take a car (in real life) for example: you have a wheel, radio, brakes, clutch, etc. You know about those and you learn how to operate them. But if the interface includes something that you have no access to - how will you use that to control the behavior of the class? In other words - interfaces are your gateway to the world - use them to generalize not to hide fields, etc...Erg
@Erg but this private field is needed by the default implementation. Interfaces were meant not to provide any implementation, but Java 8 changed this a bit.Zavras
I know people will say that this is not correct, but in a way, interfaces are getting closer to cpp abstract classes. Why? I don't know. But the implementation should take care of that. The user implementing an interface should not at all look at the private stuff.Erg
@Erg Why? I don't know---defender methods were the prerequisite to the effective introduction of the Streams API to the JDK. Many interfaces needed extension and without defenders that would be impossible as it would break Java's serious promise of backward compatibility.Mcelrath
M
22

In the pre-Java-8 view of the world, interfaces were purely for interface contracts, and private members exist purely for implementation, so this restriction was completely sensible.

In the post-Java-8 world, where interfaces can carry behavior (but not state), it starts to be reasonable to ask whether other features of classes should be applied to interfaces as well. (However, just because something might be "reasonable" doesn't mean it must be supported; there is often more than one reasonable way to construct the world.)

In Java 9, private methods in interfaces will be supported.

Modal answered 18/7, 2015 at 13:46 Comment(5)
this answer explains my question the best :) do you have some references to private members in Java 9?Zavras
kamil09875: openjdk.java.net/jeps/213 (point 5); if you think, this answers your question, you can accept the answer.Cedrickceevah
"In Java 9, private members in interfaces will be supported" - It seems, that only private methods are supported, but not private static final fields? Do you have any information about why private static final fields were left out?Phratry
They were never in. I should have said "methods" above, as that was the plan all along; consider it a typo. (Answer has been edited.)Modal
Why private static final fields are left out?Placer
M
9

Interfaces are not classes. They have no private state. Even a public logger in the interface is a design smell and an abuse of interfaces.

The use case for static fields in interfaces is mainly for compile-time constants, not for stateful objects.

Mcelrath answered 16/7, 2015 at 10:51 Comment(1)
Yeah I don't think it is "design smell".Buckskin
L
0

The goal of interface is to define something implemented by other classes. A private field does not define anything as it is not visible outside the interface. Hence it does not make any sense in this construct. It may be some hacks how to use it (maybe from interface inner classes) but would not look like a good design anyway.

If you actually implement part of the functionality, use abstract class instead.

Lacrimatory answered 16/7, 2015 at 11:2 Comment(7)
default implementation is not visible outside of the interface tooZavras
Visible in the same package.Hexyl
how is it visible in the same package? also Java 8 interfaces are different because they actually do implement part of the functionality. If they weren't private static field wouldn't be needed at allZavras
Then why we have private method in Java 9? Consider your "A private field does not define anything as it is not visible outside the interface. Hence it does not make any sense in this construct."Placer
@LiSeeLeiCow-Q__Q Private methods help with the implementation of default methods (e.g. prevent code duplication). Same with private static methods ↔ public static methods.Husain
@Husain so would private fieldsBuckskin
@Buckskin But an interface defines behavior, not state. The presence of private methods does not violate that "principle", whereas allowing private fields would. Of course, that really only applies to instance fields. Maybe some day they will allow private static fields in interfaces. My guess, however, is that the designers don't want you to use interfaces like abstract classes.Husain
J
0

Interface is like a blueprint of any class, where you declare your members. Any class that implement that interface is responsible for its definition. Private members can only be accessed by same class member, which does not make sense in terms of interface. Protected members can be accessed by same class member and inherited class members, but in case of interface we never extend an interface, we implement it. So any interface can only contain public methods generally,

Jaworski answered 16/7, 2015 at 11:4 Comment(0)
E
0

public interface SomeInterface {
    public default void someMethod() {
        SomeInterfaceInternal.logger.info("someMethod: default implementation");
    }
}

final class SomeInterfaceInternal {
    protected static final Logger logger = LoggerFactory.getLogger(SomeInterface.class);
}

Ellette answered 30/4, 2019 at 6:32 Comment(2)
this has same issue as original package private field, ie classes from package can access itBuckskin
@Buckskin actually you never had a "package private field". If you delete the modifier on a member of an interface you get a public member, not a package private member.Horseshoe

© 2022 - 2024 — McMap. All rights reserved.