简体   繁体   English

在不破坏二进制向后兼容性的情况下,Java 中的扩展方法可能吗?

[英]Extension Methods in Java possible without breaking Binary Backwards Compatibility?

Several languages have externsion methods like C#, Ruby, Smalltalk, Kotlin, Scala.几种语言都有扩展方法,如 C#、Ruby、Smalltalk、Kotlin、Scala。 The idea is that you can add methods to a class that is closed for extension like system classes such as String, Integer or final classes such as ArrayList.这个想法是你可以向一个类添加方法,该类对于扩展是封闭的,比如系统类,如 String、Integer 或最终类,如 ArrayList。

So instead of having all those Util-Classes you just add the respective extension method.因此,您只需添加相应的扩展方法,而不是拥有所有这些 Util-Classes。 So instead of StringUtils.split(...) you would call "foo".split().所以,而不是 StringUtils.split(...) 你会调用 "foo".split()。

Java does not have extension methods. Java 没有扩展方法。 My question is whether extension methods could be added to Java without breaking binary backwards compatibility as for exanple with Java8 lambdas or other features in the past.我的问题是是否可以将扩展方法添加到 Java 中,而不会破坏二进制向后兼容性,就像过去使用 Java8 lambda 或其他功能的示例一样。 The question is only about whether it can be done without braking backwards compatibility or not.问题仅在于是否可以在不降低向后兼容性的情况下完成。

In C# and Kotlin extension methods are implemented as static methods.在 C# 和 Kotlin 中,扩展方法被实现为静态方法。 So, in the same way for Java there would be some additional syntax for StringUtils.split(...), which would tell the Java compiler that "foo".split() at compile time has to be replaced with StringUtils.split(...).因此,与 Java 相同,StringUtils.split(...) 会有一些额外的语法,它会告诉 Java 编译器编译时的 "foo".split() 必须替换为 StringUtils.split( ……)。 At least, I think this is what happens in C# and Kotlin.至少,我认为这是 C# 和 Kotlin 中发生的事情。

Again, my question is only about whether extension methods in Java can be done without braking backwards compatibility or not.同样,我的问题只是关于 Java 中的扩展方法是否可以在不降低向后兼容性的情况下完成。 Just that.只是。

I don't know the ultimate answer to this but here's how Kotlin does it, which would probably be possible for Java as well.我不知道这个问题的最终答案,但这里是 Kotlin 是如何做到的,这可能也适用于 Java。

Let's consider a simple extension on String :让我们考虑一个简单的String扩展:

fun String.lengthSquare() = length * length

The Kotlin compiler generates bytecode similar to the following (shown as corresponding Java code): Kotlin 编译器生成类似于以下的字节码(显示为对应的 Java 代码):

public static final int lengthSquare(@NotNull String $this$lengthSquare) {
   Intrinsics.checkParameterIsNotNull($this$lengthSquare, "$this$lengthSquare");
   return $this$lengthSquare.length() * $this$lengthSquare.length();
}

So basically it just creates a static method that takes in a String , just as we know it from utility methods.所以基本上它只是创建一个接受String的静态方法,就像我们从实用程序方法中知道的那样。 I believe the Java compiler could do something similar.我相信 Java 编译器可以做类似的事情。 All call sites of those extension functions, of course, will use that static method in the JVM byte code.当然,这些扩展函数的所有调用点都将在 JVM 字节码中使用该静态方法。

More Information on Kotlin Extensions关于 Kotlin 扩展的更多信息

Extensions do not actually modify classes they extend.扩展实际上并不修改它们扩展的类。 By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.通过定义扩展,您不会将新成员插入到类中,而只是使新函数可以使用这种类型的变量上的点符号调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM