Java 性能差异:在if-else块或额外的“;否则;?
我很好奇以下哪项更有效:使用默认值初始化变量并仅在if-else块中需要时重写它,或者在没有值的情况下初始化变量并在if-else块中设置值 以下是前者和后者的一个例子: 前任:Java 性能差异:在if-else块或额外的“;否则;?,java,performance,Java,Performance,我很好奇以下哪项更有效:使用默认值初始化变量并仅在if-else块中需要时重写它,或者在没有值的情况下初始化变量并在if-else块中设置值 以下是前者和后者的一个例子: 前任: String weightStatus = "Underweight"; if (bMI > 29.9) { weightStatus = "Obese"; } else if (bMI >= 25.0) {
String weightStatus = "Underweight";
if (bMI > 29.9)
{
weightStatus = "Obese";
}
else if (bMI >= 25.0)
{
weightStatus = "Overweight";
}
else if (bMI >= 18.5)
{
weightStatus = "Healthy Weight";
}
后者:
String weightStatus;
if (bMI > 29.9)
{
weightStatus = "Obese";
}
else if (bMI >= 25.0)
{
weightStatus = "Overweight";
}
else if (bMI >= 18.5)
{
weightStatus = "Healthy Weight";
}
else
{
weightStatus = "Underweight";
}
差异可能很小,但我不禁想知道,根据变量赋值的工作原理,哪一个在技术上更快。如您所知,前一种情况下,字节码将始终设置变量,然后根据
if/then
,它可能会再次重置变量
但这也取决于在运行时传递哪些值,如果它们大部分不在然后
分支中,那么我想这不会有太大的区别,但是如果它们经常进入然后
分支,那么大多数情况下会执行双重设置
您可以使用以下方法进行测试:
public class MyTest {
private static double START = 0;
private static double END = 100;
private static double INCREMENT = 0.0001;
@Test
public void testFirst() throws Exception {
long time = System.nanoTime();
for (double bMI = START; bMI < END; bMI += INCREMENT) {
first(bMI);
}
System.out.println("First " + (System.nanoTime() - time));
}
@Test
public void testSecond() throws Exception {
long time = System.nanoTime();
for (double bMI = START; bMI < END; bMI += INCREMENT) {
second(bMI);
}
System.out.println("Second " + (System.nanoTime() - time));
}
private String first(double bMI) {
String weightStatus = "Underweight";
if (bMI > 29.9) {
weightStatus = "Obese";
} else if (bMI >= 25.0) {
weightStatus = "Overweight";
} else if (bMI >= 18.5) {
weightStatus = "Healthy Weight";
}
return weightStatus;
}
private String second(double bMI) {
String weightStatus;
if (bMI > 29.9) {
weightStatus = "Obese";
} else if (bMI >= 25.0) {
weightStatus = "Overweight";
} else if (bMI >= 18.5) {
weightStatus = "Healthy Weight";
} else {
weightStatus = "Underweight";
}
return weightStatus;
}
}
公共类MyTest{
专用静态双启动=0;
专用静态双端=100;
专用静态双增量=0.0001;
@试验
public void testFirst()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第一,体重指数;
}
System.out.println(“First”+(System.nanoTime()-time));
}
@试验
public void testSecond()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第二(bMI);
}
System.out.println(“第二个”+(System.nanoTime()-time));
}
私有字符串优先(双bMI){
字符串weightStatus=“重量不足”;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}
返回状态;
}
私有字符串秒(双bMI){
字符串权重状态;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}否则{
weightStatus=“体重不足”;
}
返回状态;
}
}
如您所知,在前一种情况下,字节码将始终设置变量,然后根据if/then
,它可能会再次重置变量
但这也取决于在运行时传递哪些值,如果它们大部分不在然后
分支中,那么我想这不会有太大的区别,但是如果它们经常进入然后
分支,那么大多数情况下会执行双重设置
您可以使用以下方法进行测试:
public class MyTest {
private static double START = 0;
private static double END = 100;
private static double INCREMENT = 0.0001;
@Test
public void testFirst() throws Exception {
long time = System.nanoTime();
for (double bMI = START; bMI < END; bMI += INCREMENT) {
first(bMI);
}
System.out.println("First " + (System.nanoTime() - time));
}
@Test
public void testSecond() throws Exception {
long time = System.nanoTime();
for (double bMI = START; bMI < END; bMI += INCREMENT) {
second(bMI);
}
System.out.println("Second " + (System.nanoTime() - time));
}
private String first(double bMI) {
String weightStatus = "Underweight";
if (bMI > 29.9) {
weightStatus = "Obese";
} else if (bMI >= 25.0) {
weightStatus = "Overweight";
} else if (bMI >= 18.5) {
weightStatus = "Healthy Weight";
}
return weightStatus;
}
private String second(double bMI) {
String weightStatus;
if (bMI > 29.9) {
weightStatus = "Obese";
} else if (bMI >= 25.0) {
weightStatus = "Overweight";
} else if (bMI >= 18.5) {
weightStatus = "Healthy Weight";
} else {
weightStatus = "Underweight";
}
return weightStatus;
}
}
公共类MyTest{
专用静态双启动=0;
专用静态双端=100;
专用静态双增量=0.0001;
@试验
public void testFirst()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第一,体重指数;
}
System.out.println(“First”+(System.nanoTime()-time));
}
@试验
public void testSecond()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第二(bMI);
}
System.out.println(“第二个”+(System.nanoTime()-time));
}
私有字符串优先(双bMI){
字符串weightStatus=“重量不足”;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}
返回状态;
}
私有字符串秒(双bMI){
字符串权重状态;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}否则{
weightStatus=“体重不足”;
}
返回状态;
}
}
我当然会选择带有默认.Phix的switch语句,但我不是在问switch语句。谢谢你,第一个还有一个任务。当你考虑到优化、预测分支、CPU/内存速度等因素时,你肯定不会注意到其中的差异。无论哪个用户使代码更清晰。@yshavit第一个用户少了一次赋值,多了一次初始化。@Phix你不能用开关来实现不等式。显然,我会选择带有默认值.Phix的开关语句,但我不是问开关语句。谢谢你,第一个还有一个任务。当你考虑到优化、预测分支、CPU/内存速度等因素时,你肯定不会注意到其中的差异。用户(以使代码更清晰的为准)。@yshavit第一个减少了一个赋值,又增加了一个初始化。@Phix您不能使用开关执行不等式。我最初会检查IDE,然后在运行时(服务器)环境中使用实际期望值运行它来测试结果,如果您有输入数据。选择作为答案是因为答案清晰、深入,并提供代码示例。谢谢,这太棒了!这不是一个很好的基准;例如,你没有任何热身。在从性能测试中得出任何结论之前,您应该先阅读如何用Java编写微基准。您可能也想看看jmh。我最初会使用IDE进行检查,但如果您有输入数据,则会在运行时(服务器)环境中使用实际期望值运行它来测试结果。选择作为答案是因为答案清晰、深入,