有什么理由比clone()更喜欢System.arraycopy()吗?

发布于 2024-12-01 08:46:59 字数 285 浏览 0 评论 0原文

在复制整个数组时,我经常看到人们这样写:

int[] dest = new int[orig.length];
System.arraycopy(orig, 0, dest, 0, orig.length);

但在我看来,没有理由更喜欢这个:

int[] dest = orig.clone();

无论如何,它们都是浅拷贝。也许这些人只是没有意识到克隆的存在。那么有什么理由不使用clone呢?

When copying an entire array, I've often seen people write:

int[] dest = new int[orig.length];
System.arraycopy(orig, 0, dest, 0, orig.length);

But it seems to me there is no reason to favor this over:

int[] dest = orig.clone();

They're both shallow copies anyway. Probably these folks just don't realize that clone exists. So is there any reason not to use clone?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

茶底世界 2024-12-08 08:46:59
  • clone() 使用其自己的引用创建第一个数组的不同副本。
  • System.arraycopy() 使用JNI(Java Native Interface)进行复制
    一个数组(或它的一部分),所以它是
    正如您可以确认的那样,速度极快
    此处
  • clone() 创建一个与旧数组具有相同特征的数组,即相同大小、相同类型和相同内容。请参阅此处了解的一些示例>克隆在行动;
  • 手动复制就是手动复制。这个方法没什么好说的,只不过很多人发现它是最表现出色
  • arraynew = arrayold 复制数组;它只是指向 arraynewarrayold 的内存地址,或者换句话说,您只是分配一个引用到旧数组。
  • clone() makes a distinct copy of the first array with its own reference.
  • System.arraycopy() uses JNI (Java Native Interface) to copy
    an array (or parts of it), so it is
    blazingly fast, as you can confirm
    here;
  • clone() creates a new array with the same characteristics as the old array, i.e., same size, same type, and same contents. Refer to here for some examples of clone in action;
  • manual copying is, well, manual copying. There isn't much to say about this method, except that many people have found it to be the most performant.
  • arraynew = arrayold doesn't copy the array; it just points arraynew to the memory address of arrayold or, in other words, you are simply assigning a reference to the old array.
神回复 2024-12-08 08:46:59

不。如果您确实进行微基准测试,那么也许可以,具体取决于您运行的 JVM。但实际上,没有。

No. If you're really microbenchmarking, then maybe, depending on what JVM you're running. But in actuality, no.

友欢 2024-12-08 08:46:59

我在思考同样的疑问时,恰巧看到了这个问题。我觉得 arraycopy() 是预定义数组时使用的方法(即内存已分配)。因此,不会重复与存储器分配相关的开销。

例如,想象一下您定义了一个定期更新的大型数组的情况。然后使用clone()将在每次复制数组时重新创建所需大小的数组。但是,arraycopy() 使用预先分配的内存空间。

因此,与 clone() 相比,arraycopy() 在某些情况下更有效。另一方面,clone() 会产生紧凑的代码。

I happened to look at this question when I was pondering on the same doubt. I feel that the arraycopy() is a method to be used when the array is predefined (i.e. memory is already allocated). Thus, the overhead associated with memory allocation is not repeated.

For example, imagine a case when you have defined a large array which is updated periodically. Then using clone() will recreate a array of required size every time the array is copied. However, arraycopy() uses the pre-allocated memory space.

Thus arraycopy() is more efficient in certain scenarios compared to clone(). On the other hand clone() results in a compact code.

暖树树初阳… 2024-12-08 08:46:59

使用 System.arraycopyArrays.copyOf 而不是 clone() 使您的代码更加明确,因此更易于理解。它说“我正在复制一个数组”,而不是“我正在(神奇地)复制某种对象”。

显式优于隐式。
- Python 之禅

但支持 的主要论点Arrays.copyOf 方法(以及针对 clone())是类型安全,缺乏这一点可能是 clone() 最大的问题 这可能会导致微妙的错误,如果您不小心正在克隆的对象具有您想要的确切数组组件类型。

