当我看Comparable时,我正在使用反编译器工具,它只有一种抽象方法,没有FunctionalInterface
批注
public interface Comparable<T> {
int compareTo(T var1);
}
与Comparator相似,但是比较器具有FunctionalInterface
批注
@FunctionalInterface
public interface Comparator<T> {
int compare(T var1, T var2);
...
}
答案 0 :(得分:4)
是FunctionalInterface
吗?否。Comparable
没有该注释。
是功能界面吗?是。根据{{3}}中的定义:
功能接口是仅具有一种抽象方法的接口(除对象的方法之外)
将其视为FunctionalInterface
吗? language spec:
但是,无论接口声明中是否存在FunctionalInterface注释,编译器都会将满足功能接口定义的任何接口视为功能接口。
在逻辑上是功能上的接口吗?否:Comparable
不代表函数。它更像是对象的特征。 “可以比较这件事”,而不是“可以比较这件事”。
作为功能接口有实际用途吗?我会声称没有明显的用处,因为事实是,您很少(如果有的话)看到Comparable<Something>
被用作变量,参数或字段的类型;仅在extends
或implements
子句中以及类型变量的范围内。
答案 1 :(得分:2)
我在Java Book Chapter 3 [144 page]
中找到了答案Is Comparable a Functional Interface?
我们说比较器是一个功能接口,因为它具有一个 单一抽象方法。可比也是功能接口 因为它也只有一个抽象方法。但是,使用lambda 对于可比来说将是愚蠢的。可比的重点是实现 将其放入要比较的对象中。
答案 2 :(得分:1)
可比对象是可以与其他对象进行比较的对象; compareTo()
应该比较this
的值。
将其实现为lambda毫无意义。
答案 3 :(得分:1)
从字面上看,private static final int NUM_ROW = 2;
private static final int NUM_COL = 3;
private TableLayout table;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
table = findViewById(R.id.tableForButtons);
table.post(new Runnable() {
@Override
public void run() {
populateTable();
}
});
}
private void populateTable() {
int tableLayoutWidth = table.getMeasuredWidth();
int cellWidth = tableLayoutWidth / NUM_COL;
for (int row = 0; row < NUM_ROW; row++) {
TableRow tableRow = new TableRow(this);
tableRow.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
cellWidth
));
for (int col = 0; col < NUM_COL; col++) {
ImageButton button = new ImageButton(this);
button.setLayoutParams(new TableRow.LayoutParams(
cellWidth,
cellWidth
));
button.setBackgroundResource(R.mipmap.single_case);
button.setPadding(0, 0, 0, 0);
button.setScaleType(ImageView.ScaleType.FIT_XY);
tableRow.addView(button);
}
table.addView(tableRow);
}
}
是一个功能接口,因为它声明了一个并且只有一个抽象方法。
但是用Comparable
对其进行注释将意味着它已被证明可以用作功能接口,而事实并非如此。
JLS指出:
9.6.4.9。 @FunctionalInterface
由于某些接口偶然起作用,所以不是 功能接口的所有声明都是必需或可取的 用@FunctionalInterface注释。
当然,您可以通过依赖外部@FunctionalInterface
实例而不是像我们在Foo
实现中通常使用的this
那样在lambda中使用它:
compareTo()
但这是不希望的,因为滥用了Foo one = new Foo(...);
Comparable<Foo> comparableForOne = other -> one.getX().compareTo(other.getX()));
Foo anotherFoo = new Foo(...);
int result = comparableForOne.compareTo(anotherFoo);
接口,该接口被设计用于类的任何实例而不是特定实例。
答案 4 :(得分:0)
要完全回答这个问题,我们应该看一下Java的内幕,看看什么是lambda(至少到目前为止):用一种方法实现接口的语法糖。让我们以Comparator<T>
(可以很好地由lambda实现)的示例进行说明,然后转到Comparable<T>
(可以由lambda实现,但没有意义)。 / p>
假设有人给了我们(编译的)
public class Car {
private final int horsePowers;
private final int topSpeed;
private final int numDoors;
private final String color;
// Setters omitted for brevity
}
我们无法修改此类,但是我们想按颜色对汽车进行分类。传统方法是调用Collections.sort(List<T> list, Comparator<? super T> c)
。由于我们作为开发人员经常很懒惰(否则,我们将不使用Copy-Paste-Programming),因此我们经常在anonymous class中实现这种功能:
...
List<Car> cars = ...;
Collections.sort(cars, new Comparator<Car> {
@Override
public int compare(final Car lhs, final Car rhs) {
return lhs.getColor.compareTo(rhs.getColor());
}
});
这很丑。首先,它漫长而又漫长,阅读起来很尴尬。但是幸运的是,Java之神用lambda expressions祝福了我们,所以我们写了 1 :
...
List<Car> cars = ...;
Collections.sort(cars, (lhs, rhs) -> lhs.getColor().compareTo(rhs.getColor()));
这看起来更好,不是吗?它简短,全面且易于阅读(至少,如果您已经看过一百遍了)。但实际上,它仍然是一个古老的匿名类。没有其他的。某些限制确实适用于lambda。首先,lambda没有任何状态(实例变量)。其次,从lambda外部使用的所有引用(局部变量或周围方法/类的属性)必须为final
或有效地为final
(不允许lambda更改值)。这将在下面变得更加重要。
现在,我们来看看Comparable<T>
。 Comparator<T>
定义了如何将两个T
相互比较的同时,Comparable<T>
说“此类与T
(通常是本身)具有可比性,这是如何将其与T
进行比较”。让我们想象一下,我们上面的Car
类实际上是这样实现Comparable<Car>
的:
public class Car implements Comparable<Car> {
...
public int CompareTo(final Car that) {
int diff = this.getHorsePowers() - that.getHorsePowers();
if (diff == 0) {
diff = this.getTopSpeed() - that.getTopSpeed();
}
if (diff == 0) {
diff = this.getNumDoors() - that.getNumDoors();
}
if (diff == 0) {
diff = this.getColor().compareTo(that.getColor());
}
return diff;
}
}
实质上,它首先将Car
与它们的horsePowers
比较。如果它们相等,则通过它们的topSpeed
比较它们。如果它们再次相等,则将其与门数进行比较,依此类推。
现在让我们来回顾一下:Lambda是仅使用一种方法即可实现接口的语法糖,Comparable<T>
描述了如何将类与T
进行比较。现在回想一下我之前对Lambda和州所说的话:Lambda没有任何州。因此,在大多数情况下将它们与任何事物进行比较都是毫无意义的(没有状态-没有可比较的事物;我说“大部分时间”,因为在某些情况下这种事情可能是可行的)。因此,几乎没有理由用lambda实现Comparable<T>
。
总而言之,我们可以说,虽然可以用lambda实现Comparable<T>
,但这很少有用。
1 我知道比较lambda通常写为Comparator.comparing(Car::getColor)
,但这不是我要强调的重点。