Java流程控制的陷阱——if语句和循环体的陷阱

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Never_Blue/article/details/70786738

3、if语句的陷阱

3、1 else隐含的条件

       else字面意义是“否则”,隐含的条件是前面条件都不符合,也就是else有一个隐含的条件,else if的条件是if显示条件和else隐式条件的交集。
public class IfErrorTest {
	public static void main(String[] args) {
		int age = 45;
		if ( age > 20 ) {
			System.out.println("青年人");
		}
		else if ( age > 40 ) {
			System.out.println("中年人");
		}
		else if ( age > 60 ) {
			System.out.println("老年人");
		}
	}
}
输出结果为:
青年人
       上面的程序是试图根据年龄来判断属于青年人、中年人还是老年人。从表面上来看,程序的运行过程为:年龄大于20岁是青年人,年龄大于40岁的是中年人,年龄大于60岁的是老年人。但是最终输出的却是青年人。造成这个问题的原因就是else后的隐含条件,else的隐含条件就是不满足else之前的条件。换句话来说,上面的代码实质上等于如下代码。
public class IfErrorTest {
	public static void main(String[] args) {
		int age = 45;
		if ( age > 20 ) {
			System.out.println("青年人");
		}
		else if ( age > 40 && !(age > 20)) {
			System.out.println("中年人");
		}
		else if ( age > 60 && !(age > 40) ) {
			System.out.println("老年人");
		}
	}
}
       这样就比较容易看出为什么会发生上面的错误。对于判断中年人和老年人的情况是永远不会发生的,因此,程序也永远不可能打印出中年人和老年人。为了能够达到预期的效果,将程序修改为如下所示。
public class IfRightTest {
	public static void main(String[] args) {
		int age = 45;
		if ( age > 60 ) {
			System.out.println("老年人");
		}
		else if ( age > 40 ) {
			System.out.println("中年人");
		}
		else if ( age > 20 ) {
			System.out.println("青年人");
		}
	}
}
输出结果为:
中年人
       上面程序的判断逻辑可以转换为如下三种情形。
  1. age大于60,判断为“老年人”。
  2. age大于40岁,且age小于等于60岁,判断为“中年人”。
  3. age大于20岁,且age小于等于40岁,判断为“青年人”。

       如果每次都去计算if条件和else条件的交集也是一件非常繁琐的事情,为了避免出现上面的错误,使用if-else语句有一条基本原则: 总是优先把包含范围小的条件放在前面处理。例如age>60比age>20的范围更小,所以应该优先处理age>60的情况。

3、2 空语句

public class BlankStatement {
	public static void main(String[] args) {
		int age = 45;
		if ( age > 60 ); {
			System.out.println("老年人");
		}
		else if ( age > 40 ) {
			System.out.println("中年人");
		}
		else if ( age > 20 ) {
			System.out.println("青年人");
		}
	}

}
从表面上来看,这个程序应该一切正常,程序先处理小范围条件,后处理大范围的条件,应该输出“青年人”,但是程序却报错:Syntax error on token "else", delete this token。原因是:if ( age > 60 );,在判断之后有一个分号,这个分号就是一个空语句。也就是说,这个分号就是if语句的条件执行体,if语句到这里就完全结束了。 需要指出的是,如果if语句后没有花括号括起来的条件执行体,那么这个if语句仅仅控制到该语句后的第一个分号处,后面部分将不再受该if语句的控制

4、循环体的陷阱

4、1 循环体花括号

       Java对于if语句、while语句、for语句的处理策略完全一样:如果紧跟该语句的是花括号括起来的语句块,那么该 if语句、while语句、for语句将控制花括号括起来的语句块;如果if语句、while语句、for语句之后没有紧跟花括号,那么if语句、while语句、for语句的作用范围到该语句之后的第一个分号结束。
public class WhileScopeTest {
	public static void main(String[] args) {
		int i = 0 ; 
		while ( i < 10 ) 
			System.out.println(i);
			i ++;
	}
}
       上面程序编译正常,运行时一直输出0,并且是一个死循环。出现这个输出结果是因为程序省略了while循环的循环体花括号,那么受while循环控制的循环体只有一行代码System.out.println(i);。接下来的i++;并不在循环体之内,将导致循环计数器i一直保持0。
       只有当循环体内只包含一条语句时才可以省略循环体的花括号,此时循环本身不会受到太大的影响。当循环体有多条语句时,不可省略循环体的花括号,否则循环体将变成只有紧跟循环条件的那条语句。

4、2 省略花括号的危险

class Cat {
	private static long instance = 0;
	
	public Cat() {
		System.out.println("执行无参数的构造器");
		instance++;
	}
	
	public static long getInstance() {
		return instance;
	}
}

public class CatTest {
	public static void main(String[] args) {
		for ( int i = 0 ; i < 10 ; i ++ ) 
			Cat cat = new Cat();
		System.out.println(Cat.getInstance());
	}
}
       上面程序试图通过for循环来创建10个Cat对象,然后通过getInstance()静态方法获取instance的值,由于循环体只有一条语句,因此省略了循环体的花括号,但是如果尝试编译该程序,编译器会报错:Syntax error, insert ";" to complete Statement。发生这种错误的原因: 因为Java语言规定:for、while或do循环中的重复执行语句不能是一条单独的局部变量定义语句;如果程序要使用循环来重复定义局部变量,这条局部变量定义语句必须放在花括号内才有效。因此将程序改为如下所示。
class Cat {
	private static long instance = 0;
	
	public Cat() {
		System.out.println("执行无参数的构造器");
		instance++;
	}
	
	public static long getInstance() {
		return instance;
	}
}

public class CatTest {
	public static void main(String[] args) {
		for ( int i = 0 ; i < 10 ; i ++ ) {
			Cat cat = new Cat();
		}
		System.out.println(Cat.getInstance());
	}
}






猜你喜欢

转载自blog.csdn.net/Never_Blue/article/details/70786738
今日推荐