开源俱乐部

开源框架
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

java中goto语句解析12

Posted on 2006-07-31 09:24 HandSoft 阅读(17274) 评论(8)  编辑  收藏

hi,
    今天无意中看到有个兄弟在java程序中多次用到了goto语句,感觉很是怪异,copy来编译下发现有很多错误!
为此,我付出了一下午时间去研究这个块被人遗忘了的可怕的"魔鬼".
   “可怕”的goto语句是c和c++的“遗物”,它是该语言技术上的合法部分,引用goto语句引起了程序结构的混乱,不易理解,goto语句子要用于无条件转移子程序和多结构分支技术。鉴于以广理由,Java不提供goto语句,它虽然指定goto作为关键字,但不支持它的使用,使程序简洁易读。在Java中goto语句被完全抛弃了,与此同时,Java又扩大了break语句和continue语句的功能,通过使用break和continue,程序流程被允许在多层循环中跳转。
大家再看看以下代码:

 

import java.sql.*;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// Referenced classes of package fiyucore.db:
//            DBOptions

class DBConnectionManager
{
    class DBConnectionPool
    {

        private String URL;
        private int checkedOut;
        private Vector freeConnections;
        private int maxConn;
        private String password;
        private String user;

        synchronized void freeConnection(Connection con)
        {
            if(con == null)
                break MISSING_BLOCK_LABEL_63;
            if(checkedOut > 0)
                break MISSING_BLOCK_LABEL_39;
            DBConnectionManager.log.debug("DBConnectionManager: 关闭连接");
            con.close();
              goto _L1
            SQLException ex;
            ex;
_L1:
            break MISSING_BLOCK_LABEL_62;
            freeConnections.addElement(con);
            checkedOut--;
            notifyAll();
            return;
        }

        Connection getConnection(long timeout)
        {
            long startTime = System.currentTimeMillis();
              goto _L1
_L3:
            long timeToWait;
            long elapsedTime = System.currentTimeMillis() - startTime;
            if(elapsedTime >= timeout)
                return null;
            timeToWait = timeout - elapsedTime;
            if(timeToWait > 500L)
                timeToWait = 500L;
            Thread.sleep(timeToWait);
            continue; /* Loop/switch isn't completed */
            InterruptedException e;
            e;
_L1:
            Connection con;
            if((con = getConnection()) == null) goto _L3; else goto _L2
_L2:
            return con;
        }

        synchronized Connection getConnection()
        {
            Connection con;
            for(con = null; freeConnections.size() > 0 && con == null;)
            {
                con = (Connection)freeConnections.firstElement();
                freeConnections.removeElementAt(0);
                try
                {
                    if(con.isClosed())
                    {
                        DBConnectionManager.log.info("删除坏连接!");
                        con = null;
                    }
                }
                catch(SQLException e)
                {
                    con = null;
                }
            }

            if(con == null)
            {
                if(maxConn == 0 || checkedOut < maxConn)
                    con = newConnection();
            }
            if(con != null)
                checkedOut++;
            return con;
        }

        private Connection newConnection()
        {
            Connection con = null;
            if(user == null)
                con = DriverManager.getConnection(URL);
            else
                con = DriverManager.getConnection(URL, user, password);
            con.setAutoCommit(true);
            break MISSING_BLOCK_LABEL_83;
            SQLException e;
            e;
            DBConnectionManager.log.error("不能在连接池中创建新的连接. URL = " + URL, e);
            return null;
            return con;
        }

        synchronized boolean release()
        {
            boolean retValue;
            Enumeration allConnections;
            retValue = true;
            allConnections = freeConnections.elements();
              goto _L1
_L3:
            Connection con = (Connection)allConnections.nextElement();
            con.close();
            continue; /* Loop/switch isn't completed */
            SQLException e;
            e;
            DBConnectionManager.log.error("不能关闭连接!");
_L1:
            if(allConnections.hasMoreElements()) goto _L3; else goto _L2
_L2:
            freeConnections.removeAllElements();
            if(checkedOut != 0)
            {
                retValue = false;
                DBConnectionManager.log.warn("DBConnectionManager: 内置的连接池没有正确配置好");
            }
            checkedOut = 0;
            return retValue;
        }

