问题
When I want to refer to the method in the current scope I still need
to specify class name (for static methods) or this
before ::
operator. For example, I need to write:
import java.util.stream.Stream;
public class StreamTest {
public static int trimmedLength(String s) {
return s.trim().length();
}
public static void main(String[] args) {
System.out.println(Stream.of(" aaa ", " bb ", " c ")
.mapToInt(StreamTest::trimmedLength).sum());
}
}
It's not so big problem for this
, but sometimes look overcrowded for static methods as the class name can be quite long. It would be nice if compiler allowed me to write simply ::trimmedLength
instead:
public static void main(String[] args) {
System.out.println(Stream.of(" aaa ", " bb ", " c ")
.mapToInt(::trimmedLength).sum());
}
However Java-8 compiler doesn't allow this. For me it seems that it would be quite consistent if class/object name were resolved in the same manner as it's done for normal method call. This would also support static imports for method references which also can be useful in certain cases.
So the question is why such or similar syntax was not implemented in Java 8? Are there any problems which would arise with such syntax? Or it was not simply considered at all?
回答1:
I can’t speak for the Java developers but there are some things to consider:
There are certain kind of method references:
- Reference to a static method, e.g.
ContainingClass::staticMethodName
- Reference to an instance method of a particular object, e.g.
containingObject::instanceMethodName
- Reference to an instance method of an arbitrary object of a particular type, e.g.
ContainingType::methodName
- Reference to a constructor, e.g.
ClassName::new
The compiler already has to do some work to disambiguate the forms 1 and 3 and sometimes it fails. If the form ::methodName
was allowed, the compiler had to disambiguate between three different forms as it could be any of the three forms from 1 to 3.
That said, allowing the form ::methodName
to short-cut any of the form 1 to 3 still wouldn’t imply that it is equivalent to the form methodName(…)
as the expression simpleName ( argopt )
may refer to
- an instance method in the scope of the current class or its superclasses and interfaces
- a
static
method in the scope of the current class or its superclasses - an instance method in the scope of an outer class or its superclasses and interfaces
- a
static
method in the scope of an outer class or its superclasses - a
static
method declared viaimport static
So saying something like “::name
should be allowed to refer to any method name(…)
may refer to” implies to combine the possibilities of these two listings and you should think twice before making a wish.
As a final note, you still have the option of writing a lambda expression like args -> name(args)
which implies resolving name
like a simple method invocation of the form name(args)
while at the same time solving the ambiguity problem as it eliminates the option 3 of the method reference kinds, unless you write explicitly (arg1, otherargs) -> arg1.name(otherargs)
.
来源:https://stackoverflow.com/questions/31665393/thismethodreference-or-equivalent-in-static-init-block-in-java-8