论坛首页 Java企业应用论坛

单命令行下,if 必须加"{}" 的问题

浏览 20704 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (16)
作者 正文
   发表时间:2011-05-31  
你该明白你在公司写的代码不是永远只有你个人来维护!你确实对你自己的代码很熟!但你也有离开的一天,别人来接的时候就体现出{}重要性了!
0 请登录后投票
   发表时间:2011-05-31   最后修改:2011-05-31
加上可以减少很多维护风险,仅此一个理由就够了吧?
if (a > 0)      return 1;  
else if (a < 0) return -1;  
else (a == 0)   return 0;  

如果是确定不会有其它情况,那还不如直接三目:
return a>0 ? 1 : (a<0 ? -1 : 0);

问题是,以后维护的人看这行代码时会多蛋疼……
0 请登录后投票
   发表时间:2011-05-31  
不要给自己的懒找借口,也不要认为行号少了几十就显得多高明。

幸好LZ没有批判 (a > 0) 多了两个空格占地方
0 请登录后投票
   发表时间:2011-05-31  
工具限制思路。

在java里,for、if表达式本身都不返回值,它们的作用只是在适当的情况下执行后面语句,因此,执行这些语句必然要产生一定的效果,例如给变量赋值成计算后的值,换句话说,这些语句必然产生side effect。



那么“有没有side effect”和“要不要加大括号”有什么联系呢?

举例,根据对一个现有的list每项加一得到新的list,用java实现是:
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        List<Integer> newList = new ArrayList<Integer>();
        for(Integer item:list){
            //注意,这里以后还可以加一些与生成newList无关的其它代码,比如,计算item累加值。
            newList.add(item + 1);
        }


用scala实现是:
val list = List(1,2,3) 
val newList = for(item <- list)yield{
  // 注意这里,无论下面代码以后有多长,都与计算新元素有关。
  // 如果以后有其它需求,使用新的for语句来做。
  item + 1
} 


随着项目的开展,对于java代码,常常需要往已有的for、if语句里添加新代码来做其它事情,如果事先不加大括号,也会编译通过,但得到的运行结果又不是预期的,这样发现问题的成本比较高。

也就是说,java这种有side effect的if/for语句,以后难免要膨胀,早加大括号也许会减少修复bug的成本,相比之下,上面scala风格的if/for的功能是单一、明显、可控的。
0 请登录后投票
   发表时间:2011-05-31   最后修改:2011-05-31
这种规范问题讨论起来仁者见仁,智者见智,不过我认为必须加上,java语言就在其规范性特强,所有人按照编码规范编码,最好的结果就是大家写一个功能,一个思路的情况下,代码一模一样,这才是好代码,这样极易维护,来个人就能看明白,思想上要创新,规范上创新有什么用,少写两个括号就能显出你牛b吗?感觉不写括号就不够严谨。

要是不加括号,多行时候必须加,1行时候不加,你自己看着不别扭吗?手动缩进多累啊。

最后举个例子,你可以举出100多条早上起来不叠被的好处,有10000个人赞同你,但是军队还是要叠被,叠的还很齐;企业就是这样,你好处再多,企业还是需要规范,需要管理的。不加括号就像不叠被的新兵(举例而已),个人能力再强,不遵守规范也不是好兵(除非你们公司规定就不加)。
0 请登录后投票
   发表时间:2011-05-31  
雪飘寒 写道
这种规范问题讨论起来仁者见仁,智者见智,不过我认为必须加上,java语言就在其规范性特强,所有人按照编码规范编码,最好的结果就是大家写一个功能,一个思路的情况下,代码一模一样,这才是好代码,这样极易维护,来个人就能看明白,思想上要创新,规范上创新有什么用,少写两个括号就能显出你牛b吗?感觉不写括号就不够严谨。

要是不加括号,多行时候必须加,1行时候不加,你自己看着不别扭吗?手动缩进多累啊。

最后举个例子,你可以举出100多条早上起来不叠被的好处,有10000个人赞同你,但是军队还是要叠被,叠的还很齐;企业就是这样,你好处再多,企业还是需要规范,需要管理的。不加括号就像不叠被的新兵(举例而已),个人能力再强,不遵守规范也不是好兵(除非你们公司规定就不加)。

觉的这个才是问题的本质,加不加并不会影响运行的效率,编译器都进行了相应的优化
0 请登录后投票
   发表时间:2011-05-31   最后修改:2011-05-31
