Как мне выполнить цикл, если в java есть исключение? [Дубликат]

Компиляция программы на C ++ выполняется в несколько этапов, как указано в 2.2 (кредиты для Кейта Томпсона для ссылки) :

Превалирование среди правил синтаксиса

  1. Физические символы исходного файла сопоставляются в соответствии с реализацией в соответствии с базовым набором символов источника (ввод символов новой строки для индикаторов конца строки) при необходимости. [SNIP]
  2. Каждый экземпляр символа обратной косой черты (\), за которым сразу следует символ новой строки, удаляется, сплайсируя физические исходные строки для формирования логических строк источника. [SNIP]
  3. Исходный файл разбивается на токены предварительной обработки (2.5) и последовательности символов пробела (включая комментарии). [SNIP]
  4. Выполнены предпроцессорные директивы, макро-вызовы разворачиваются и выполняются операторные выражения _Pragma. [SNIP]
  5. Каждый элемент набора символов в символьном литерале или строковый литерал, а также каждая escape-последовательность и универсальное имя-символа в символьном литерале или не- -raw строковый литерал, преобразуется в соответствующий член набора символов выполнения; [SNIP]
  6. Соединительные маркеры литералов строки объединены.
  7. Символы пробела, разделяющие токены, уже не являются значимыми. Каждый токен предварительной обработки преобразуется в токен. (2.7). Результирующие маркеры синтаксически и семантически анализируются и переводятся как единица перевода. [SNIP]
  8. Устанавливаемые единицы перевода и единицы экземпляра объединяются следующим образом: [SNIP]
  9. Все ссылки на внешние сущности решена. Компоненты библиотеки связаны для удовлетворения внешних ссылок на объекты, не определенные в текущем переводе. Весь такой переводчик выводится в образ программы, который содержит информацию, необходимую для выполнения в среде выполнения. (акцент мой)

[footnote] Реализации должны вести себя так, как если бы эти отдельные фазы происходили, хотя на практике различные фазы могли быть свернуты вместе.

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

Скажите, что вы определили символ a в a.cpp. Теперь b.cpp объявил этот символ и использовал его. Перед связыванием он просто предполагает, что этот символ был определен где-то , но он пока не заботится о том, где. Фаза связывания отвечает за поиск символа и правильную привязку его к b.cpp (ну, собственно, к объекту или библиотеке, которая его использует).

Если вы используете Microsoft Visual Studio, вы будете см., что проекты генерируют файлы .lib. Они содержат таблицу экспортированных символов и таблицу импортированных символов. Импортированные символы разрешены против библиотек, на которые вы ссылаетесь, и экспортированные символы предоставляются для библиотек, которые используют этот .lib (если есть).

Подобные механизмы существуют для других компиляторов / платформ.

Общие сообщения об ошибках: error LNK2001, error LNK1120, error LNK2019 для Microsoft Visual Studio и undefined reference to symbolName для GCC.

Код:

struct X
{
   virtual void foo();
};
struct Y : X
{
   void foo() {}
};
struct A
{
   virtual ~A() = 0;
};
struct B: A
{
   virtual ~B(){}
};
extern int x;
void foo();
int main()
{
   x = 0;
   foo();
   Y y;
   B b;
}

генерирует следующие ошибки с GCC:

/home/AbiSfw/ccvvuHoX.o: In function `main':
prog.cpp:(.text+0x10): undefined reference to `x'
prog.cpp:(.text+0x19): undefined reference to `foo()'
prog.cpp:(.text+0x2d): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD1Ev[B::~B()]+0xb): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD0Ev[B::~B()]+0x12): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1Y[typeinfo for Y]+0x8): undefined reference to `typeinfo for X'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1B[typeinfo for B]+0x8): undefined reference to `typeinfo for A'
collect2: ld returned 1 exit status

и аналогичные ошибки с Microsoft Visual Studio:

1>test2.obj : error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ)
1>test2.obj : error LNK2001: unresolved external symbol "int x" (?x@@3HA)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall A::~A(void)" (??1A@@UAE@XZ)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall X::foo(void)" (?foo@X@@UAEXXZ)
1>...\test2.exe : fatal error LNK1120: 4 unresolved externals