让我们以 JDK-6260652 错误为例。罪魁祸首是在Arrays.ArrayList中使用clone()来实现Collection.toArray()(它被声明为返回Object [])。这个特定的 ArrayListjava.util.Arrays 中的一个私有类,由 Arrays.asList(T... a) 使用 实例化a 作为其后备数组,而不关心 a 的实际类型,它可能是 String[]Integer[] > (或者其他实际上不是的对象[])。其 toArray() 方法返回 a.clone() 的问题在于,程序员最终可能会使用 Arrays.ArrayList.toArray() > 在某些时候做这样的事情:

List<String> lst = Arrays.asList("a", "b", "c");
// ... many lines of code later ...
Object[] arr = lst.toArray();
// ... at this point don't care about the original type of elements in lst ...
arr[0] = 123;  // ArrayStoreException - WTF?!
// arr is an Object[] so should be able to store Integer values!

这种错误可能会被忽视很多年,因为上面说明的使用模式并不常见。只要考虑一下集合框架自 JDK 1.2(1998 年)以来就已经存在,但这个特定问题直到 2005 年才被报告(10 年后有人发现了一个JDK 不同部分中的类似问题)。 JDK-6260652 补丁(在 Java 9 中发布)很简单将 a.clone() 替换为 Arrays.copyOf(a, a.length,对象[].class)


总而言之,我赞成使用数组复制方法而不是 clone() 的论点是:

  • System.arraycopy
    1. 更明确
  • Arrays.copyOf
    1. 更明确
    2. 并提供类型安全

Using System.arraycopy or Arrays.copyOf instead of clone() makes your code more explicit and therefore easier to understand. It says "I'm copying an array" as opposed to "I'm (magically) copying some kind of object".

Explicit is better than implicit.
- The Zen of Python

But the main argument in favor of the Arrays.copyOf methods (and against clone()) is type-safety, the lack of which is probably the biggest gotcha of clone() that could lead to subtle bugs if you're not careful that the object you're cloning has the exact array component type that you want.

Let's look at the JDK-6260652 bug for example. The culprit was clone() being used in Arrays.ArrayList to implement Collection.toArray() (which is declared to return Object[]). This particular ArrayList is a private class in java.util.Arrays instantiated by Arrays.asList(T... a) using a as its backing array without caring about the actual type of a, which might have been a String[] or Integer[] (or whatever else that's not actually Object[]). The problem with its toArray() method returning a.clone() here is that a programmer might end up using Arrays.ArrayList.toArray() at some point to do something like this:

List<String> lst = Arrays.asList("a", "b", "c");
// ... many lines of code later ...
Object[] arr = lst.toArray();
// ... at this point don't care about the original type of elements in lst ...
arr[0] = 123;  // ArrayStoreException - WTF?!
// arr is an Object[] so should be able to store Integer values!

This kind of bug can go unnoticed for years because the usage pattern illustrated above is not common. Just consider that the Collections framework has been around since JDK 1.2 (1998) but this particular issue wasn't reported until 2005 (and 10 years later someone discovered a similar issue in a different part of the JDK). The patch for JDK-6260652 (released in Java 9) simply replaces a.clone() with Arrays.copyOf(a, a.length, Object[].class).


To summarize, my arguments in favor of using the array copy methods instead of clone() are:

  • System.arraycopy:
    1. more explicit
  • Arrays.copyOf:
    1. more explicit
    2. and provides type-safety
浪漫之都 2024-12-08 08:46:59

这里只是猜测,但使用 System.arraycopy 可能是有充分理由的,因为不同的 JVM 可以通过利用底层系统的本机功能来提高性能的方式来实现它们。

例如,JVM 实现可以使用像 memcpy 这样的本机库调用,它可能会利用一些内存控制器技巧以某种令人难以置信的快速和巧妙的方式执行操作。但是,由于其虚拟性质,Object.clone 实现可能不适合进行此类优化。

Just guessing here, but there might be a good reason to use System.arraycopy because different JVM's could conceivably implement them in a way that takes advantage of native abilities of the underlying system for a performance boost.

For example, a JVM implementation could use a native library call like memcpy which could potentially take advantage of some memory controller tricks to perform the action in some incredibly fast and clever way. However, the Object.clone implementation might not be a good candidate for such optimization due to its virtual nature.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文