我需要将Java 8代码转换为JavaScript(单向,一次性)。为了加快速度,我希望尽可能自动化,并在之后使用测试套件来解决所有剩余的问题。
我想知道Java 8 lambda和JavaScript(函数)之间的区别是什么?
是否存在重要的不兼容性?
我需要将Java 8代码转换为JavaScript(单向,一次性)。为了加快速度,我希望尽可能自动化,并在之后使用测试套件来解决所有剩余的问题。
我想知道Java 8 lambda和JavaScript(函数)之间的区别是什么?
是否存在重要的不兼容性?
比较 Java lambdas 和 JS 函数时需要注意两者对作用域的处理方式。
在 Java 中,lambdas 只能访问 effectively final 变量,并且只捕获那些明确需要的变量。在 JS 中,函数可以访问所有父闭包中的变量,因此捕获了所有内容。
由此产生的一个结果是可能会发生内存泄漏,除非您知道自己在做什么。例如:
IntSupplier getSupplier(MyMemoryHeavyClass heavy) {
int x = heavy.hashCode();
return () -> x;
}
这种方法将返回一个仅包含 int 的 lambda。这里没有问题。然而,直接翻译为 JavaScript 的话......
function getSupplier(heavy) {
var x = heavy.hashCode();
return function() { return x; };
}
乍一看可能不明显,但这有一个重大问题。函数表达式将捕获范围内的所有内容,包括heavy
参数(即使它在返回的函数中没有被引用)。因此,它会阻止需要占用大量内存的heavy
被垃圾回收,从而会在返回的函数存在期间一直保留在内存中。
编辑
正如评论中指出的那样,这些信息可能有点过时,因为现代引擎似乎更加智能化。例如,V8将仅捕获其认为必要的内容。但是,由于在同一范围内创建的所有函数似乎共享相同的闭包,因此仍然可能会被欺骗。
例如,添加行(function y() { return heavy; });
,否则几乎不起作用,将强制heavy
进入与return x;
函数使用相同的闭包,从而创建泄漏。
虽然在这个特定示例中有些牵强,但是在简单地翻译包含多个Lambda的Java方法时,类似的问题并不难发生。
JavaScript函数/箭头函数表达式和Java 8匿名类/lambda之间的一个主要区别是,后者(Java)不能重新分配捕获的变量和参数,因为它们在Java 8中被认为是有效地最终的(在先前的Java版本中,所有捕获的变量和参数必须声明为final
)。有一些解决此限制的方法:
Mutable<T>
,并使用 set
和 get
方法作为 Mutable<?>
实例,因为可能会将其作为捕获变量或参数传递。AtomicReference<T>
或一些类似的 Atomic***
方法(如果我没记错的话,这种方法在 GWT 中不能使用)。Object[] o = {null}
。尽管这种解决方法似乎更低级,并且需要通过索引进行仔细的重新分配/引用,但它可能具有以下优点:1)它可以完美处理基本类型(比如说,new int[1]
明显比 Mutable<Integer>
更好)。2)一个数组可以保存多个值(比如说,你的 lambda 表达式可能想要修改捕获的 r
、g
和 b
,并且三元组可以被包装在 float[] rgb = new float[3]
中,其中 rgb[0]
可以是 r
)。如果我没记错的话,这种解决方法是 IntelliJ IDEA 中的建议意图。final float rgb[] = new float[3];
final Runnable whiteOut = () -> {
rgb[0] = 255;
rgb[1] = 255;
rgb[2] = 255;
};
final Runnable blackOut = new Runnable() {
@Override
public void run() {
rgb[0] = 255;
rgb[1] = 255;
rgb[2] = 255;
}
};
whiteOut.run();
blackOut.run();
如果您可以接受分开的r
、g
和b
,则可以轻松将其转换为更清晰的JavaScript代码:
var r, g, b;
var whiteOut = () => { r = 255; g = 255; b = 255; }
var blackOut = function() { r = 0; g = 0; b = 0; }
whiteOut();
blackOut()
heavy
的活动状态。尽管即使他们将其优化掉,那也是实现特定的行为,而不是规范所保证的。 - the8472