Все после моего оператора попытки должны быть охвачены в том операторе попытки к переменным доступа в нем?

Я изучаю Java и одну вещь, я нашел, что мне не нравится, обычно, когда у меня есть код как это:

import java.util.*;
import java.io.*;

public class GraphProblem
{
    public static void main(String[] args)
    {
        if (args.length < 2)
        {
            System.out.println("Error: Please specify a graph file!");
            return;
        }


        FileReader in = new FileReader(args[1]);
        Scanner input = new Scanner(in);

        int size = input.nextInt();
        WeightedGraph graph = new WeightedGraph(size);

        for(int i = 0; i < size; i++)
        {
            graph.setLabel(i,Character.toString((char)('A' + i)));
        }

        for(int i = 0; i < size; i++)
        {
            for(int j = 0; j < size; j++)
            {
                graph.addEdge(i, j, input.nextInt());
            }
        }

        // .. lots more code

    }
}

У меня есть неперехваченное исключение вокруг моего FileReader.

Так, я должен перенести его в выгоду попытки для ловли того определенного исключения. Мой вопрос, делает это try { } должны охватить все после этого в моем методе, который хочет использовать или мой FileReader (в) или мой Сканер (вход)?

Если я не переношу целый остаток от программы в том операторе попытки, то что-либо за пределами него не может получить доступ в/вводить том, потому что это май не инициализированный или было инициализировано за пределами его объема. Таким образом, я не могу изолировать выгоду попытки, чтобы просто сказать часть, которая инициализирует FileReader, и закройте оператор попытки сразу после этого.

Так, действительно ли это - "лучшая практика", чтобы иметь оператор попытки, переносящий все части кода, которые идут в переменные доступа, инициализированные в нем?

Спасибо!

7
задан Nathan Hughes 24 April 2014 в 17:02
поделиться

7 ответов

Да и нет. Try инициирует свою собственную локальную область видимости, поэтому, когда вы делаете это:

try
{
   FileReader reader = new FileReader(args[1]);

   // Stuff
}
catch(Exception e) { }

Переменная reader видна только в пределах ограничений блока try {}. Это предпочтительное поведение. Если вы хотите использовать его вне (в случае файлового ввода-вывода это не рекомендуется), вам необходимо объявить его вне try / catch. Подходящим примером может быть флаг:

boolean isValidFile = false;
try
{
   FileReader reader = new FileReader(args[1]);

   // Do Stuff

   isValidFile = true;
}
catch(Exception e)
{
   // Handle Errors
}

System.out.print("Valid File: ");
System.out.println(isValidFile);
0
ответ дан 6 December 2019 в 19:34
поделиться

Если вы только учитесь, ваш метод может генерировать исключение. Однако это не лучший способ обработки исключений, если вы только учитесь, вы, вероятно, захотите больше сосредоточиться на логике того, что делает ваш код. Как только вы освоитесь с этим, вы сможете изучить правильную обработку исключений.

Ваш код должен выглядеть следующим образом, и вам не придется беспокоиться об операторах try / catch:

public class GraphProblem {
    public static void main(String[] args) throws Exception {
        //your code
    }
}

Опять же, это не лучшая практика, но она позволяет вам сосредоточиться на бизнес-логике, а не на обработке ошибок. . Как только вы освоитесь с бизнес-логикой, вы сможете углубиться в обработку исключений, которая является отдельной темой.

0
ответ дан 6 December 2019 в 19:34
поделиться

Если вас устраивает , а не , заключающий код после конструктора FileReader, вы можете объявить FileReader вне блок try / catch, например:

FileReader fr = null;
try
{
    fr = new FileReader(args[1]);
}
catch (IOException e)
{
    // handle
}
// code that uses fr

Это разумный дизайн, и я часто его использую. Убедитесь, что вы правильно обрабатываете в следующем коде возможность того, что fr имеет значение NULL (т.е. конструктор сгенерировал исключение).

9
ответ дан 6 December 2019 в 19:34
поделиться

Это не проблема с блоками try / catch как таковыми. Проблема заключается в области видимости переменной и в том, что у вас должен быть блок try / catch из-за отмеченного исключения и, таким образом, установить новую область.

У вас также есть другой вариант - объявить проверенное исключение (я) как выбрасывает из вашего метода.

public static void main(String[] args) throws IOException {
    // ...code here...
}