        public DBConnectionPool(String URL, String user, String password, int maxConn)
        {
            checkedOut = 0;
            freeConnections = new Vector();
            this.maxConn = 0;
            this.password = null;
            this.URL = null;
            this.user = null;
            this.URL = URL;
            this.user = user;
            this.password = password;
            this.maxConn = maxConn;
        }
    }


    private static final int TIME_BETWEEN_RETRIES = 500;
    static Class class$fiyucore$db$DBConnectionManager; /* synthetic field */
    private static DBConnectionManager instance = null;
    private static Log log;
    private DBConnectionPool pool;

    private DBConnectionManager(DBOptions option)
    {
        pool = null;
        Class.forName(option.driverClassName).newInstance();
        break MISSING_BLOCK_LABEL_59;
        Exception e;
        e;
        log.fatal("DBConnectionManager: 不能加载驱动 = " + option.driverClassName);
        pool = new DBConnectionPool(option.databaseURL, option.databaseUser, option.databasePassword, option.maxConnection);
        return;
    }

    static Class class$(String x0)
    {
        return Class.forName(x0);
        ClassNotFoundException x1;
        x1;
        throw new NoClassDefFoundError(x1.getMessage());
    }

    void freeConnection(Connection con)
    {
        pool.freeConnection(con);
    }

    Connection getConnection(long time)
    {
        return pool.getConnection(time);
    }

    Connection getConnection()
    {
        return pool.getConnection();
    }

    public static synchronized DBConnectionManager getInstance(DBOptions option)
    {
        if(instance == null)
        {
            if(option == null)
                option = new DBOptions();
            instance = new DBConnectionManager(option);
        }
        return instance;
    }

    public static synchronized DBConnectionManager getInstance()
    {
        if(instance == null)
        {
            DBOptions option = new DBOptions();
            instance = new DBConnectionManager(option);
        }
        return instance;
    }

    boolean release()
    {
        return pool.release();
    }

