Why doesn't java.lang.ref.Reference<T> implement Supplier<T>? - java

I'm looking at the class java.lang.ref.Reference (and it's sub-classes) and I'm wondering why it doesn't implement Java 8's Supplier<T> interface.
Seems like this should be a no-brainer. Supplier's get() method is satisfied by Reference. The only reason I'm hesitating to implement an extension of SoftReference<T> myself that also implements Supplier<T> is because I know that References are special-cased by the garbage collector.
Are there any problems you can forsee with making a class like this
public class SoftReferenceSupplier<T> extends SoftReference<T> implements Supplier<T>
{
public SoftReferenceSupplier(T referent)
{
super(referent);
}
public SoftReferenceSupplier<T referent, ReferenceQueue<? super T> queue)
{
super(referent,queue);
}
}
I don't want to in some way defeat the purpose of SoftReferences because of some garbage collection caveats interferring with how Supplier's are handled.
BTW, I am aware the SoftReferences will return null upon a full garbage collection. I have a need SoftReferences in my program and I'd like to have it implement this function interface in order to increase the flexibility.

Reference is a lot older than Supplier. As far as I can tell, changing Reference<T> to implement Supplier<T> would not have broken any existing code, however in my view it wouldn't make a lot of sense. When all the new functional interfaces were introduced into the language, it would have been possible to have gone through every existing class and make each one implement every new functional interface that happened to have a matching method, but I can't see the value of this.
In many cases, there is no point in a class actually implementing a functional interface at all, because if you need to regard an object as an instance of a functional interface, you can just use a method reference.
Reference<Object> reference = new WeakReference<>(someObject);
Supplier<Object> supplier = reference::get;
This solution does not depend on the fact that the two methods happen to both be called get, so in my view it is preferable to making Reference implement Supplier.

I did some Googling, but didn't find anything related to why Java's Reference class doesn't implement the Supplier interface. But the Javadoc of Supplier leaves some clues. I think that the answer lies in how the Supplier was introduced to Java - namely as a functional programming interface for use in Lambda expressions. The meanings of the two get() methods just mean logically different things. The get() method of an instance of the Reference class returns the referent; the get() method of Supplier instance returns the result of a lambda expression. It's hard to imagine a semantic overlap between the two, unless I was creating a lambda expression involving JVM soft, weak, and/or phantom references.

Related

Why does Google Guava's Multimap.get(TKey) method not instead accept Object?

There must be a good reason, or some history behind this design decision. Or perhaps I misunderstand the use case.
Background: Google Guava has a Multimap interface. The get method has signature: Collection<V> get(#Nullable K key). I expected: Collection<V> get(#Nullable Object key)
Normally generic map-like interfaces accept Object to get methods as it helps with wildcards. See Java's Map interface (and What are the reasons why Map.get(Object key) is not (fully) generic).
I have a method that accepts a Multimap with wildcards, such as: void doWork(Multimap<? extends MyKeyType, ? extends MyValueType>). However, even with a MyKeyType reference, I cannot call (effectively) Multimap.get(? extends MyKeyType). (The code will not compile.)
I guess, just because this eliminates a lot of dumb errors when you supply something wrong to get() method and just have null returned without any compilation error or runtime exception. Such problems in the code can only be discovered using static analysis tools like FindBugs (see GC_UNRELATED_TYPES pattern), but even FindBugs cannot detect every possible such bug.
As for your case: probably you have to introduce the generic parameter instead using
void <T extends MyKeyType> doWork(Multimap<T, ? extends MyValueType> mmap) {}
And every instance of your key reference should actually have the T type. If it's impossible for you, then you may use ugly unchecked cast like this:
((Multimap<MyKeyType, ? extends MyValueType>)mmap).get(key)
Probably it's a good idea to assign casted multimap to the intermediate variable.

Why isn't #FunctionalInterface used on all the interfaces in the JDK that qualify?

Java 8 gave us many fun ways to use functional interfaces and with them a new annotation: #FunctionalInterface. Its job is to tell the compiler to yell at us if we fail to stick to the rules of a functional interface (only one abstract method that needs overriding please).
There are 43 interfaces in the java.util.function package with this annotation. A search of jdk.1.8.0/src for #FunctionalInterface only turns up 57 hits. Why are the other interfaces (such as AutoCloseable) that could have added #FunctionalInterface still missing it?
There is a bit of a vague hint in the annotations documentation:
"An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface"
Is there any good reason NOT to intend that an interface I've designed (that may simply happen to be a functional interface) not be used as one? Is leaving it off an indication of anything besides not realizing it could have been added?
Isn't adding abstract methods to any published interface going to screw anyone implementing it, functional or not? I feel cynical assuming they just didn't bother to hunt them all down but what other explanation is there?
Update: After looking over "Should 'Comparable' be a 'Functional interface'?" I find I still have nagging questions. When a Single Method Interface and a Functional Interface are structurally identical what's left to be different? Is the difference simply the names? Comparable and Comparator are close enough to the same semantically. Turns out they are different structurally though so still not the best example...
Is there a case when an SMI is structurally fine to use as a Functional Interface but still discouraged over the semantic meaning of the name of the interface and the method? Or perhaps the contract implied by the Javadocs?
Well, an annotation documenting an intention would be useless if you assume that there is always that intention given.
You named the example AutoCloseable which is obviously not intended to be implemented as a function as there’s Runnable which is much more convenient for a function with a ()->void signature. It’s intended that a class implementing AutoCloseable manages an external resource which anonymous classes implemented via lambda expression don’t do.
A clearer example is Comparable, an interface not only not intended to be implemented as a lambda expression, it’s impossible to implement it correctly using a lambda expression.
Possible reasons for not marking an interface with #FunctionalInterface by example:
The interface has programming language semantics, e.g. AutoClosable or Iterable (that’s unlikely to happen for your own interfaces)
It’s not expected that the interface has arbitrary implementations and/or is more an identifier than the actual implementation, e.g. java.net.ProtocolFamily, or java.lang.reflect.GenericArrayType (Note that the latter would also inherit a default implementation for getTypeName() being useless for lambda implementations as relying on toString())
The instances of this interface should have an identity, e.g. java.net.ProtocolFamily, java.nio.file.WatchEvent.Modifier, etc. Note that these are typically implemented by an enum
Another example is java.time.chrono.Era which happens to have only a single abstract method but its specification says “Instances of Era may be compared using the == operator.”
The interface is intended to alter the behavior of an operation for which an implementation of the interface without inheriting/implementing anything else makes no sense, e.g. java.rmi.server.Unreferenced
It’s an abstraction of common operations of classes which should have more than just these operations, e.g. java.io.Closeable, java.io.Flushable, java.lang.Readable
The expected inheritance is part of the contract and forbids lambda expression implementations, e.g. in java.awt: ActiveEvent should be implemented by an AWTEvent, PrinterGraphics by a Graphics, the same applies to java.awt.print.PrinterGraphics (hey, two interfaces for exactly the same thing…), wheras javax.print.FlavorException should be implemented by a javax.print.PrintException subclass
I don’t know whether the various event listener interfaces aren’t marked with #FunctionalInterface for symmetry with other multi-method event listener that can’t be functional interfaces, but actually event listeners are good candidates for lambda expressions. If you want remove a listener at a later time, you have to store the instance but that’s not different to, e.g. inner class listener implementations.
The library maintainer has a large codebase with more than 200 candidate types and not the resources to discuss for every interface whether it should be annotated and hence focuses on the primary candidates for being used in a functional context. I’m sure, that, e.g. java.io.ObjectInputValidation, java.lang.reflect.InvocationHandler, juc RejectedExecutionHandler & ThreadFactory wouldn’t be bad as #FunctionalInterface but I have no idea whether, e.g. java.security.spec.ECField makes a good candidate. The more general the library is, the more likely users of the library will be able to answer that question for a particular interface they are interested in but it would be unfair to insist on the library maintainer to answer it for all interfaces.
In this context it makes more sense to see the presence of a #FunctionalInterface as a message that an interface is definitely intended to be usable together with lambda expressions than to treat the absence of the annotation as an indicator for it’s being not intended to be used this way. This is exactly like the compiler handles it, you can implement every single abstract method interface using a lambda expression, but when the annotation is present it will ensure that you can use this interface in this way.
Planned expansion. Just because an interface matches the requirements of an SMI now doesn't mean that expansion isn't needed later.
In java 8, functional interface is an interface having exactly one abstract method called functional method to which the lambda expression’s parameter and return types are matched.
The java.util.function contains general purpose functional interfaces used by JDK and also available for end users. While they are not the complete set of funtional interfaces to which lambda expressions might be applicable, but they provide enough to cover common requirements. You are free to create your own functional interfaces whenever existing set are not enough.
There are many such interfaces available which deserves to be designated as functional interface but java.util.function package already provides functional interfaces for our almost all purposes.
For example look into following code.
public interface Comparable<T> {
public int compareTo(T o);
}
#FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable can also take an object and derive some int type value but there is a more general dedicated interface ToIntFunction is provided to perform this task. There is no such hard rule that all the deserving interfaces should be annotated with #FunctionalInterface but to gain the advantage of lambda feature, the interface should fulfill all criterias defined by FunctionalInterface.

Should 'Comparable<T>' be a 'Functional interface'?

The definition of a functional interface is "A functional interface is an interface that has just one abstract method
(aside from the methods of Object ), and thus represents a single function contract."
According to this definition, the Comparable<T> is definitely a functional interface.
The definition of a lambda expression is "A lambda expression is like a method: it provides a list of formal parameters
and a body - an expression or block - expressed in terms of those parameters."
Evaluation of a lambda expression produces an instance of a functional interface.
Thus, the purpose of the lambda expression is to be able to create an instance of the functional interface, by implementing
the single function of the functional interface. ie. to allow the creation of an instance with the single function.
Let us look at Comparable<T>, is this interface designed for use as a single function?
ie. was it designed for the creation of instances with this single function only?
The documentation of Comparable<T> starts with "This interface imposes a total ordering on the objects of each class that
implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred
to as its natural comparison method."
The above sentence makes it clear that the Comparable<T> is not designed to be used as a single function, but is always
meant to be implemented by a class, which has natural ordering for its instances, by adding this single function.
Which would mean that it is not designed to be created by using a lambda expression?
The point is that we would not have any object which is just Comparable only, it is meant to be implemented and thus used
as an additional function for a class.
So, is there a way in the Java language, by which creation of a lambda expression for Comparable<T> is prevented?
Can the designer of an interface decide that this interface is meant to be implemented by a class and not meant to be
created as an instance with this single method by use of a lambda expression?
Simply because an interface happens to have a single abstract method, it should not be considered as a functional interface.
Maybe, if Java provides an annotation like NotFunctional, it can be checked by the compiler that this interface is not used
for the creation of a lambda expression, eg.
#NotFunctional
public interface Comparable<T> { public int compareTo(T t); }
A lambda expression can be used where an instance of an interface with a single abstract method is required. You wrote,
Simply because an interface happens to have single abstract method, it should not be considered as a functional interface.
This is exactly correct. Having a single abstract method is a structural property of an interface, one that makes it eligible to be implemented with a lambda. However, whether an interface makes sense or is semantically sensible to be implemented with lambda is a different story. The latter is the purpose of the #FunctionalInterface annotation. When it is present on an interface, it indicates the intent that the interface is useful to be implemented with a lambda.
Notably, the Comparable interface lacks the #FunctionalInterface annotation.
While it's probably nonsensical to use a lambda as a Comparable implementation, there doesn't seem to be any reason to create a mechanism to prevent this from being done. It doesn't seem like doing this would be a source of error, which would be a good reason to develop such a mechanism. By contrast, the #FunctionalInterface annotation is intended to guide programmers in the right direction instead of prohibiting something that is arguably wrong but doesn't seem truly harmful.
The issue comes from a subtle difference between a "method" and a "function".
The output value of a function depends ONLY on the arguments that are input to that function.
However the output of a method depends on the arguments that are input to the function but it may also depend on the object's state (instance variables).
That is, any function is a method but not all methods are functions.
For example, the method compare in the interface Comparator depends only on its arguments. However, the method compareTo in the interface Comparable depends on the state of the object to compare to, so it needs to be implemented in a class.
So even Comparable has one abstarct method, semantically it shouldn't be considered as a functional interface.
Well, asides from the discussion how usefull the informative annotation #FunctionalInterface is (and I am happy Java 8 does not require it for lambdas).
Comparable is typically a property of a type and therefore not a good candidate for a functional interface. It is explicitly described as the natural ordering and does not take the two this/that arguments. So this property makes it unlikely any method would operate on a lambda (similliar argument is applicable for nearly all -able interfaces).
So, the collection designers use a second interface for that task: Comparator<T>, and for that a lambda implementing it is a very natural choice.
There is no mechanism to prevent a naive use of an interface not intended to be a functional interface.
by having an additional annotation like #NotFunctional, it could be declared explicitly by a
designer of an interface, that it should not be used as lambda.
And by default if no annotation is specified, it can be considered as good as #Functional,
which is currently the case.

About the Java interface and polymorphism

I just met an strange case when reading the Java doc. Here is the link to Oracle's java doc on Arrays.asList method, http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList(T...)
There is an example in the doc
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
My question is, as List is an interface, why can we declare stooges as a 'List', rather than a concrete subclass implementing List(e.g. ArrayList or LinkedList)?
So does it mean that we can have a reference variable of interface type? It looks quit weird to me as I always think that interface stands only for polymorphism, and we should never really use a interface type variable.
Could anyone please give me some clue on this?
Think of the List interface as a guarantee. Any class that implements List will be guaranteed to have the methods of the interface. When Arrays.asList() returns a List you're not actually getting an interface, you're getting a concrete class that is guaranteed to implement the methods listed in the List interface.
As to your "we should never really use a interface type variable" you're actually suppose to do that. It's called "programming to the interface". It's much more flexible if you can return a List as opposed to something like a LinkedList. The caller of your method isn't coupled to your specific implementation internal implementation which might use, and return, a LinkedList. If at some point you wanted to return a ArrayList instead of the LinkedList the caller would not have to change any code because they only care about the interface.
What does it mean to "program to an interface"?
Just a word of note, Serializable is a marker interface and a little odd because of that. It doesn't guarantee that methods are there, but instead guarantees that the creator of the class that implements serializable has thought about the many issues associated with serializing a class (overriding readObject/writeObject, compatiblity with other serialized forms, and other issues http://www.javapractices.com/topic/TopicAction.do?Id=45). So Serializable is still offering a guarantee, like List is, but it isn't about method signatures, it's about an extralinguistic feature of the language.
http://en.wikipedia.org/wiki/Marker_interface_pattern
Using an Interface as a reference type is a perfectly valid practice in Java. For example, the Serializable interface will do this inside it's class, so that any object that is passed to it can be serialized.
This is also how Java provides something that resembles Multiple Inheritance. For example:
public interface A { }
public class B implements A {}
public class program {
B bClass = new B();
A aObject = (A)bClass;
}
That way the same object can be referenced with different reference types, and all without messing up an inheritance chain!
The interface defines a contract or a specification for an implementation. Which is the methods and their signature. So a class that implements an interface has to respect that contract. This way you can change implementation without affecting the code that uses interfaces for declaring variables.
In the example you mentioned:
You don't know what implementation of the List interface Arrays.asList is using unless you look into the code. So how would you know which one to use? (see javadoc for list interface to see what implementations it has)
The implementation is subject for change, what if Arrays.asList decides to use another implementation? Your code will be broken.
The signature of the method Arrays.asList is that it returns List<T> so if you want to have a concrete implementation as variable you'll have to cast that return value which is bad practice or to create new - let's say ArrayList - and copy all the elements into it, which is just an unnecessary overhead.
Effective Java by Bloch is a great book on Java best practices. In particular, item #52 talks about this: "If the appropriate interface types exist ... declared using the interface types."
The general notion is that, for greatest flexibility and understandability, you should use the type that best reflects the context, which is usually the interface. In the example, you provided, does the exact implementation matter or just that it is a List. Of course, if the code requires an ArrayList-specific method or if the code is relies on an ArrayList-specific behavior, then use the concrete class.
There are occasional exceptions, such as when using GWT-RPC, but this is for implementation reasons.
This is really good example of polymorphism power, if you like you can look at the source code of Arrays.asList() here Arrays.asList(T...a) ,you will find that it takes varibale length input and defines its own private static concrete class ArrayList that implements List interface rather than using the well known java.util.ArrayList or other java Collection type,
this may be to make it more efficient or something, you want to implement your own class and you return it to the user without overwhelming him by implementation details since there is an interface he can deal with your private class through.

Java collections API: why are Unmodifiable[List|Set|Map] not publicly visible classes?

Collections.unmodifiableList(...) returns a new instance of a static inner class UnmodifiableList. Other unmodifiable collections classes are constructed same way.
Were these classes public, one had two advantages:
ability to indicate a more specific return value (such as UnmodifiableList), so an API user wouldn't come to the idea of modifying that collection;
ability to check during runtime if a List is instanceof UnmodifiableList.
So, were there any advantages not to make those classes public?
EDIT: No definitely convincing arguments were presented, so I choose the most upvoted answer.
Personally I completely agree with you. At the core of the problem is that fact that Java's generics are not covariant, which, in turn, is because Java's collections are mutable.
It is not possible for Java's type system to codify a type that seems to have mutators is actually immutable. Imagine if we were to start designing some solution:
interface Immutable //marker for immutability
interface ImmutableMap<K, V> extends Map<K, V>, Immutable
But then ImmutableMap is a subclass of Map, and hence Map is assignable from ImmutableMap so any method which returns such an immutable Map:
public ImmutableMap<K, V> foo();
can be assigned to a Map and can therefore be mutated at compile time:
Map<K, V> m = foo();
m.put(k, v); //oh dear
So, you can see that the addition of this type has not actually prevented us from doing anything bad. I think for this reason a judgement was made that it did not have enough to offer.
A language like scala has declaration-site variance annotations. That is, you could specify a type as being covariant (and hence immutable) as Scala's Map is (actually it's covariant in its V parameter). Hence your API can declare whether its return type is mutable or immutable.
As another aside, Scala lets you declare intersection types so that you don't even need to create the ImmutableXYZ interface as a separate entity, you could specify a method to return:
def foo : XYZ with Immutable
But then scala has a proper type system, whereas Java does not
I think both advantages are there but are not that useful. The main problems remain the same: UnmodifiableList still is a List and thus all the setters are available and the underlying collections still are modifiable. Making the class UnmodifiableList public would add to the illusion of being unmodifiable.
The nicer way would be for the compiler to help, but for that the collection class hierarchies would have to changed a lot. E.g., the collection API of Scala is way more advanced in that respect.
A disadvantage would be the introduction of at least three additional classes / interfaces into the API. Because of them not being that useful, I think leaving them out of the API is a good choice.
If it important for you to check if the list was created with Collections.unmodifiableList then you can create an instance and ask for the class. Now you you can compare this class with the class of any list.
private static Class UNMODIFIABLE_LIST_CLASS =
Collections.unmodifiableList( new ArrayList() ).getClass();
...
if( UNMODIFIABLE_LIST_CLASS == listToTest.getClass() ){
...
}
The answer to the why is quite simple: at the time, in 1998, efficient design was a bit flanky. People thought about it it wasn't apparently a priority. But there was no true, deep thinking about it.
If you want to use such a mechanism, use Guava's ImmutableList/Set/Map/...
They are explicitly Immutable and a good practice when using that library is not to return a List for instance but an ImmutableList. So you will know that a List/Set/Map/... is immutable.
Example:
private final ImmutableList constants = ...;
public final ImmutableList<String> getConstants() {
return constants;
}
About the design itself of UnmodifiableXxx, one could have done the following:
public static final class UnmodifiableXxx implements Xxx { // don't allow extend
// static if inside Collections
UnmodifiableXxx (Xxx backend) { // don't allow direct instanciation
...
}
...
}
Suppose UnmodifiableList was a public class. I suspect that it would lull programmers into a false sense of security. Remember, UnmodifiableList is a view of a modifiable List. This means that the contents of an UnmodifiableList can still change via any changes made to its underlying List. A naive programmer may not understand this nuance and may expect instances of UnmodifiableList to be immutable.
ability to indicate a more specific return value (such as UnmodifiableList), so an API user wouldn't come to the idea of modifying that collection;
In a proper API, this should already be documented in the javadoc of the method returning the unmodifiable list.
ability to check during runtime if a List is instanceof UnmodifiableList.
Such a need indicates that the actual problem lies somewhere else. It's a flaw in the code design. Ask yourself, have you ever had the need to check if a List is an instance of ArrayList or LinkedList? Whether it's an ArrayList, LinkedList or UnmodifiableList is clearly a decision which is to be made during code write time, not during code run time. If you're encountering problems because you're attempting to modify an UnmodifiableList (for which the API developer may have very good reasions which should be already documented), then it's rather your own fault, not a runtime fault.
All with all, it makes no sense. The Collections#unmodifiableXXX(), synchronizedXXX() and checkedXXX() do in any way not represent concrete implementations. They are all just decorators which can be applied regardless of the underlying concrete implementation.
I think the answer is because the method form properly knows about the generics used and requires no extra programming to pass this information through, whilst the class form would require more messing about. The method form for unmodifiableMap has two floating generic arguments, which it maps to both the generic arguments of the return type and of the passed argument.
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
return new UnmodifiableMap<K,V>(m);
}

Categories

Resources