java - java转义分析也适用于只有一个元素的数组吗?

标签 java arrays escape-analysis

背景:

当您从长代码段中提取方法时,您经常会遇到原始变量的按值调用问题。您无法更改提取方法中的这些原始参数,以便调用者看到更改。 您可以通过将原始变量设置为只有一个元素的数组来避免这种情况。然后有效地使用引用调用。然而它现在是堆上的一个对象。 Java 的逃逸分析是否足够聪明,能够理解这一点并使用堆栈?

给出以下代码以及无法内联的情况:

public class EscapeAnalysisTest {
    public static void main(String[] args) {
        final Set<Integer> integers = new HashSet<>();
        integers.add(1);
        integers.add(9);
        integers.add(8);
        integers.add(4);
        // and so on ...

        final long[] product = new long[1];
        final long[] sum = new long[1];
        final long[] count = new long[1];
        final int[] max = new int[1];
        final int[] min = new int[1];

        product[0] = 1L;
        max[0] = Integer.MIN_VALUE;
        min[0] = Integer.MAX_VALUE; 

        for (Integer i : integers) {
            calcSomeValues(product, sum, count, max, min, i);
        }

        System.out.println("Product :" + product[0]);   
        System.out.println("Sum :" + sum[0]);   
        System.out.println("Count:" + count[0]);
        System.out.println("Max:" + max[0]);
        System.out.println("Min:" + min[0]);            
    }

    private static void calcSomeValues(final long[] product, final long[] sum, final long[] count, final int[] max,
            final int[] min, Integer i) {
        product[0] *= i;
        sum[0] += i;
        count[0]++;
        max[0] = Math.max(max[0], i);
        min[0] = Math.min(min[0], i);
    }
}

最佳答案

这里有一个更好的方法:

public class Test {
    public static class Summary {
        private long product;
        private long sum;
        private long count;
        private int max;
        private int min;

        private Summary() {
            product = 1;
            sum = 0;
            count = 0;
            max = Integer.MIN_VALUE;
            min = Integer.MAX_VALUE; 
        }

        public long getProduct() { return product; }
        public long getSum() { return sum; }
        public int getCount() { return count; }
        public int getMax() { return max; }
        public int getMin() { return min; }

        public static Summary summarize(Collection<Integer> ints) {
            Summary s = new Summary();

            s.count = ints.size();
            for (Integer i : ints) {
                s.product *= i;
                s.sum += i;

                if (i > s.max) {
                    // You can use Math.max if you want
                    s.max = i;
                }
                if (i < s.min) {
                    // You can use Math.min if you want
                    s.min = i;
                }
            }

            return s;
        }
    }

    public static void main(String[] args) {
        final Set<Integer> integers = new HashSet<>();
        integers.add(1);
        integers.add(9);
        integers.add(8);
        integers.add(4);
        // and so on ...

        Summary s = Summary.summarize(integers);

        System.out.println("Product: " + s.getProduct());
        System.out.println("Sum: " + s.getSum());
        System.out.println("Count: " + s.getCount());
        System.out.println("Max: " + s.getMax());
        System.out.println("Min: " + s.getProduct());
    }
}

以您的方式使用数组很奇怪。不要这样做。这会让其他程序员感到困惑,而且也不是该语言的预期使用方式。它违反了最小惊讶原则。

相反,找到一种方法让系统为您工作,而不进入奇怪的领域。您有多个在逻辑上相互关联的值,并且它们都是同时计算的。当您有多个值一起使用时,是考虑使用类的好时机。通过使用一个类和一个方法来完成所有更新,您的代码将变得清晰且合理。我提供的类实际上最终是不可变的(就外部代码而言),因为计算摘要的逻辑全部位于 summarize 方法内,该方法可以访问私有(private)属性,因此它封装得很好。 (名称可能会更好,但我认为这作为示例就足够了。)如果不希望修改 summarize 中的私有(private)状态,则可以通过给出 Summary 轻松调整。 code> 参数及其实例变量的值,并将这些值作为局部变量计算后简单地传递给构造函数,这会将 Summary 变成一个非常简单的结果对象。

保持所有这些逻辑非常本地化并防止调用者修改结果使得很容易推断正在发生的事情。您的数组长度为 1 的示例代码违反了这两个原则,并使代码更难理解、使用或维护。

或者,如果您可以在计算后立即使用这些值,则可以跳过该类(class)并直接在线计算它们。您可以通过循环来完成此操作,或使用内置功能单独计算它们。

关于java - java转义分析也适用于只有一个元素的数组吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41213952/

相关文章:

javascript - 如何重用对象文字

python - 如何操作 numpy.loadtxt 后的数据?

java - Java中的逃逸分析

java - 使用 SDL 将现有的 Lunar Lander 程序从 C 转换到 Android 手机

java - spring-batch 读取 null int 值

java - jax-ws 服务中的 "Operation Connection.commit is not allowed during a global transaction"

Java JSON Jar NoClassDefFound 由 ClassNotFoundException 引起

javascript - 如何返回对象数组属性的总和而不是它们的 double ?

java - Hotspot 中的逃逸分析在简单情况下有多脆弱,例如 for-each 循环中的迭代器

android - android dalvik vm 是否使用逃逸分析优化?