扫描仪对象在while和do-while中

时间:2016-03-30 21:40:17

标签: java

我从github获得了这段代码,我决定在我的代码中使用do-while语法。原始代码没有错误或警告,但我的代码确实如此。

原始

<?php
//used for benchmarking
$time_start = microtime(true); 
require_once 'db.php';

//get the users location
$location = $_GET['location'];

                //check the users location is valid
           if (checkLocation($location) == "found") {

                  echo "null";

            } else {
                //select all of the rows
                $SQLSelect = $odb -> query("SELECT * FROM `something`");
                    $array = array();
                    $count = 0;
                    while ($show = $SQLSelect -> fetch(PDO::FETCH_ASSOC)) {
                        $distance = getDistance($location, $show['location']);
                            $distance = $distance * 0.000621371192;

                                        //narrow down the distance
                                        if ($distance < 100) {

$array[$count] = array();
$array[$count]['name'] = $show['locationName'];
$array[$count]['spec'] = $show['spec'];
$array[$count]['distance'] = round($distance);
                                        $count = $count + 1;
                                        }
                    }
                    //sort the array based on distance
usort($array,function($a,$b) {return strnatcasecmp($a['distance'],$b['distance']);});
                    echo json_encode($array);
            }


              function getDistance($start, $end) {
                    $from = $start;
                    $to = $end;
                    $from = urlencode($from);
                    $to = urlencode($to);

                    $data = file_get_contents("http://maps.googleapis.com/maps/api/distancematrix/json?origins=$from&destinations=$to&language=en-EN&sensor=false");

                    $data = json_decode($data);
                    $time = 0;
                    $distance = 0;
                    foreach($data->rows[0]->elements as $road) {
                    $time += $road->duration->value;
                    $distance += $road->distance->value;
                    }

                    return $distance;
                    }



                    function checkLocation($start) {
                    $from = $start;
                    $to = 'location1';
                    $from = urlencode($from);
                    $to = urlencode($to);

                    $data = file_get_contents("http://maps.googleapis.com/maps/api/distancematrix/json?origins=$from&destinations=$to&language=en-EN&sensor=false");
                    if (strpos($data, '"status" : "NOT_FOUND"') !== false) {
                    return "found";
                        } else {
                            return "null";
                        }
                }

                    echo '</br>Total execution time in seconds: ' . (microtime(true) - $time_start);        
?>

在我的代码中

public static char getChar(){
    char input = 0;
    Scanner keyIn;
    boolean notValid = true;
    while(notValid){
        keyIn = new Scanner(System.in);  //no warning
        try{
            input = keyIn.nextLine().charAt(0);
            notValid = false;
        }catch(InputMismatchException e){
            System.err.print("Input Error - Non-Character\n");
            System.err.print("Enter Again:\n");
        }
    }
    return input;
}

就原始代码不需要public static char setOperend(){ char operand = 0; Scanner keyIn; boolean notValid = true; do{ keyIn = new Scanner(System.in); //warning:Resource leak: 'keyIn' is never closed try{ operand= keyIn.nextLine().charAt(0); notValid = false; }catch(InputMismatchException e){ System.err.print("애러 : 문자가 아닙니다."); System.err.print("다시 입력하세요."); } }while(notValid ); return operand; } (这也让我感到困惑)这一事实而言,我想这是因为当do-while首先执行时,编译器知道它在没有任何条件的情况下执行认为必须关闭,而原件有条件检查,可能不需要关闭(如果条件从未满足)。但他们两个对我来说都是一样的。因为original有这行keyIn.close(),所以它至少应该执行一次。

  • 为什么boolean notValid = true;不需要whileclose()会这样做。
  • do-while是否必要?

3 个答案:

答案 0 :(得分:1)

正如其他人所指出的那样,你在第二个例子中得到警告的原因是编译器可以确定循环将至少执行一次,从而创建扫描器。在第一个版本中,编译器只是注意到如果变量不为真,则while循环可能不会发生(尽管在这种情况下它显然是)。

其他人(我认为错误地)指出你总是关闭扫描仪。当您的扫描仪包含在System.in中时,这通常不是一个好主意,因为这将关闭System.in:

  

当扫描仪关闭时,如果源实现了Closeable接口,它将关闭其输入源。    Oracle Java Documentation - Scanner

由于System.in is an InputStream implements the Closeable interface,这意味着您将无法再次收到用户的任何输入 - 可能不是您想要的。

至于解决方案,我会做以下事情:

public static char setOperend(){    
    @SuppressWarnings("resource") // We don't want to close System.in
    Scanner keyIn = new Scanner(System.in);
    boolean notValid = true;
    char operand = 0;

    do{             
        try{
            operand= keyIn.nextLine().charAt(0);
            notValid = false;
        }catch(InputMismatchException e){
            System.err.print("애러 : 문자가 아닙니다.");
            System.err.print("다시 입력하세요.");
        }
    }while(notValid );

    return operand;
}

这样可以在不需要在System.in上调用close()的情况下处理警告。它还解决了代码中的“问题”,即为循环的每次迭代创建Scanner的新实例,这是不必要的(坦率地说非常难看)。

答案 1 :(得分:0)

您没有收到原始代码警告的原因是编译器认为循环可能永远不会发生,因为它依赖于变量。但是,使用do-while循环时,循环中的代码总是至少运行一次,这就是它发生的原因。如果将其设置为while(true),您将收到相同的警告。

<强>原始 这两种方式都应该调用close() 更新不应按@BadCash

的说明调用close()

答案 2 :(得分:0)

如果此扫描仪尚未关闭,请使用close(),确保扫描仪已关闭,但如果此扫描仪已关闭,则设置此方法将无效。

并且不需要将new Scanner(System.in)调用到循环中,例如:每次执行nextLine()时,它都会执行新的Scanner!