Topic: switch语句用法的困惑

  Print this page

1.switch语句用法的困惑 Copy to clipboard
Posted by: othello
Posted on: 2003-06-04 23:44

我在运行tij中的范例程序时,发现一个让我不解的事情。程序如下。

-------------------------------------------------
//: c07:Shapes.java
// From 'Thinking in Java, 2nd ed.' by Bruce Eckel
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
// Polymorphism in Java.

class Shape {
void draw() {}
void erase() {}
}

class Circle extends Shape {
void draw() {
System.out.println("Circle.draw()");
}
void erase() {
System.out.println("Circle.erase()");
}
}

class Square extends Shape {
void draw() {
System.out.println("Square.draw()");
}
void erase() {
System.out.println("Square.erase()");
}
}

class Triangle extends Shape {
void draw() {
System.out.println("Triangle.draw()");
}
void erase() {
System.out.println("Triangle.erase()");
}
}

public class Shapes {
public static Shape randShape() {
switch((int)(Math.random() * 3)) {
default:
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
}
}
public static void main(String[] args) {
Shape[] s = new Shape[9];
// Fill up the array with shapes:
for(int i = 0; i < s.length; i++)
s[i] = randShape();
// Make polymorphic method calls:
for(int i = 0; i < s.length; i++)
s[i].draw();
}
} ///:~
-------------------------------------------------

在程序中的randShape()中

public static Shape randShape() {
switch((int)(Math.random() * 3)) {
//default:
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
}
}

有一个default:语句,我认为好象没什么作用呀,就去掉了,可是编译竟不能通过,提示missing return statement
下面不是有return语句吗?
我把default移到 case 2: return new Triangle(); 后面也是如此。
加上default而且必须放上最上面,就可编译通过,这是怎么回事呀?是不是运用switch语句的一个技巧?

2.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: kavenlin
Posted on: 2003-06-04 23:55

You can write

public static Shape randShape() {
Shape shape=null;
switch((int)(Math.random() * 3)) {
//default:
case 0: shape=new Circle(); break;
case 1: shape=new Square(); break;
case 2: shape=new Triangle(); break;
}
return shape;
}

3.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: bean_wj
Posted on: 2003-06-05 09:43

1.如果去掉default,则非0、1、2时没return。
2.default移到case2后,同样当非0、1、2时没return。
此函数必须要reuturn语句。
3.加上default在最上,则任何情况都有return。

4.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: othello
Posted on: 2003-06-05 09:48

可是原来的程序在default后面也没有return语句呀,可是编译是可以通过的,
只不过default必须放在最前面,放在后面则不行,我主要想知道放在前面和
放在后面为什么会有不同的结果?

另外(int)(Math.random() * 3)的值只会有三种可能,即:0,1,2.这样应该不会
有其它的情况出现,那我们还需要default语句吗?

5.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: 牛老板
Posted on: 2003-06-05 10:23

1. default在语法中是可选的.
2. 由于(fall-through)的存在,所以case的顺序是很关键的.

呵呵....

6.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: bean_wj
Posted on: 2003-06-05 10:30

1.放在最后面一定错,因为没有return对应,放在前面如果值是非0、1、2则对应default,又因为没break,顺序往下return0。
2.编译器不会判断逻辑,和(int)(Math.random() * 3)的值有哪些情况没关系。

7.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: emarket
Posted on: 2003-06-05 10:39

(switch.txt是排过版的)
一,首先理解3种情况
1.这种情况可以可以编译
int doSomething(){
if(true){
return 1;
}else{
return 0;
}
}

2.这种情况就不可以
int doSomething(){
if(true){
return 1;
}

}
3.这种情况也不行
int doSomething2(){
if(true){
return 1;
}
if(false){
return 2;
}
}

明白了以上3种情况,你应该了解到,java compiler是怎么工作的了吧
他认为 if()else 才是可以完全覆盖的
但是 if(true) if(false) 则不是。

二,理解switch得default:如果没有其他条件满足,则执行default.

三,理解break在swith中的行为(这点不用我讲了吧),强调一点,case语句only提供入口
出口要break来把握,也就是说如果一个case block没有一个break,那么这个case会继续执行
(除非遇到return 或抛出异常)。

四,来看看你的问题
1. (没有default得情况)
  public static Shape randShape() {
    switch((int)(Math.random() * 3)) {
      //default:
      case 0: return new Circle();
      case 1: return new Square();
      case 2: return new Triangle();
    }
  }
这样子理解你的程序:
  public static Shape randShape() {
    int i=((int)(Math.random() * 3)) ;
    if(i==0)
     return new Circle();
   else if(i==1) return new Square();
else if (i==2) return new Triangle();
     // else{ //default miss return
       //不能编译
   }

  
2. default在末尾的情况   
public static Shape randShape() {
    switch((int)(Math.random() * 3)) {
      case 0: return new Circle();
      case 1: return new Square();
      case 2: return new Triangle();
      default:
    }
  }
这样子理解你的程序:
  public static Shape randShape() {
    int i=((int)(Math.random() * 3)) ;
    if(i==0)
     return new Circle();
   else if(i==1) return new Square();
else if (i==2) return new Triangle();
     else{ //default
     //donothing here, so miss return
     //不能编译
    
  }

3. default在头的情况   
public static Shape randShape() {
    switch((int)(Math.random() * 3)) {
     default:// no break here, if has a break, then can not compile
      case 0: return new Circle();
      case 1: return new Square();
      case 2: return new Triangle();
    }
  }
这样子理解你的程序:
   public static Shape randShape() {
    switch((int)(Math.random() * 3)) {
     default: /*case 0*/ return new Circle(); // 因为没有break,这条default得的对等结果就是执行case 0;
      case 0: return new Circle();
      case 1: return new Square();
      case 2: return new Triangle();
    }
  }

so

public static Shape randShape() {
    int i=((int)(Math.random() * 3)) ;
    if(i==0)
     return new Circle();
   else if(i==1) return new Square();
else if (i==2) return new Triangle();
     else{ //default
     return new Circle();   //has a return 可以编译       
  }   

是不是有点糊涂了//hehe
其实简单来说, 1, 如果default在头,加上break照样不能编译(因为这样这条default得的对等结果就不是执行case 0了)
2, 如果default在尾,加上return new Circle()照样可以编译
3,其实把default(without break) 放在 case 2之前,都可以编译

switch.txt (3.23k)

8.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: othello
Posted on: 2003-06-05 14:52

这个问题我在csdn和cjsdn分别提问,大家可以参照这两个帖子。
csdn:http://expert.csdn.net/Expert/topic/1877/1877411.xml?temp=.4656793
cjsdn:http://www.cjsdn.com/post/view?bid=1&id=31157&sty=1

非常感谢大家这么耐心而又细致的解答,谢谢!

综合大家的观点和我自已的理解,做一总结如下:

1.为什么需要 default 语句?

在randShape()中,其实 (int)(Math.random() * 3 的结果只有三种可能,就是:0,1,2
好象default语句是多余的,实际上(int)(Math.random() * 3 的值只有在运行期才会得出,
而编译器事先无法知道只可能有三种结果,它认为还有其它的结果,并且 randShape() 要求
必须返回一个 Shape object ,因此编译器需要一个default语句。

其实在运行期,永远都不会执行 default 后面的子句,因为不可能出现三种结果以外的
情况,加入default 语句只是为了让编译器顺利通过编译。

这也是最初让我困惑的地方,在我的头脑中已经有了(int)(Math.random() * 3 只有三种
结果的想法,而这一切编译器不知道,我的思维方式与编译器的运作方式出现了错位。

emarket 老兄的示例很好,让我对这一问题有了了解。详见 emarket 的帖子。

2.为什么 default 语句(在其后没有子句的情况下)不能放在switch语句块的块尾。

public static Shape randShape() {
switch((int)(Math.random() * 3)) {
default:
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
}
}

等价于

public static Shape randShape() {
switch((int)(Math.random() * 3)) {
default: return new Circle();
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
}
}

上面是default放在块头的情形。default 放在其它地方也可以,只是不能放在块尾
(在default后没有子句的情况下),当执行到default语句时,由于其后并无break,
return语句,它会执行紧接于其后的语句(尽管在运行期default语句不会被执行)。

public static Shape randShape() {
switch((int)(Math.random() * 3)) {
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
default:
}
}

编译器认为在三种结果之外情况下, randShape() 不能获得返回值。所以它不允许
编译通过。
有好几位朋友都提到这一点。

到此这个问题有了最终的解答,如果没有人对我以上的总结提出异议或补充的话,明天就
可以结帖了。再次感谢大家让我这么快就获得了答案。

9.Re:switch语句用法的困惑 [Re: othello] Copy to clipboard
Posted by: Hodex
Posted on: 2003-06-10 14:06

呵呵


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923