I think it can't, because marker interface principle is to not have any methods, but since default methods are not abstract I am not sure.
相关问题
- Delete Messages from a Topic in Apache Kafka
- Jackson Deserialization not calling deserialize on
- How to maintain order of key-value in DataFrame sa
- StackExchange API - Deserialize Date in JSON Respo
- Difference between Types.INTEGER and Types.NULL in
A Marker Interface is a design pattern, so we can start to answer your question by observing just what the definition is:
The purpose of a Marker interface, in the context of Java, was to say something about that class. Funnily enough, it marked it as something. An example of this is the
Serializable
interface, that did nothing but marked that aClass
was able to be serialized into aString
. The question here is:Does the definition include functionality?
No, I don't think it does. Functionality is more than just metadata about the class; it helps to define the class itself. It takes that step from metadata to data. So in terms of the design pattern, a marker interface can not define or declare functionality; it can simply make a statement about the implementing
Class
.Although @Azar's answer is correct, we mustn't forget that Effective Java was written before default methods were introduced.
What is a marker interface?
There are two ways of looking at marker interfaces:
The "official" definition is the first one but up until Java 7 those two statements were equivalent. It is a recurring pattern in Effective Java that once you publish an interface, you can't add any methods to it because it would force the implementation of the new methods.
However, this is exactly the problem default methods are trying to address: to allow for evolution of interfaces without the need to retrofit all classes implementing them. It also makes the two statements above mean slightly different things: a default method clearly violates statement 1 and by design doesn't violate statement 2.
What does all this mean in practice?
Imagine that you write an XML serialization engine and you create a marker interface
XmlSerializable
to go with it:So far, so good. But later on you realise that you actually have some classes that need special treatment, they need to provide their own custom converters. So what you may do is something like this:
Would that stop
XmlSerializable
being a marker interface? You can say it still is a marker interface as you don't really add extra behaviour directly to your interface, only extra metadata that influences the behaviour of the serializer engine. On the other hand, this solution allows implementing classes to overridecustomConverter()
, which is slightly dodgy, a marker interface shouldn't allow that. (Then again, isSerializable
andCloneable
relying on "magic" methods in the implementing class any better? I don't think so.)Arguably the example above isn't a very good way to solve this kind of problem, you'd probably be much better off using annotations. But that also holds true for most "true" marker interfaces.
tl;dr
We can conclude that an interface with only default methods is more or less equivalent to an empty interface. If you want to make a theoretical distinction and not call it a marker interface, that is of course fine. But there's little practical difference, and given the inherent problems with marker interfaces in general, we should probably avoid them anyway.
A "Marker" interface is just a regular interface as far as Java is concerned. Thus, it can have default methods just as any (Java-8) interface can.
Now, as to whether this violates the principle of a Marker interface, I would have to say yes. A Marker interface should act as a flag of sorts, only identifying that a class meets some external criteria. Now, it can be a Marker interface and have abstract/default methods, but it will no longer purely meet the definition.
From Effective Java (Second Edition):
A marker interface can have default methods, but having them is nonsensical.
A marker interface differs from a conventional interface in the way it's used. A conventional interface defines methods, both abstract and default. Thus it is sensible for a program to declare variables with that interface as its type, and to call methods of both kinds through a reference of that interface type.
A marker interface, by constrast, is not used for calling methods. It is a piece of meta-information about an object declared through the type system. It is typically used by calling code via an
instanceof
expression, or occasionallyClass.isAssignableFrom()
. It is pointless to declare a variable whose type is a marker interface, since there's nothing you can do with such a variable.Examples of marker interfaces in the JDK are
Cloneable
,RandomAccess
, andSerializable
.Now consider the addition of a default method to some marker interface:
What could the default implementation of
foo
do?Implementations of default methods typically want to operate on
this
, and they do so by calling other instance methods onthis
. They could call other default methods, but having a bunch of default methods calling each other isn't useful. Eventually, some kind of actual operation onthis
must be performed. Since interface methods have no access to state (fields), any actual operations must be performed by abstract method implementations residing in an implementing class. However, in a marker interface there are no such methods.The default implementation of
foo
could call a static method on this interface or on some other class. This is mostly pointless, as such a method would probably be better expressed as a static method in the first place. The implementation could passthis
to a static method, but that method couldn't do anything useful with such a reference, since it has no methods! Well, it might have default methods, but now we're going in circles.For a default method to be useful on an interface, that interface needs to have abstract methods as well. But if it has abstract methods, it's no longer a marker interface. Thus, it is nonsensical to have default methods on a marker interface.