I was reading through the Map.Entry interface, when I noticed it is a static interface. I didn't quite understand what a static interface is, and how is it different from a regular interface?
public static interface Map.Entry<K,V>
This is the definition of the interface. Docs here: Map.Entry<K,V>.
I'm curious about the case when it's not an inner interface.
The static modifier is only allowed on a nested classes or interfaces. In your example Entry is nested inside the Map interface.
For interfaces, the static modifier is actually optional. The distinction makes no sense for interfaces since they contain no code that could access the outer this anyway.
Static inner interface and inner interface is the same, all access rules are the same as with inner static class. So inner interface can be accessible only if you have access to its parent class/interface. In case below you will have access to interface B only from package of interface A, because A has default access modifier. BTW: interface B could be static or not.
interface A {
void testA();
public interface B {
void testB();
}
}
Finally, even Android Studio indicates that using static with inner interface is not needed:
Related
I want to declare an interface inside an inner class, which shows compiler error message "inner classes cannot have static declarations".
public class Apple {
//...
public class InnerApple{
//...
public interface InnerInterface{
//Error: inner classes cannot have static declarations
}
}
}
Does it mean interface is actually static in Java?
I'm using Java 1.7. Thanks!!
An interface is always static - in a sense that there cannot be any dependency to another instance.
Having two levels of inner declarations is quite uncommon, but if it is intended I would expect that at least InnerApple is static:
public class Apple {
public static class InnerApple{
public interface InnerInterface{
//this does not cause an error
}
}
}
In most cases the keyword static of inner classes is omitted. If so this class may contain dependencies to a surrounding instance (and not only to the class as static inner classes do).
Yes, member interfaces are implicitly static. Section 8.5.1 of the JLS states:
A member interface is implicitly static (§9.1.1).
For it not to be static, the interface must be top-level, with no enclosing class or interface.
Consider the following classes:
class A {
void print() {
System.out.println("A");
}
}
class B extends A implements C {
}
public interface C {
void print();
}
I get this error:
The inherited method A.print() cannot hide the public abstract method
in C
Now, I understand that print() must be public in order the eliminate the compilation error, but what's the reason behind this?
The answer is simple interface methods are always public or else just use composition instead of inheritance. Also to note that while overriding a method you can not narrow down the access level of the method.
The Oracle Docs says:
The access modifier public (§6.6) pertains to every kind of interface
declaration.
B#print can never be truly private, because anyone can call it via the interface:
B b = new B();
C c = b;
c.print();
Java doesn't let you pretend it's private when it is effectively public. (C++ does; different languages make different trade-offs.)
The method void print() in class A is implementation for the interface method declaration. Now , in the interface C this method is public ( every interface method is public by default ) and the rules of OOP ( Liskov principle in particular ) dictates that the visibility of this method's implementation in class A cannot be lower than that in its interface - hence it has to be public.
Short answer is because Java doesn't allow it. According to the Java Language Specification under 9.1.1. Interface Modifiers - JLS-9.1.1,
The access modifier public (§6.6) pertains to every kind of interface declaration.
The access modifiers protected and private pertain only to member interfaces within a directly enclosing class or enum declaration (§8.5.1).
So if you don't specify an access modifier in your non-member interface (like void print()) it is public and your class which implements that interface must provide a public void print().
Well, think it this way: if an interface defined private methods then these methods would only be called by the class implementing the interface, and that doesn't make much sense, since (in Java) an interface defines the contracts between classes. When a class follows an interface then the methods defined in the interface can be called in the implementation by external classes.
In your case, your class B is extending A while class A is not implementing the interface C. So, by extending A it inherits a method that has less access than the one defined in the interface, and that is not allowed.
If your class A had implemented the interface you would have seen the error "Cannot reduce the visibility of the inherited method from C"
All the methods in an interface are implicitly public. The names and return types of the methods(the ones B inherits from A and C) are same in your case but the visibility modifiers are different. And if you change the visibility modifier of an inherited method the compiler will complain because you cannot reduce the visibility of an inherited member.
I have the following situation.
package A;
class SampleClass
{
static interface sampleInterface
{
....
}
}
Now when I try to import the sampleInterface from another package , jDev says 'access not allowed'. What could be the problem?
Currently, the interface is seen as package-private (there's no visibility modifier, so that's the default). Place public on the outer class and the interface, and it will become visible to other classes.
Just be careful - if you get caught in a situation where you have to do this:
public class Alpha extends Alpha.IAlpha {
public void doNothing();
public static interface IAlpha {
public void doNothing();
}
}
...you'll have an issue with cyclic inheritance, and your class won't compile. In fact, you won't be able to use the interface at all.
Keep these rules in mind for exposing interfaces, classes, or enums:
If you only need an inner class, interface, or enum for that particular object, then it's fine to declare it as static.
If you need a class, interface, or enum accessible from anywhere but that object, then it's best to move it out of the inner class, and into its own file.
In general, interfaces are seen as APIs to conform by - there's really no benefit in having them as nested unless the scope of them is extremely narrow.
Change visibility of the class and the interface to public. It will work for sure.
When you declare a class without a access specifier it is by package-default. This means you can access that class in that package only.
If you want to access class from another package, make class public, i.e.
public class SampleClass
Similarly, in your case, as you want to access the Interface as well, you have to make that interface public as well.
This will solve your problem.
I am wondering what does it mean to have a nested abstract class ? for example,
abstract class A{
abstract class B{
}
}
Are there any use cases or scenario that we might need such as design ? or is there something useful in such pattern ? and why Java allows us to do it ?
In design, you want the base class class A to present only an interface for its derived classes. This means, you don’t want anyone to actually instantiate an object of the base class. You only want to upcast to it (implicit upcasting, which gives you polymorphic behavior), so that its interface can be used. This is accomplished by making that class abstract using the abstract keyword. In other hand you want to use only part of functionality of class A so you create class B (as child) to reduce the coupling or implementation dependencies between systems and prevent duplicates.
But bear in mind when you define an inner class, code without inner classes is more maintainable and readable. When you access private data members of the outer class, the JDK compiler creates package-access member functions in the outer class for the inner class to access the private members. This leaves a security hole. In general we should avoid using inner classes. Use inner class only when an inner class is only relevant in the context of the outer class and/or inner class can be made private so that only outer class can access it. Inner classes are used primarily to implement helper classes like Iterators, Comparators etc which are used in the context of an outer class. About abstract class, it should be abstract to helpers, suppose your helpers should be too complicated to write abstract form for them.
In your case, I don't remember extensive usage of nested abstract classes, maybe in Swing world.
abstract classes are used to provide a partial implementation of a class for inheritance. it allows you to define the scheme of a class without providing the full definiton, so that it can be specified in a child class. it works somewhat like a Interface in that you can perform any operation specified in the abstract class upon an instance of any classes derived from it. Nested abstracted classes are designed to be inherited by other inner classes (even anonymous ones I think) but not by classes defined outside the outermost class.
public class HelloEveryone{
abstract class Hello{
void SayHello(){
System.out.println("Hello!");
}
abstract void SayHelloAlt();
}
public class HelloWorld extends Hello{
public void SayHelloAlt(){
System.out.println("HelloWorld!");
}
}
public class HelloUniverse extends Hello{
public void SayHelloAlt(){
System.out.println("HelloUniverse!");
}
}
void Go(){
ArrayList<Hello> hellos = new ArrayList<Hello>();
hellos.add(new HelloWorld());
hellos.add(new HelloUniverse());
for (Hello h : hellos){
h.SayHello();
h.SayHelloAlt();
}
}
}
static void main(){
HelloEveryone hello = new HelloEveryone();
hello.Go();
}
I have this interface:
public interface ISectionListItem {
public int getLayoutId();
public void setProps(View view, int position);
}
But i want all the classes who implements this interface be forces to have a static class inside them. I thought of:
public interface ISectionListItem {
public int getLayoutId();
public void setProps(View view, int position);
static class ViewHolder {};
}
But that dosn't force the classes to "add unimplemented inner classes". Anyway to accomplish this? Is it even possible?
Thanks :)
The point of an interface is that you're defining a contract, not an implementation. If you really need to have an instance then you'd want to do something like
public ViewHolder getViewHolder();
and define a viewholder interface. Again, the idea is that you're not creating an implementation, you're expressing a contract.
This is not possible by the nature of interfaces. An interface defines the public behavior of objects; if a class implements an interface, that means that all instances of that class obey the contract defined by the interface. For this reason interfaces can't contain static members. (There's an exception to this rule, but at this point you shouldn't care about that.)
Be careful of your terminology: static member classes are not inner classes. Static member classes are like normal classes, except that they live in a different namespace. Static member classes are not members of the instances of the containing class, just as any static class member is not part of the "instance template". An inner class is by definition not static.
So, why can't we declare a genuine (i.e. non-static) inner class in an interface? That's because in an interface you can only define the behavior of objects, not how they are composed. The whole point (and beauty) of interfaces is that they separate the behavior ("what does it do") from the implementation ("how is it done"). For that reason you can't declare inner classes in an interface, just as you can't declare fields in an interface.
I don't know what you're trying to do, but you might want to try the following. Let's call your original interface MyInterface.
Define an extra interface SomeType
Have your inner class implement SomeType
Declare a method like public SomeType getInnerClassInstance() (a terrible method name) in MyInterface
Note that MyInterface instances aren't forced to actually return an instance of an inner class as a result of getInnerClassInstance(). This is a nice thing, because you're not bound to a specific implementation.
You can't force someone to create an inner class.
Depending on what you want to do your best best is probably adding a method getViewHolder() to the interface and create another interface which specifies the behaviour of a ViewHolder.