В Java, как лучше продолжать вызывать функцию до тех пор, пока не будет выдано исключение? - PullRequest
5 голосов
/ 29 октября 2009

В моем Java-коде у меня есть функция с именем getAngle(), которая иногда выдает NoAngleException. Является ли следующий код лучшим способом написания функции, которая продолжает вызывать getAngle() до тех пор, пока не будет выдано исключение?

public int getAngleBlocking()
{
    while(true)
    {
        int angle;
        try
        {
            angle = getAngle();
            return angle;
        }
        catch(NoAngleException e)
        {

        }
    }
}

Или было бы лучше переписать getAngle(), чтобы вернуть NaN при ошибке?

Ответы [ 8 ]

9 голосов
/ 29 октября 2009

Я удивлен, прочитав некоторые ответы на эту тему, потому что именно этот сценарий является причиной существования проверенных исключений. Вы можете сделать что-то вроде:

private final static int MAX_RETRY_COUNT = 5;

//...

int retryCount = 0;
int angle = -1;

while(true)
{
    try
    {
        angle = getAngle();
        break;
    }
    catch(NoAngleException e)
    {
        if(retryCount > MAX_RETRY_COUNT)
        {
            throw new RuntimeException("Could not execute getAngle().", e);
        }

        // log error, warning, etc.

        retryCount++;
        continue;
    }
}

// now you have a valid angle

Это предполагает, что что-то вне процесса тем временем изменилось. Как правило, что-то вроде этого будет сделано для повторного подключения:

private final static int MAX_RETRY_COUNT = 5;

//...

int retryCount = 0;
Object connection = null;

while(true)
{
    try
    {
        connection = getConnection();
        break;
    }
    catch(ConnectionException e)
    {
        if(retryCount > MAX_RETRY_COUNT)
        {
            throw new RuntimeException("Could not execute getConnection().", e);
        }

        try
        {
            TimeUnit.SECONDS.sleep(15);
        }
        catch (InterruptedException ie)
        {
            Thread.currentThread().interrupt();
            // handle appropriately
        }

        // log error, warning, etc.

        retryCount++;
        continue;
    }
}

// now you have a valid connection
5 голосов
/ 29 октября 2009

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

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

3 голосов
/ 30 октября 2009

Не могли бы вы использовать рекурсию? то есть;.

public int getAngleBlocking()
{
        int angle;
        try
        {
                angle = getAngle();
                return angle;
        }
        catch(NoAngleException e)
        {
               return getAngleBlocking();
        }
    }
}
3 голосов
/ 29 октября 2009

Вы хотите вызывать метод, если он вызывает исключение?

Это не программирование. Вы должны использовать отладчик и взглянуть на реальную проблему.

И вы никогда не должны ловить исключение без каких-либо сообщений или регистрации!

1 голос
/ 30 октября 2009

В итоге я решил вернуть значение NaN, так как это предотвращает небрежное использование Integer.MIN_VALUE где-то еще.

public float getAngle(boolean blocking)
{
    while(true)
    {
        int dir = getDirection();
        if(dir == 0 && !blocking)
            return Float.NaN;
        else
            return (dir - 5) * 30;
    }
}
1 голос
/ 29 октября 2009

Я бы не рекомендовал делать это таким образом, потому что когда getAngle () никогда не возвращает действительное значение (по какой-то причине всегда выдает исключение), вы попадаете в бесконечный цикл. Вы должны по крайней мере определить условие перерыва (например, время ожидания) для этого случая.

0 голосов
/ 29 октября 2009

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

Иногда, конечно, это невозможно либо потому, что класс не ваш, либо невозможно двойное использование возвращаемого типа в качестве результата или состояния ошибки.

Например, в вашем случае, предполагая, что все целые (отрицательные и 0) градусы являются возможными углами, вы не сможете вернуть значение типа int, которое указывает на ошибку и отличается от действительного значения угла.

Но давайте предположим, что ваши действительные углы находятся в диапазоне -360 -> 360 (или эквивалент в радианах). Тогда вы действительно должны рассмотреть что-то вроде:

// assuming this ..
public static final int NO_ANGLE_ERROR = Integer.MIN_VALUE; 

// do this
public int getAngleBlocking()
{
    int angle;
    do {
       angle = getAngle();
    }while(angle == NO_ANGLE_ERROR);
}
0 голосов
/ 29 октября 2009

Никогда не используйте исключения для обработки логики в вашем коде.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...