    static
    {
        log = LogFactory.getLog(class$fiyucore$db$DBConnectionManager != null ? class$fiyucore$db$DBConnectionManager : (class$fiyucore$db$DBConnectionManager = class$("fiyucore.db.DBConnectionManager")));
    }

}
这程序初看起来是多么的恐怖啊!多次用到goto,混乱。关于流程控制的方法,c++,java都提供了很好的语法:

  • 分支语句 :if-else,break,switch, return.
  • 循环语句 :while,do-while,for, continue.
  • 例外处理语句 :try-catch-finally,throw
  • 最后我们简单介绍一下注释语句
  • 支语句

    分支语句提供了一种控制机制,使得程序的执行可以跳过某些语句不执行,而转去执行特定的语句。

    条件语句if-else.

    if-else语句根据判定条件的真假来执行两种操作中的一种,格式为:

    if(boolean-expression)
    statement1;
    [else statement2;]


    1.布尔表达式boolean-expression是任意一个返回布尔型数据的达式(这比C、 C++的限制要严格)。

    2.每个单一的语句后都必须有分号。

    3.语句statement1,statement2可以为复合语句,这时要用大括号{}。建议对单一的语句也用大括号括起,这样程序的可读性强,而且有利于程序的扩充(可以在其中填加新的语句)。{}外面不加分号。

    4.else子句是任选的。

    5.若布尔表达式的值为true,则程序执行statement1,否则执行statement2。

    6.if-else语句的一种特殊形式为:

    if(expression1){ 
    statement1 
    }else if (expression2){ 
    statement2 
    }…… 
    }else if (expressionM){ 
    statementM 
    }else { 
    statementN 

    [else子句不能单独作为语句使用,它必须和if配对使用。else总是与离它最近的if配对。可以通过使用大括号{}来改变配对关系。]
    多分支语句switch

    switch语句根据表达式的值来执行多个操作中的一个,它的般格式如下:

    switch (expression){
    casevalue1:statement1;
    break;
    casevalue2:statement2;
    break;
    …………
    casevalueN:statemendN;
    break;
    [default:defaultStatement;]
    }


    1.表达式expression可以返回任一简单类型的值(如整型、实数型、字符型),多分支语句把表达式返回的值与每个case子句中的值相比。如果匹配成功,则运行该case子句后的语句序列。

    2.case子句中的值values必须是常量,而且所有case子句中的值是不同的。

    3.default子句是任选的。当表达式的值与任一case子句中的都不匹配时,程序执行default后面的语句。如果表达式的值与任一case子句中的值都不匹配且没有default子句,则程序不作任何操作,而是直接跳出switch语句。

    4.break语句用来在执行完一个case分支后,使程序跳出switch语句,即终止switch语句的执行。因为case子句只是起到一个标号的作用,用来查找匹配的入口,从此处开始执行,对后面的case子句不再进行匹配,而是直接执行其后的语句序列,因此该在每个case分支后,要用break来终止后面的case分支语句的执行。

    在一些特殊情况下,多个不同的case值要执行一组相同的操作,这时可以不用break。

    5.case分支中包括多个执行语句时,可以不用大括号{}括起。

    6.switch语句的功能可以用if-else来实现,但在某些情况下,使switch语句更简炼,可读性强,而且程序的执行效率提高。
    break语句

    1.在switch语中,break语句用来终止switch语句的执行。使程序switch语句后的第一个语句开始执行。

    2.在Java中,可以为每个代码块加一个括号,一个代码块通常用大括号{}括起来的一段代码。加标号的格式如下:

    BlockLabel:{codeBlock}

    break语句的第二种使用情况就是跳出它所指定的块,并从紧挨该块的第一条语句处执行。其格式为:

    break BlockLabel;
    例如:
    a:{……//标记代码块a
    b:{……//标记代码块b
    c:{……//标记代码块c
    break b;
    …… //willnotbeexecuted
    }
    …… //willnotbeexecuted
    }
    …… //willnotbeexecuted
    }
    …… /executefromhere
    }


    3.与C、 C++不同,Java中没有goto语句来实现任意的跳转,因为goto语句破坏程序的可读性,而且影响编译的优化。但是从上例可以看出,Java用break来实现goto语句所特有的一些优点。如果break后所指定的标号不是一个代码块的标号,而是一个语句,则这时break完全实现goto的功能。不过应该避免这种方式的使用。
    返回语句return

    return语句从当前方法中退出,返回到调用该方法的语句处,继续程序的执行。返回语句有两种格式:


    1.return expression

    返回一个值给调用该方法的语句,返回值的数据类型必须用方法声明中的返回值类型一致。可以使用强制类型转换来使类型一致。

    2.return

    当方法说明中用void声明返回类型为空时,应使用这种格式,不返回任何值。

    return语句通常用在一个方法体的最后,以退出该方法并返一个值。Java中,单独的return语句用在一个方法体的中间时,会产生编译错误,因为这时有一些语句执行不到。但
    可以通过把return语句嵌入某些语句(如if-else)来使程序在未执行完方法中的所有语句时退出,例如:

    int method (int num) { 
    ∥ return num; ∥will cause compile time error 
    if (num>0) 
    return num; 
    …… ∥ may or may not be executed 
    ∥depending on the value of num 
    环语句

    循环语句的作用是反复执行一段代码,直到满足终止循环条件为止,一个循环一般应包括四部分内容:

    1.初始化部分(initialization):用来设置循环的一些初始条件,计数器清零等。

    2.循环体部分(body):这是反复循环的一段代码,可以是单一一条语句,也可以是复合语句。

    3.迭代部分(iteration):这是在当前循环结束,下一次循环开始执行的语句,常常用来使计数器加1或减1。

    4.终止部分(termination):通常是一个布尔表达式,每一次循环要对该表达式求值,以验证是否满足循环终止条件。

    Java中提供的循环语句有:while语句,do-while语句和for语句,下分别介绍。
    while语句

    while语句实现"当型"循环,它的一般格式为;

    [initialization]
    while (termination){
    body;
    [iteration;]
    }


    1.当布尔表达式(termination)的值为true时,循环执行大括号中语句。并且初始化部分和迭代部分是任选的。

    2.while语句首先计算终止条件,当条件满足时,才去执行循环当中的语句。这是"当型"循环的特点。


    do-while语句

    do-while语句实现"直到型"循环,它的一般格式为:
    [initialization]
    do{
    body;
    [iteration;]
    }while (termination);


    1.do-while语句首先执行循环体,然后计算终止条件,若结果为true,则循环执行大括号中的语句,直到布尔表达式的结果为false。

    2.与while语句不同的是,do-while语句的循环体至少执行一次,这是"直到型"循环的特点。
    for语句

    for语句也用来实现"当型"循环,它的一般格式为:

    for(initialization;termination; iteration){

    body;

    }

    1.for语句执行时,首先执行初始化操作,然后判断终止条件否满足,如果满足,则执行循环体中的语句,最后执行迭代部分。完成一次循环后,重新判断终止条件。

    2.可以在for语句的初始化部分声明一个变量,它的作用域为一个for语句。

    3.for语句通常用来执行循环次数确定的情况(如对数组元素进行操作),也可以根据循环结束条件执行循环次数不确定的情况。

    4.在初始化部分和迭代部分可以使用逗号语句,来进行多个操作。逗号语句是用逗号分隔的语句序列。例如:

    for(i=0,j=10;i<j;i++, j--){
    ……
    }
    5.初始化、终止以及迭代部分都可以为空语句,三者均为空的时候,相当于一个无限循环。


    continue语句

    1.continue语句用来结束本次循环,跳过循环体中下面尚未执的语句,接着进行终止条件的判断,以决定是否继续循环。对于for语句,在进行终止条件判断前,还要先执行迭代
    语句。它的格式为:

    continue;
    2.也可以用continue跳转到括号指明的外层循环中,这时的格为

    continue outerLable; 

    例 如 : 

    outer: for( int i=0; i<10; i++ ){ ∥外层循环 
    for( int j=0; j<20; j++ ){ ∥内层循环 
    if( j>i ){ 
    …… 
    continue outer; 

    …… 

    …… 



    该例中,当满足j>i的条件时,程序执行完相应的语句后跳转到外层循环,执行外层循环的迭代语句i++;然后开始下一次循环。
    可以从中来比较这三种循环语句,从而在不同的场合选择合适的语句。
    外处理语句

    例外处理语句包括try、catch、finally以及throw语句

    释语

    Java中可以采用三种注释方式:

    1∥ 用于单行注释。注释从∥开始,终止于行尾。
    2/*…*/用于多行注释。注释从/*开始,到*/结束,且这种注释不能互相嵌套。
    3/**…*/是Java所特有的doc注释。它以/**开始,到*/结束。这种注释主要是为支持JDK工具javadoc而采用的。javadoc能识别注释中用标记@标识的一些特殊变量,并把doc注释加入它所生成的HTML文件。


    评论

    # re: java中goto语句解析12  回复  更多评论   

    2007-04-10 17:23 by 没所谓
    这段代码是我们公司的一段极相似, 而且照常运行,

    # re: java中goto语句解析12  回复  更多评论   

    2007-08-22 19:58 by sisi
    能不能请楼主解释下,为什么上面的程序会出现使用goto语句的情况?还有,到底在java中可不可以使用goto语句?

    # re: java中goto语句解析12  回复  更多评论   

    2008-02-05 17:56 by wl
    因为这个代码是用反编译得来的。

    # re: java中goto语句解析12  回复  更多评论   

    2008-03-03 15:30 by vanslyke
    碰到过类似问题
    源代码中是不存在goto的
    是反编译出来的结果

    # re: java中goto语句解析12  回复  更多评论   

    2008-08-26 18:01 by
    确实是反编译的结果,JAVA中如果有GOTO语法那就是新闻了.

    # re: java中goto语句解析12[未登录]  回复  更多评论   

    2008-09-18 09:40 by test
    你这篇goto的“解析”应该叫替代goto的方法,文不对题

    # re: java中goto语句解析12  回复  更多评论   

    2008-09-25 11:43 by 小宁
    不明白GOTO的请不要乱参与发表意见啊
    菜鸟才不会用
    Java 中虽然没有GOTO 关键字
    但是依然保留了用法
    好的GOTO语句不仅仅可以使程序变的更加灵活
    也可以做一些BREAK,CONTINUE所做不到的!
    菜鸟不用并不代表高手不用!

    # re: java中goto语句解析12  回复  更多评论   

    2013-03-15 11:38 by chn
    饿。。。我反编译了代码里面很多的goto.但是我想问的是怎么让他们编译通过?@小宁

    只有注册用户登录后才能发表评论。


    网站导航: