java 中的 String[]::new 和 new String[] 有区别吗?
Is there a difference between String[]::new and new String[] in java?
我正在使用
将 ArrayList 转换为数组
ArrayList<String> var1 = new ArrayList<>();
for(condition){
// Add items to var1
}
return var1.toArray(new String[]{})
我的 IDE 建议我将最后一行更改为
return var1.toArray(String[]::new)
这只是更好的约定,还是对编译时或内存使用也有一些好处。
"String[]::new" 是一个方法参考。它与“new String[]”基本相同。有关详细信息,请参阅 Method References。
String[]::new
是一个函数。它不创建新的字符串数组,它定义了一个创建新字符串数组的函数。这就像蛋糕和制作蛋糕的食谱之间的区别。一种由面粉和糖衣等组成。另一个只是文字和纸张。完全不同但相关的东西,因为食谱可以让你做蛋糕(甚至可以做任何数量的蛋糕!)
String[]::new
是 shorthand* 对于:
public String[] makeNewStringArray(int size) {
return new String[size];
}
仅仅编写根本不构成任何字符串数组; 调用该函数每次调用时都会生成一个字符串数组。
示例:
IntFunction<String[]> stringArrayMaker = String[]::new;
String[] size10 = stringArrayMaker.apply(10);
好的,那么推荐呢?
你写的有点不规范; new String[0]
更标准。那么让我们比较一下 new String[0]
和 String[]::new
.
这个参数唯一的意义就是让arraylist知道你想要什么类型。你会认为 arraylist 已经知道(毕竟它是一个 ArrayList<String>
!)但是由于泛型擦除(一个相当复杂的主题),toArray
的代码无法知道你的内容想要,所以,你必须指定。
new String[0]
最终生成一个长度为 0 的字符串数组,然后立即将其丢弃。这感觉很浪费,但垃圾收集就是这样,'quick garbage'(对象创建和丢弃非常快并且从不与其他线程共享)几乎完全免费。此方法 (toArray(T[])
) 的工作原理如下:如果传入数组与需要的一样大或大于需要的数组,则将其填充并返回。如果太小,则创建一个具有相同组件类型且大小合适的新数组,填充一个,然后返回一个。
因此,您会认为 var1.toArray(new String[var1.size()])
是最有效的。但是 JMH 告诉我完全没有区别。这表明 java 在处理短暂垃圾方面是多么高效(当我说 'short lived garbage is free' 时,我是认真的。几乎不可能见证它的成本)。
函数式方法(您传递 String[]::new
的地方)意味着此函数将负责创建数组,而 toArray
本身仅依赖于它得到的内容。这..也可以正常工作。它最终在你的 class 文件中的某个地方创建了一个方法。
所以,真的没关系。我发现 IDE 在这里过于说教了。 String[]::new
提出了一种新方法,仅 class space 中的开销可能意味着它最终效率较低,即使垃圾的创建是更容易理解的低效率。
但是,我们真的很挑剔。字面意思是纳秒 - 你永远不会注意到。
做任何你认为最易读的事情(虽然我会避开 new String[]{}
- 它本身没有错,但它不是很常见并且它没有 new String[0]
的好处 - 可能如果无关紧要,我们会做社区做的事。
*) 这有点过于简单了,但并没有太多。
我正在使用
将 ArrayList 转换为数组ArrayList<String> var1 = new ArrayList<>();
for(condition){
// Add items to var1
}
return var1.toArray(new String[]{})
我的 IDE 建议我将最后一行更改为
return var1.toArray(String[]::new)
这只是更好的约定,还是对编译时或内存使用也有一些好处。
"String[]::new" 是一个方法参考。它与“new String[]”基本相同。有关详细信息,请参阅 Method References。
String[]::new
是一个函数。它不创建新的字符串数组,它定义了一个创建新字符串数组的函数。这就像蛋糕和制作蛋糕的食谱之间的区别。一种由面粉和糖衣等组成。另一个只是文字和纸张。完全不同但相关的东西,因为食谱可以让你做蛋糕(甚至可以做任何数量的蛋糕!)
String[]::new
是 shorthand* 对于:
public String[] makeNewStringArray(int size) {
return new String[size];
}
仅仅编写根本不构成任何字符串数组; 调用该函数每次调用时都会生成一个字符串数组。
示例:
IntFunction<String[]> stringArrayMaker = String[]::new;
String[] size10 = stringArrayMaker.apply(10);
好的,那么推荐呢?
你写的有点不规范; new String[0]
更标准。那么让我们比较一下 new String[0]
和 String[]::new
.
这个参数唯一的意义就是让arraylist知道你想要什么类型。你会认为 arraylist 已经知道(毕竟它是一个 ArrayList<String>
!)但是由于泛型擦除(一个相当复杂的主题),toArray
的代码无法知道你的内容想要,所以,你必须指定。
new String[0]
最终生成一个长度为 0 的字符串数组,然后立即将其丢弃。这感觉很浪费,但垃圾收集就是这样,'quick garbage'(对象创建和丢弃非常快并且从不与其他线程共享)几乎完全免费。此方法 (toArray(T[])
) 的工作原理如下:如果传入数组与需要的一样大或大于需要的数组,则将其填充并返回。如果太小,则创建一个具有相同组件类型且大小合适的新数组,填充一个,然后返回一个。
因此,您会认为 var1.toArray(new String[var1.size()])
是最有效的。但是 JMH 告诉我完全没有区别。这表明 java 在处理短暂垃圾方面是多么高效(当我说 'short lived garbage is free' 时,我是认真的。几乎不可能见证它的成本)。
函数式方法(您传递 String[]::new
的地方)意味着此函数将负责创建数组,而 toArray
本身仅依赖于它得到的内容。这..也可以正常工作。它最终在你的 class 文件中的某个地方创建了一个方法。
所以,真的没关系。我发现 IDE 在这里过于说教了。 String[]::new
提出了一种新方法,仅 class space 中的开销可能意味着它最终效率较低,即使垃圾的创建是更容易理解的低效率。
但是,我们真的很挑剔。字面意思是纳秒 - 你永远不会注意到。
做任何你认为最易读的事情(虽然我会避开 new String[]{}
- 它本身没有错,但它不是很常见并且它没有 new String[0]
的好处 - 可能如果无关紧要,我们会做社区做的事。
*) 这有点过于简单了,但并没有太多。