Это совершенно законно для метода main .

Если вы все же хотите обработать исключение, как это должно происходить в более крупной программе. Вы можете определить конкретную попытку / поймать вокруг проблемного блока кода и использовать переменную вне области видимости, объявив переменную вне этой области, как многие ответили:

FileReader fr = null; // must be initialized here if the exception handling code 
                      // does not exit the method
try {
    fr = new FileReader(fileName);
} catch (IOException ex) {
    // log, print, and/or return
    // if you return or exit here then subsequent code can assume that fr is valid
}

Вы также можете переместить код в другой метод, который имеет дело с исключением:

private static FileReader openReader(String fileName) {
    try {
        return new FileReader(fileName);
    } catch (IOException ex) {
        // log/print exception
        return null; // caller must then expect a null
        // or
        throw new RuntimeException(...); // throw a RuntimeException of some kind (may not be good practice either)
    }
}

Вы также можете переместить код обработки файла в другой метод. Это может быть лучше и позволит вам более правильно следить за открытием / закрытием в идиоме finally:

FileReader fr = null;
try {
    fr = new FileReader(fileName);
    Scanner input = new Scanner(fr);

    processInput(input);
} catch (IOException ex) {
    // log/print exception
} finally {
    if (fr != null) {
        try {
            fr.close();
        } catch (IOException ex) {
            // empty
        }
    }
}

private static void processInput(Scanner in) throws IOException {
    // ...processing here
}

Для закрытия вы можете использовать стороннюю библиотеку (Apache File Utils) или написать простой метод для обеспечения статического безопасного закрытия метод, который не генерирует исключений.

Вам действительно следует подумать о разбиении больших методов на более мелкие единицы, и это часто также предоставит вам гораздо более ясный способ обработки исключений.

4
ответ дан 6 December 2019 в 19:34
поделиться

Вы обязательно должны следовать приведенному выше шаблону. Если я помню прямо из моего изучения SCJP, компилятор не пытается оптимизировать все, что находится в блоке try, поэтому вы должны попробовать-поймать на самом низком возможном уровне.

-2
ответ дан 6 December 2019 в 19:34
поделиться

Нет. Вы можете объявить это следующим образом:

FileReader in = null;
Scanner input = null;

try {
   in = new FileReader(args[1]);
   input = new Scanner(in);
} catch(IOException ioe) {
   //
}
2
ответ дан 6 December 2019 в 19:34
поделиться

Локальные переменные, объявленные в блоке , привязаны к этому блоку.

Итак, является ли «лучшей практикой», чтобы оператор try обертывал все части кода, которые будут обращаться к инициализированным в нем переменным?

В общем, вам следует попытаться минимизировать область видимости ваших переменных до сделайте их как можно более узкими. Это описано, среди прочего, в Эффективная Java и Code Complete .

Этот вид кода является рецептом для NullPointerExceptions :

FileReader in = null;
try {
  in = new FileReader(filename);
} catch(IOException e) {
  //handle error, but now what?
}
// Code that needs "in", but what if it is null
// because of a FileNotFoundException?
// This code is junk.

Практически все объявления локальных переменных должны включать присваивание.

FileReader in = new FileReader(filename);

Если вы будете следовать этому практическому правилу, вы получите лучший код.


// .. lots more code

Если у вас есть гигантские операторы try / catch, похоже, что ваши методы слишком велики. Это проблема организации кода, а не что-то конкретное, связанное с try / catch.

  public static void main(String[] args) {
    if (args.length < 1) {
      System.out.println("Error: Please specify a graph file!");
      return;
    }
    try {
      processGraphFile(args[0]);
    } catch (IOException e) {
      // Deal with error
    }
  }

  private static void processGraphFile(String filename) throws IOException {
    FileReader in = new FileReader(filename);
    try {
      Scanner scanner = new Scanner(in);
      processGraph(scanner);
      if (scanner.ioException() != null) {
        throw scanner.ioException();
      }
    } finally {
      in.close();
    }
  }

  //other methods

В стороне:

  • Обратите внимание, что массивы Java начинаются с индекса 0 , а не 1
  • FileReader удобен при обучении, но обычно избежать из-за проблем с кодировкой; это вряд ли будет проблемой, пока код не покинет вашу машину
0
ответ дан 6 December 2019 в 19:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: