【问题标题】:Trying to understand final variables试图理解最终变量
【发布时间】:2015-03-14 05:13:27
【问题描述】:

最终变量。我已经阅读了我在这个网站和其他网站上可以找到的所有内容,并且我几乎理解了它们,但我仍然有点困惑。

所以,我知道我们为什么将变量声明为 final 的官方答案:它锁定变量并防止它被重新初始化。我的问题是:

  1. 如果不能重新初始化,它的值还是可以改变的吧?例如:

    final int a = 1;
    a = a + 1;
    

    这种代码是否仍然有效,或者“final int a”是否会被永久锁定为 1?

  2. 如果上面int a的值声明为final后仍然可以更改,那么final的意义何在?

我想问题 2 是我最大的问题。我一直看到所有这些关于它如何锁定变量的解释,有些人甚至说他们将大部分变量声明为 final,但这样做背后的动机对我来说没有意义。

【问题讨论】:

  • 把上面所有的文字都写出来比简单地尝试更容易吗?
  • 我投票结束这个问题,因为它是一个低质量的问题。
  • @alfasin 这是投反对票的理由,而不是关闭。
  • @JohnKugelman 我认为这是两个都做的好理由:)
  • @alfasin 我认为这是一个很好的编辑理由。要么找到一个骗子,要么避开那些试图有用的人。

标签: java final


【解决方案1】:
final int a = 1; 
a = a + 1;

不,此代码不会通过编译,因为它会尝试将新值分配给最终变量。

但是,如果a 的类型是某个可变类的引用类型,您将能够改变对象的状态。例如:

final StringBuidler a = new StringBuilder (20);
a.append ("foo");

变量的finality 只会阻止您更改其值。如果最终变量引用了一个可以修改其状态的对象,finality 不会阻止您修改该状态。

【讨论】:

    【解决方案2】:

    如果你声明

    final int a = 1;
    

    那么以下将导致编译错误,因为您声明为 final 但您试图重新分配一个变量给它:

    a = a + 1;
    

    但是,如果您有一个名为 MyInt 的对象,如下定义:

    class MyInt{
        int myInt = 5;
    
        public int getInt() {
            return myInt;
        }
    
        public void setInt(int newInt) {
            myInt = newInt;
        }
    }
    

    然后你这样做了:

    final MyInt bestIntEver = new MyInt();
    

    你仍然可以打电话

    bestIntEver.setInt(42);
    

    因为对bestIntEver 的引用没有改变,但是

    bestIntEver = new MyInt();
    

    会导致编译错误,因为您更改了对声明为 final 的变量的引用。

    【讨论】:

      【解决方案3】:

      final 表示a 的值不会改变。但是,根据类型,a 的值实际上可能是一个对象的地址(在问题中它只是一个 int 所以值不是地址,只是一个 1)。锁定地址a 持有不会锁定对象。将对象设计为immutable 将。

      对此最喜欢的比喻是一个公文包,里面有一个 1。一个不可变的设计将锁定公文包,因此人们无法进入并更换 1。final 会将它戴在您的手腕上,这样人们就无法将一个装有其他东西的新公文包塞给您。如果您想确保您的 1 不会发生任何事情,则两者都需要。

      但这仅适用于对象。

      如果您是primitive(如int),则没有公文包。您没有握住它的句柄(地址)。你只是拿着1在你的手中。

      如果您是final 原语,则 1 已融合到您的手上。你不能放手。你不能拿起任何东西。

      对象还是原语,final 的意思是一样的。无论你持有什么,一个地址或一个值,你都会一直持有到死。

      如果上面的 int a 声明为 final 后仍然可以更改,那么 final 的意义何在?

      不能。

      ...他们将大部分变量声明为 final,但这样做的动机对我来说毫无意义。

      在声明 final 时将标识符称为变量实际上只是一个常见的坏习惯。如果它是最终的,则它不是可变的。它没有改变。这是一个常数。

      创建常量有几个动机。语义正确性是其中之一。 是一个常数 (3.14159...),所以去改变它的值是没有意义的。另一个动机是防止导致错误的错误。变量经常被重用,因此被赋予了新的值。常量受到保护,不会发生意外更改。防止不良代码越多越好。

      【讨论】:

        猜你喜欢
        • 2016-08-25
        • 2013-08-02
        • 1970-01-01
        • 1970-01-01
        • 2018-09-15
        • 1970-01-01
        • 1970-01-01
        • 2014-12-07
        • 1970-01-01
        相关资源
        最近更新 更多