好吧看代码,把下面两段代码粘到eclipse中你就会知道了
public class Test
{
	public static void main(String[] args)
	{
		if (true)
		{
			String i = new String("Test");
		}

	}

}
上面的编译正确
public class Test
{
	public static void main(String[] args)
	{
		if (true)
			String i = new String("Test");

	}

}
上面的编译错误

至于原因请高人来回答
0 请登录后投票
   发表时间:2011-05-31  
lion1354 写道
好吧看代码,把下面两段代码粘到eclipse中你就会知道了
public class Test
{
	public static void main(String[] args)
	{
		if (true)
		{
			String i = new String("Test");
		}

	}

}
上面的编译正确
public class Test
{
	public static void main(String[] args)
	{
		if (true)
			String i = new String("Test");

	}

}
上面的编译错误

至于原因请高人来回答


错误提示:String cannot be resolved to a variable,这个高深了,猜测是语法错误。

 

对于if后面的{},我的实践,并且使用语法检测工具配置的策略:

我的实践:什么时候不写{},其他时候都必须写

 

  1. 没有else
  2. if后面只有一行内容且非常简单
  3. 不写{}时,必须空一行
    		if (condition) {
    			only a line statement;
    		}
    可以写为:
    		if (condition) only a line statement;
    		 //<-- a empty line;
    		other statements;
     

 

 

 

0 请登录后投票
   发表时间:2011-06-01   最后修改:2011-06-01
哥, 别蛋疼, 喝几量白酒, 然后, 来修改你的代码, 如果在单行if 一直能修改对, 那你就不需要遵循这个狗屁规则了。


这是我某年曾经犯过的错误, 从此以后{}从没有离开过if~
0 请登录后投票
   发表时间:2011-06-01   最后修改:2011-06-01
lion1354 写道
好吧看代码,把下面两段代码粘到eclipse中你就会知道了
public class Test
{
	public static void main(String[] args)
	{
		if (true)
		{
			String i = new String("Test");
		}

	}

}
上面的编译正确
public class Test
{
	public static void main(String[] args)
	{
		if (true)
			String i = new String("Test");

	}

}
上面的编译错误

至于原因请高人来回答

嘛,这个的理由很简单:因为局部变量声明不是“语句”。
这是Java语言规范里非常搞笑的一个地方:请看Java语言规范第三版18.1所指定的语法规则中的几条:
Block:
        { BlockStatements }

BlockStatements:
        { BlockStatement }

BlockStatement :
        LocalVariableDeclarationStatement
        ClassOrInterfaceDeclaration
        [Identifier :] Statement

LocalVariableDeclarationStatement:
        [final] Type VariableDeclarators   ;

Statement:
        Block
        assert Expression [ : Expression] ;
     if ParExpression Statement [else Statement]
     for ( ForControl ) Statement
     while ParExpression Statement
     do Statement while ParExpression   ;
     try Block ( Catches | [Catches] finally Block )
     switch ParExpression { SwitchBlockStatementGroups }
     synchronized ParExpression Block
     return [Expression] ;
     throw Expression   ;
     break [Identifier]
     continue [Identifier]
        ;
        StatementExpression ;
        Identifier   :   Statement

MethodBody:
        Block

方法体必须是一个block。
Block是由花括号包围的零或多个BlockStatement。
BlockStatement可以是局部变量声明,或者类/接口声明(注:这样的类或接口被称为“局部类”(local class)“局部接口”(local interface)),或者是可选带label的语句Statement。
语句有若干中可能,其中一种是if语句;if语句的then分支必须是一个Statement。

关注点是:LocalVariableDeclarationStatement虽然叫做“Statement“,但在语法规则中它却不是一种”Statement“。所以说根据这个规则,局部变量声明就不是语句,自然也就不能单独出现在if的then分支位置上。被花括号包围起来的话它就是一个Block了,而Block是Statement的一种所以没问题。

槽点:叫做“语句”但却不是语句的局部变量声明。

顺带一提,NS提醒我,在javac里代表局部变量声明的节点类型是JCVariableDecl,该类继承了代表了语句的JCStatement类;但是,javac仍然会按照语法规范来检查…所以if的then分支上还是不能单独放一个局部变量声明 =_=|||
想看源码的请点:
http://hg.openjdk.java.net/jdk6/jdk6/langtools/file/tip/src/share/classes/com/sun/tools/javac/tree/JCTree.java
1 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics