当一个人应该使用的最终方法参数和局部变量?当一个人应该使用的最终方法参数和局部变量?(When sh

2019-05-06 11:27发布

我发现一对夫妇引用(的例如使用建议) final尽可能地和我不知道那是多么的重要。 这主要是在方法参数和局部变量,而不是最后的方法或类的上下文。 对于常量,它使明显的感觉。

一方面,编译器可以进行一些优化和它使程序员的意图更清晰。 在另一方面,它增加了冗长和优化可能是微不足道的。

它说的是,我应该作出努力,还记得吗?

Answer 1:

迷恋:

  • 决赛场 - 打标领域的最终迫使他们通过建筑的结束设定,使得这一领域的基准不变。 这允许领域的安全发布,可避免需要同步上后读取。 (请注意,对象引用,只有字段引用是不变的 - 东西,对象引用指向仍然可以改变和影响不变性。)
  • 最终静态字段 - 虽然我现在用枚举了许多我曾经使用静态final字段的情况。

考虑但明智地使用:

  • final类 - 框架/ API的设计是,我认为它的唯一案例。
  • 最后的方法 - 基本上相同的final类。 如果你使用像疯了似的标记的东西最终模板方法模式,你可能依靠继承太多,没有足够的授权。

忽略除非感觉肛门:

  • 方法参数和局部变量 - 我很少这样做,主要是因为我懒,我觉得它杂波的代码。 我会充分承认标记参数和局部变量,我不是要修改为“点对点”。 我希望这是默认的。 但它不是,我觉得代码更难与各地决赛理解。 如果我在别人的代码是,我不是要拉出来,但如果我在编写新的代码,我不会把他们在其中一个例外是,你必须标记最终的东西,所以你可以访问的情况下它从一个匿名内部类内。


Answer 2:

它说的是,我应该作出努力,记得吗?

不,如果你使用的是Eclipse,因为你可以配置一个保存措施以自动添加这些最后的修饰你。 然后,你得到的好处较少的努力。



Answer 3:

的“最终”的开发时的好处是至少与运行时间好处显著。 它讲述了一些代码对你的意图未来的编辑。

标一类“最终”表明你没有做设计或实现的类的过程中,努力妥善处理扩展。 如果读者可以进行更改类,并希望删除“最后”修饰符,他们可以在自己的风险这样做。 这是给他们,以确保该类将处理扩展很好。

标记变量“最后”(以及在构造函数中分配给它)是依赖注入有用。 它表示变量的“合作者”的性质。

标记的方法“最终”是抽象类是有用的。 它清楚地描绘出扩展点。



Answer 4:

我发现标记方法参数和当地人final当有问题的方法是不可理解的混乱长达几页是一个重构的有用工具。 撒上final宽松,看看有什么“不能分配给最后一个变量”错误的编译器(或您的IDE)抛出了,你也许会发现为什么被称为“数据”变空结束了,即使几个(过时)评论发誓不可能发生。

然后,您可以通过更换重用变量与新变量的声明更接近使用点修正一些错误。 然后你会发现你可以用该方法的整体部分的范围界定括号,突然你一个IDE按键远离“提取方法”和你的怪物刚刚得到更多的理解。

如果你的方法是不是已经是一个不可维护的沉船,我想有可能是在做最后的东西从它变成说残骸阻碍人们值; 但如果它是一个简短的方法(参见:不是不可维护的),那么你就有可能加入了很多冗长的。 特别是,Java函数签名够硬装入80个字符,因为它是不添加6%的说法更!



Answer 5:

我用final所有的时间,使基于Java的更多的表达。 见Java的条件( if,else,switch )不是以表达我特别是如果一直恨你用函数式编程(即ML,斯卡拉或Lisp的)。

因此,你应该尝试总是(恕我直言)使用条件使用时,最终的变量。

让我给你举个例子:

    final String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
        default:
            throw new IllegalStateException();
    }

现在,如果添加其他case发言,并没有设置name ,编译器将失败。 如果你没有在任何情况下打破(您设置的变量)编译器也将失败。 这使您可以让Java非常相似,Lisp的let表情,并使其所以你的代码没有大规模缩进(因为词法范围变量)。

正如@Recurse指出的(但显然-1我),你可以做出来让前面的String name final得到编译器错误(我从来没有说你不能),但你可以很容易使编译器错误走开设置名称其扔掉表达语义或switch语句之后更糟忘记break ,你不能在不使用导致错误(不管什么@Recurse说) final

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            //break; whoops forgot break.. 
            //this will cause a compile error for final ;P @Recurse
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

因为错误设置的名称(除了忘记break这也另一个bug)我现在可以不小心这样做:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        //should have handled all the cases for pluginType
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

最后一个变化的力的名称应该是什么样一个单一评价。 方式类似,具有返回值的函数必须返回一个值(忽略例外)名称开关组将不得不解决的名字,从而绑定到该交换机模块,这使得代码更容易重构块(即的Eclipe重构:提取方法) 。

OCaml中以上:

type plugin = CandidateExport | JobPostingImport

let p = CandidateExport

let name = match p with
    | CandidateExport -> "Candidate Stuff"
    | JobPostingImport -> "Blah" ;;

match ... with ...评估像一个函数,即表达。 注意它看起来像我们的switch语句。

这里是在方案(球拍或鸡)的示例:

(define name 
    (match b
      ['CandidateExport "Candidate Stuff"]
      ['JobPostingImport "Blah"]))


Answer 6:

那么,这一切都取决于你的风格...如果你喜欢看到最后的时候,你将不会被修改的变量,然后使用它。 如果你不喜欢看到它......然后离开它。

我个人比较喜欢少冗长越好,所以我倾向于避免使用是不是真的有必要额外的关键字。

我喜欢动态语言的,所以它可能是毫不奇怪,我喜欢以避免冗长。

所以,我会说随便挑你倾向于方向,只是去用它(不管怎样,尽量保持一致)。


作为一个方面说明,我已经都使用项目工作,不使用这样的格局,我已经看到了错误或错误...我不认为量没有区别它是一种模式是,将极大提高你的bug数量或任何东西,但是这又是风格,如果你喜欢表达,你不会修改它的意图,然后继续使用它。



Answer 7:

在参数,以避免改变意外的参数值,并引进一个微妙的错误是非常有用的。 我用它来忽略此项建议,但花一些4小时后。 在一个可怕的方法(与数百码和多维权,嵌套的IFS和所有种类的陋习线),我会建议你做这件事。

 public int processSomethingCritical( final int x, final int y ){
 // hundreds of lines here 
     // for loop here...
         int x2 = 0;
        x++; // bug aarrgg...
 // hundreds of lines there
 // if( x == 0 ) { ...

 }

当然,在一个完美的世界,这是不会发生的,但..好..有时你必须要支持别人的代码。 :(



Answer 8:

如果你正在编写一个应用程序,有人会后阅读代码,比如,1年,那么,用最后的变量不应该修改所有的时间。 通过这样做,你的代码会更加“自我记录”,你还可以减少对其他开发商有机会做愚蠢的事情就像使用本地常数作为本地临时变量。

如果你正在写一些一次性的代码,然后,不,不要刻意去确定所有的常数,使他们最终决定。



Answer 9:

我将用最终的尽我所能。 这样做会标志,如果你无意中更改领域。 我还设置方法参数决赛。 从我接管了代码这样做我已经抓到了好几个错误,当他们尝试“设置”参数遗忘的Java经过值。



Answer 10:

它不是从问题清楚这是否是显而易见的,但制作方法参数最终只影响方法的主体。 它没有传达有关方法的意图给调用任何有趣的信息。 该对象被传递在仍然可以上述方法(决赛不是consts)内的突变,和可变的范围的方法内。

要回答你确切的问题,我不会刻意制造一个实例或局部变量(包括方法参数)最后,除非代码需要它(例如变量是从一个内部类中引用),或澄清一些非常复杂的逻辑。

对于实例变量,我将让他们最终,如果他们在逻辑上是常数。



Answer 11:

还有的变量很多用途final 。 这里仅仅是少数

最终常量

 public static class CircleToolsBetter {
     public final static double PI = 3.141;
        public double getCircleArea(final double radius) {
          return (Math.pow(radius, 2) * PI);
        }
    }

这可以再用于你的代码的其他部分,或由其他类访问,这样,如果你将永远改变价值,你不会有一个改变他们一个。

最终变量

public static String someMethod(final String environmentKey) {
    final String key = "env." + environmentKey;
    System.out.println("Key is: " + key);
    return (System.getProperty(key));

  }

}

在这个类中,你建立一个范围的最后一个变量,增加了一个前缀参数environmentKey。 在这种情况下,最终仅可变的执行范围,这是在该方法的每次执行不同内是最终决定。 每次进入方法时,最终是重建。 一旦它被构造,它不能被该方法执行的范围的过程中改变。 这使您可以在该方法的持续时间的方法解决一个变量。 见下文:

public class FinalVariables {


  public final static void main(final String[] args) {
    System.out.println("Note how the key variable is changed.");
    someMethod("JAVA_HOME");
    someMethod("ANT_HOME");
  }
}

最终常量

public double equation2Better(final double inputValue) {
    final double K = 1.414;
    final double X = 45.0;

double result = (((Math.pow(inputValue, 3.0d) * K) + X) * M);
double powInputValue = 0;         
if (result > 360) {
  powInputValue = X * Math.sin(result); 
} else {
  inputValue = K * Math.sin(result);   // <= Compiler error   
}

这是特别有用的,当你有代码的很长的线,它会产生编译错误,这样你就不会在运行逻辑/业务错误,当有人不小心改变,不应该被改变的变量。

最终集合

当我们在谈论集合不同的情况下,你需要将它们设置为不可修改的。

 public final static Set VALID_COLORS; 
    static {
      Set temp = new HashSet( );
      temp.add(Color.red);
      temp.add(Color.orange);
      temp.add(Color.yellow);
      temp.add(Color.green);
      temp.add(Color.blue);
      temp.add(Color.decode("#4B0082")); // indigo
      temp.add(Color.decode("#8A2BE2")); // violet
      VALID_COLORS = Collections.unmodifiableSet(temp);
    }

否则,如果不将其设置为不可修改:

Set colors = Rainbow.VALID_COLORS;
colors.add(Color.black); // <= logic error but allowed by compiler

final类final方法不能扩展或分别覆盖。

编辑:为了解决最后一类问题有关封装:

有两种方法,使一类决赛。 第一种方法是使用关键字最终在类的声明:

public final class SomeClass {
  //  . . . Class contents
}

做一个级决赛中的第二种方法是申报其所有构造函数为私有的:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

其标记最终可以节省你,如果查不到,这是实际的最后,向人们展示一下这个测试类的麻烦。 公众看第一眼。

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

不幸的是,因为类的唯一构造函数是私有的,它是不可能扩展这个类。 在测试类的情况下,没有理由这个类应该是最终决定。 测试类是final类隐怎么可能会导致问题的一个很好的例子。

所以,你应该标记它最终当你隐作出级决赛中以使它的构造私有。



Answer 12:

有点折衷的你提到,但我更喜欢隐式使用显式使用的东西。 这将有助于消除一些模糊的代码将来的维护 - 哪怕它只是你。



Answer 13:

如果你有内(匿名)类和方法需要访问含有方法的变量,你需要有一个变量决赛。

除此之外,什么你说的很对。



Answer 14:

使用final关键字的变量,如果你制作的变量immutable

通过声明的变量,最后,它帮助开发者排除变量可能的修改问题,高度多线程环境。

与Java 8的发布,我们又多了一个概念叫做“ effectively final variable ”。 非最终变量可以松作为最终变量。

从lambda表达式中引用的局部变量必须是最终或有效决赛

如果它不是初始化之后在本地块修改的变量被认为是有效最后 。 这意味着您现在可以使用本地变量没有final关键字匿名类或lambda表达式中,只要它们必须是有效的决赛。

直到Java 7中,您不能使用非最终的局部变量的匿名内部类,但是从Java 8即可

看看这个文章



Answer 15:

一个非常简单的答案,我们有3例最终以变量,最终以方法&&最终以类..

1.Final变:U`吨分配这个变量超过一次..

2.Final与方法:U`吨重写此方法..

3.Final带班:U不能老是扩展任何final类



Answer 16:

首先,final关键字是用来做一个变量不变。 恒意味着它不会改变。 例如:

final int CM_PER_INCH = 2.54;

你会声明变量最终因为每英寸厘米不会改变。

如果试图重写终值,该变量是它第一次声明。 例如:

final String helloworld = "Hello World";
helloworld = "A String"; //helloworld still equals "Hello World"

还有就是像一个编译错误:

local variable is accessed from inner class, must be declared final

如果您的变量不能被声明为final,或者如果你不想声明它最终试试这个:

final String[] helloworld = new String[1];
helloworld[0] = "Hello World!";
System.out.println(helloworld[0]);
helloworld[0] = "A String";
System.out.println(helloworld[0]);

这将打印:

Hello World!
A String


文章来源: When should one use final for method parameters and local variables?
标签: java final