将java.lang.Number实例传递给方法

时间:2017-02-18 13:38:15

标签: java

我在考虑在传递java.lang.Number(例如java.lang.Long)的实例时是否有意义在方法签名中使用final关键字?

我认为它没有任何意义,因为java传递对象崇拜值。这意味着java将原始引用的副本传递给方法。此数字上的值的任何更改在方法外部都是不可见的。因此,方法是否改变方法内的值无关紧要。

当然,当我们将pojo传递给方法时,使用final关键字是有意义的,但这是一个不同的场景。

java.lang.Number演示

public class Demo {

    public static void main(String[] args) {
        Long longValue = 1L;
        System.out.println("Long before: " + longValue);
        System.out.println(trickyMethod(longValue));
        System.out.println("Long after: " + longValue);

        BigInteger bigIntegerValue = BigInteger.ONE;
        System.out.println("BigInteger before: "+ bigIntegerValue);
        System.out.println(trickyMethod(bigIntegerValue));
        System.out.println("BigInteger after: " + bigIntegerValue);
    }

    private static String trickyMethod(Long value) {
        value = 10L;
        System.out.println("  trickyMethod: " + value);

        if (value.equals(10L))
            return "  equal";
        else
            return "  different";
    }

    private static String trickyMethod(BigInteger value) {
        value = BigInteger.TEN;
        System.out.println("  trickyMethod: " + value);

        if (value.equals(BigInteger.TEN))
            return "  equal";
        else
            return "  different";
    }
}

输出

Long before: 1
  trickyMethod: 10
  equal
Long after: 1

BigInteger before: 1
  trickyMethod: 10
  equal
BigInteger after: 1

POJO演示

public class Demo {

    static class Container {
        private Long l;

        public Container(Long l) {
            this.l = l;
        }

        @Override
        public String toString() {
            return String.valueOf(l);
        }

        @Override
        public boolean equals(Object obj) {
            Container c = (Container) obj;
            return l.equals(c.l);
        }
    }

    public static void main(String[] args) {
        Container container = new Container(1L);
        System.out.println("Container before: "+ container);
        System.out.println(trickyMethod(container));
        System.out.println("Container after: " + container);
    }

    private static String trickyMethod(final Container container) {
        container.l = 10L;
        System.out.println("  trickyMethod: " + container);

        if (container.equals(new Container(10L)))
            return "  equal";
        else
            return "  different";
    }
}

输出

Container before: 1
  trickyMethod: 10
  equal
Container after: 10

为什么开发人员在String method(final Long value)的情况下使用方法签名中的最终关键字,如Long

3 个答案:

答案 0 :(得分:4)

参数是否不可变并不重要。最终的可变参数可以在内部修改,您只能将任何内容重新赋值给参数变量。

Java中更无用的东西之一,如果参数是隐式最终的,那将是很好的,因为如果您重新分配参数,它就会变成代码味道。大多数代码分析器都将其报告为错误/警告/等。

基本的经验法则是,除非在语法上需要制作参数final(在极少数情况下),不要在参数中加入最终结果,因为它只会在代码中创建无用的混乱。但是从不重新分配参数,因为它可能容易出错,并且假装所有参数都是最终的。

答案 1 :(得分:3)

开发人员使用以下内容的原因只是为了防止重新分配变量。

例如

void method(final long value){
  long number = 90;
  value = number; // COMPILER ERROR
}

所以,我想如果您不想在以后重新分配它时意外重新分配它会导致情况不好,那么您可以将其声明为最终。

答案 2 :(得分:-1)

所有java.lang包裹包装类都是不可变的。这包括String,Long,Double等。因此,如果我们将它们标记为final,那么你是正确的。但请记住,在您的示例中,您将重新分配value引用。如果说StringBuilder,那将是新的对象引用。

但你是对的,在不可变对象的情况下无关紧要。