. Общие причины включают в себя:

138
задан Peter O. 18 October 2013 в 07:57
поделиться

16 ответов

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

 bigLoop:
 while(!stopFileExists()) {
    try {
      // do work
      break;
    }
    catch (ExpectedExceptionType e) {

       // could sleep in here, too.

       // another option would be to "restart" some bigger loop, like
       continue bigLoop;
    }
    // ... more work
}
223
ответ дан rogerdpack 26 August 2018 в 00:47
поделиться

Обязательное решение «enterpriseisy»:

public abstract class Operation {
    abstract public void doIt();
    public void handleException(Exception cause) {
        //default impl: do nothing, log the exception, etc.
    }
}

public class OperationHelper {
    public static void doWithRetry(int maxAttempts, Operation operation) {
        for (int count = 0; count < maxAttempts; count++) {
            try {
                operation.doIt();
                count = maxAttempts; //don't retry
            } catch (Exception e) {
                operation.handleException(e);
            }
        }
    }
}

И для вызова:

OperationHelper.doWithRetry(5, new Operation() {
    @Override public void doIt() {
        //do some stuff
    }
    @Override public void handleException(Exception cause) {
        //recover from the Exception
    }
});
39
ответ дан ach 26 August 2018 в 00:47
поделиться

Хотя try/catch в while хорошо известна и хорошая стратегия, я хочу предложить вам рекурсивный вызов:

void retry(int i, int limit) {
    try {

    } catch (SomeException e) {
        // handle exception
        if (i >= limit) {
            throw e;  // variant: wrap the exception, e.g. throw new RuntimeException(e);
        }
        retry(i++, limit);
    }
}
20
ответ дан AlexR 26 August 2018 в 00:47
поделиться

следующее мое решение с очень простым подходом!

               while (true) {
                    try {
                        /// Statement what may cause an error;
                        break;
                    } catch (Exception e) {

                    }
                }
0
ответ дан David Kayo 26 August 2018 в 00:47
поделиться

Как обычно, лучший дизайн зависит от конкретных обстоятельств. Обычно, я пишу что-то вроде:

for (int retries = 0;; retries++) {
    try {
        return doSomething();
    } catch (SomeException e) {
        if (retries < 6) {
            continue;
        } else {
            throw e;
        }
    }
}
31
ответ дан geisterfurz007 26 August 2018 в 00:47
поделиться

Здесь многоразовый и более общий подход для Java 8+, который не требует внешних библиотек:

public interface IUnreliable<T extends Exception>
{
    void tryRun ( ) throws T;
}

public static <T extends Exception> void retry (int retryCount, IUnreliable<T> runnable) throws T {
    for (int retries = 0;; retries++) {
        try {
            runnable.tryRun();
            return;
        } catch (Exception e) {
            if (retries < retryCount) {
                continue;
            } else {
                throw e;
            }
        }
    }
}

Использование:

@Test
public void demo() throws IOException {
    retry(3, () -> {
        new File("/tmp/test.txt").createNewFile();
    });
}
0
ответ дан Jonas_Hess 26 August 2018 в 00:47
поделиться

Ваш точный сценарий, обработанный через Failsafe :

RetryPolicy retryPolicy = new RetryPolicy()
  .retryOn(NearlyUnexpectedException.class);

Failsafe.with(retryPolicy)
  .onRetry((r, f) -> fix_the_problem())
  .run(() -> some_instruction());

Довольно просто.

8
ответ дан Jonathan 26 August 2018 в 00:47
поделиться

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

2
ответ дан Jordan Kaye 26 August 2018 в 00:47
поделиться

Я не уверен, что это «профессиональный» способ сделать это, и я не совсем уверен, что он работает на все.

boolean gotError = false;

do {
    try {
        // Code You're Trying
    } catch ( FileNotFoundException ex ) {
        // Exception
        gotError = true;
    }
} while ( gotError = true );
0
ответ дан Josh 26 August 2018 в 00:47
поделиться

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

Когда вы работаете с facebook Graph API в PHP вы иногда получаете сообщение об ошибке, но при повторном повторении одного и того же результата вы получите положительный результат (для различных магических причин Интернета, выходящих за рамки этого вопроса). В этом случае нет необходимости исправлять fix любую ошибку, но просто попробуйте еще раз, потому что произошла какая-то «ошибка facebook».

Этот код используется сразу после создания facebook session:

//try more than once because sometimes "facebook error"
$attempt = 3;
while($attempt-- > 0)
{
    // To validate the session:
    try 
    {
        $facebook_session->validate();
        $attempt = 0;
    } 
    catch (Facebook\FacebookRequestException $ex)
    {
        // Session not valid, Graph API returned an exception with the reason.
        if($attempt <= 0){ echo $ex->getMessage(); }
    } 
    catch (\Exception $ex) 
    {
        // Graph API returned info, but it may mismatch the current app or have expired.
        if($attempt <= 0){ echo $ex->getMessage(); }
    }
}

Кроме того, если число циклов for обращается в нуль ($attempt--), это довольно легко изменить количество попыток в будущем.

0
ответ дан KnightHawk 26 August 2018 в 00:47
поделиться

Вы можете использовать аннотации AOP и Java из jcabi-aspect (я разработчик):

@RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
  return url.openConnection().getContent();
}

Вы также можете использовать @Loggable и @LogException аннотаций.

14
ответ дан M-T-A 26 August 2018 в 00:47
поделиться

Используйте кнопку do-while для создания блока повторной попытки.

boolean successful = false;
int maxTries = 3;
do{
  try {
    something();
    success = true;
  } catch(Me ifUCan) {
    maxTries--;
  }
} while (!successful || maxTries > 0)
0
ответ дан Rahul Malhotra 26 August 2018 в 00:47
поделиться

Все попытки Try-Catch позволяют вашей программе терпеть неудачу изящно. В выводе catch вы обычно пытаетесь зарегистрировать ошибку и, возможно, откатите изменения, если вам нужно.

bool finished = false;

while(finished == false)
{
    try
    {
        //your code here
        finished = true
    }
    catch(exception ex)
    {
        log.error("there was an error, ex");
    }
}
0
ответ дан Sam I am 26 August 2018 в 00:47
поделиться

Большинство этих ответов по существу одинаковы. Моя тоже, но это форма, которую мне нравится

boolean completed = false;
Throwable lastException = null;
for (int tryCount=0; tryCount < config.MAX_SOME_OPERATION_RETRIES; tryCount++)
{
    try {
        completed = some_operation();
        break;
    }
    catch (UnlikelyException e) {
        lastException = e;
        fix_the_problem();
    }
}
if (!completed) {
    reportError(lastException);
}
6
ответ дан Stephen P 26 August 2018 в 00:47
поделиться

https://github.com/tusharmndr/retry-function-wrapper/tree/master/src/main/java/io

int MAX_RETRY = 3; 
RetryUtil.<Boolean>retry(MAX_RETRY,() -> {
    //Function to retry
    return true;
});
0
ответ дан tushar Mandar 26 August 2018 в 00:47
поделиться

Используйте петлю while с локальным флагом status. Инициализируйте флаг как false и установите его на true, когда операция успешна, например. ниже:

  boolean success  = false;
  while(!success){
     try{ 
         some_instruction(); 
         success = true;
     } catch (NearlyUnexpectedException e){
       fix_the_problem();
     }
  }

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

Если вы хотите повторить только определенное количество раз, используйте также счетчик:

  boolean success  = false;
  int count = 0, MAX_TRIES = 10;
  while(!success && count++ < MAX_TRIES){
     try{ 
         some_instruction(); 
         success = true;
     } catch (NearlyUnexpectedException e){
       fix_the_problem();
     }
  }
  if(!success){
    //It wasn't successful after 10 retries
  }

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

3
ответ дан Yogendra Singh 26 August 2018 в 00:47
поделиться
Другие вопросы по тегам:

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