英文:
Eclipse does not suggest methods in Lambda expression
问题
我有一个 ArrayList
,其中包含多个 String
,并且我正在添加一个方法来对这个 ArrayList
进行排序。
list.sort(Comparator.comparing(x -> x.length()));
当我输入 x
并按下 ctrl
+ space
,Eclipse 并没有提示 String
类的方法,而只显示了 Object
类的方法。
请帮我配置 Eclipse,在这种情况下显示准确的方法建议。
在常规情况下,Eclipse 是准确的。
英文:
I have an ArrayList
of String
s, and am adding a method to sort the ArrayList
list.sort(Comparator.comparing(x -> x.length()));
When I write x and press ctrl
+ space
eclipse does not suggest the methods of the String
class, but only shows methods of the Object
class.
Please help me configure eclipse to show the exact method suggestions in this case.
In regular cases eclipse is exact.
答案1
得分: 1
这是一个双重问题,一个与Eclipse相关,一个与Java语义相关。
Java语义
一个快速的示例:
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
myList.sort(Comparator.comparing(x -> x.|));
}
假设你在|
(光标)位置按下ctrl
+ space
。那么Eclipse必须推断大量信息,以了解x实际上是String
类型的元素。首先,必须知道列表的泛型类型String
(Eclipse可以推断出这一点)。然后,Comparator.comparing
方法需要知道它必须返回一个比较String
的Comparator
实例,Eclipse可以推断出这一点,但这里出现了第一个问题:Comparator
可以是比较不仅仅是String
,还可以是任何其他类型的Object
的Comparator
。如果你想要传递一个比通用的Comparator<String>
更通用的方法给myList.sort
,会怎样呢?更具体地说:List.sort
方法可以接受(在你的情况下)任何Comparator<? super String>
类型的Comparator
。而? super String
已经是Object
或String
之一。因此,在你的示例中,x
的类型可能只是一个对象,Eclipse无法最终决定。但是,你可以以不同的方式编写Lambda表达式,以使其更清晰:
myList.sort(Comparator.comparing((String x) -> x.|));
在这种情况下,自动完成建议可能会更有帮助(取决于Eclipse的版本)。
Eclipse与不完整Lambda表达式的AST问题
不完整的Lambda表达式往往会破坏整个文件的语法,因此Eclipse无法正确确定该位置的语法树。这意味着Eclipse无法推断你正在编写的代码应该是一个Lambda表达式,其中x
是Lambda函数的参数,你想要完成它。如果Eclipse的令牌化器和AST解析器相应地适应了这个问题(这可能已经尝试过了),可以解决这个问题。我无法回答是否可能解决这个问题。我只知道,编写一个"完整"的Lambda,带有一个方法块,然后稍后将其转换为"精简"的Lambda,有助于解决这个问题:
myList.sort(Comparator.comparing((String x) -> { return x.| }));
对于上述情况,如果你像我在示例中所做的那样指定String
作为Comparator
的绝对类型,自动完成应该可以工作。
这样的问题源于如何解释字符以及因此推断程序员可能意图编写什么(自动完成和完成建议的过程)的问题。
在常规代码中,如方法块、for
循环或任何其他结构中,Eclipse非常擅长隔离对命名实体的引用。这就是为什么它在那里工作得很好的原因。语法树通常很容易处理。
然而,在使用Lambda时,Eclipse(以及任何其他IDE)会更加困难。这是因为Lambda通过推断大量的隐式信息来工作,否则需要明确编写(例如,在接口的显式实现中)。
如果一切都失败了,你可以在该位置创建显式接口,然后在完成后将其转换为Lambda。
英文:
This is a two-fold issue, one with eclipse, and one with java semantics.
Java Semantics
A quick example:
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
myList.sort(Comparator.comparing(x -> x.|));
}
Assume you press ctrl
+ space
at the |
(cursor) position. Then eclipse has to infer a lot of information to know, that x is in fact an element of type String
. First, the list's generic type String
must be known (it is, eclipse can deduce this). Then the Comparator.comparing
method needs to know, that it must return an instance of a Comparator which compares String
s, which eclipse could deduce, but here is the first issue: The Comparator could be one that compares not just Strings, but also any other kind of Object
. What if you wanted to pass a method to myList.sort
that is more general than the generic Comparator<String>
? To be more precise: The List.sort
method can take (in your case) any Comparator
of type Comparator<? super String>
. And ? super String
is already either Object
or String
.
So in your example. the type of x
could just be an object, eclipse cannot ultimately decide. However, you can write your lambda expression differently, to make it clear:
myList.sort(Comparator.comparing((String x) -> x.|));
In this case, the completion suggestion could be more helpful (depending on the version of eclipse).
eclipse AST issues with incomplete lambdas
An incomplete lambda expression is more often than not such an upset in the syntax of the entire file, that eclipse cannot determine the syntax tree at that position correctly. That means, that eclipse cannot deduce, that the code you are writing is supposed to be a lambda expression, where x
is the parameter of the lambda function, and you want to complete that. This issue could be addressed, if the tokenizer and AST-parser of eclipse are adapted accordingly (which might have already been tried). Whether this is possible at all, I cannot answer. I only know it helps, to write a "full" lambda, with a method block, and convert that to a "slim" lambda later on:
myList.sort(Comparator.comparing((String x) -> { return x.| }));
For the above case, the completion should work (IF you specify String
as absolute type of the Comparator
, as I have done in the example).
Issues like this stem from the question of how to interpret the characters and therefore deduce, what the programmer might intent to write (the process of auto completion and completion suggestion).
eclipse is very strong in isolating a reference to a named entity, when in regular code, like a method block, a for
loop, or any other construct. That is why it works well there. The syntax tree is usually easy to process then.
However when using lambdas, eclipse (and any other IDE for that matter) have a harder time. This is due to the fact, that lambdas work by inferring a lot of implicit information, which would otherwise need to be written explicitly (for example in an explicit implementation of the interface).
If everything else fails, you can create the explicit interface at that position and then convert to a lambda after completing it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论