Java: можно ли сделать try/catch короче?

Например:

try {
        Thread.sleep(333);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

Могу ли я каким-то образом использовать описанную выше попытку/поймать, используя созданный метод, такой как trySleep(Thread.sleep(333));, который будет делать то же самое, что и исходная попытка?

Пример использования:

public class Test implements Runnable {

    public Test() {
        Thread thisThread = new Thread(this);
        thisThread.start();
    }

    @Override
    public void run() {
        while (true){
            System.out.println("Testing");
            trySleep(Thread.sleep(333));
        }
    }

    public void trySleep(/*Thread object*/){
        //Code for try/catch
    }

    public static void main(String[] args) {
        new Test();
    }

}

Конечно, приведенный выше код не скомпилируется, это просто вопрос.

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


person FOD    schedule 05.04.2015    source источник
comment
По каким причинам вы не встраиваете это утверждение?   -  person Patrick McLaren    schedule 06.04.2015


Ответы (7)


Вы можете обернуть Thread.sleep в функцию, которая повторно выдает любое исключение как исключение времени выполнения (или любое неперехваченное исключение).

public static void trySleep(long millis) {
    try {
        Thread.sleep(millis);
    } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted during sleep", e);
    }
}
person axblount    schedule 05.04.2015
comment
Я всегда думал, что Thread.sleep должен быть в потоке, в котором он работает? Например, если вы назовете это в конструкторе Test(), это не сработает. - person FOD; 06.04.2015
comment
@FOD Когда вы вызываете trySleep изнутри run, вы вызываете его в текущем потоке. Неважно, где определена функция. - person axblount; 06.04.2015

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

Так что да.

Кстати: Вы написали бесконечный спящий цикл

person Christian Kuetbach    schedule 05.04.2015
comment
Я знаю, что это было бесконечно, это был просто быстрый пример, который я решил сделать, все остальное в этом примере было бы бессмысленным и не относящимся к делу. - person FOD; 06.04.2015
comment
Это не дает ответа на вопрос. Чтобы подвергнуть критике или запросить разъяснения у автора, оставьте комментарий под его публикацией. - person Harshal Patil; 06.04.2015
comment
@HarshalPatil: Часть о том, если вы добавите три строки в метод trySleep, была ответом. У меня возникла проблема с вопросом, потому что ответ был включен в вопрос. - person Christian Kuetbach; 06.04.2015
comment
О, я думал, что это просто комментарий в любом случае - person Harshal Patil; 07.04.2015

Да, вы можете это сделать, но не совсем так, как вы сейчас это описываете. Везде, где вы используете Thread.sleep(), вам придется поймать InterruptedException, поэтому вам придется заключить вызов в метод следующим образом:

public void trySleep(long ms) {
    try {
        Thread.sleep(ms);
    } catch (InterruptedException e) {
        e.printStackTrace(); //handle exception here
    }
}

Вы можете вызвать этот метод следующим образом: trySleep(333)

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

person midor    schedule 05.04.2015

Вы можете обернуть свой спящий код другим методом, как вы предложили.

public static void trySleep(Thread target, long millis){
    try{
        target.sleep(millis);
    } catch(InterruptedException e) {
         System.err.println("Exception Occurred while trying to sleep!");
    }
}

Вы, вероятно, должны сделать это, так как создание модульного кода — правильный путь.

person ankh-morpork    schedule 05.04.2015
comment
Параметр target является избыточным и вводит в заблуждение, поскольку Thread.sleep(...) — это статический метод, который переводит текущий поток в спящий режим. Для удобочитаемости статические методы не следует вызывать через ссылки на экземпляры. - person Mick Mnemonic; 06.04.2015

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

В вашем коде:

@Override
public void run() {
    while (true){
        System.out.println("Testing");
        trySleep(Thread.sleep(333));
    }
}

В частности, эта строка:

trySleep(Thread.sleep(333));

Вы в основном говорите

  • Вызовите метод Thread.sleep() со значением 333.

  • Какое бы значение ни возвращал Thread.sleep(), передайте его другому методу.

Но Javadocs скажем, это пустой метод.

Также в вашем коде:

public void trySleep(/*Thread object*/){
    //Code for try/catch
}

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

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

person Water    schedule 05.04.2015

Вы можете использовать лямбда-выражения java 8, чтобы сделать что-то похожее на это:

@FunctionalInterface
interface InterruptedExceptionRunnable {
    void run() throws InterruptedException;
}

void trySleep(InterruptedExceptionRunnable exRunnable) {
    try {
        exRunnable.run();
    } catch(InterruptedException ex) {
        ex.printStackTrace();
    }
}

что позволяет вам написать это:

trySleep(()->Thread.sleep(333));
person fabian    schedule 05.04.2015

Да, вы можете сделать это с помощью лямбда-выражений Java 8.

class Example {
    @FunctionalInterface
    interface InterruptableRunnable {
        void run() throws InterruptedException;
    }

    static void tryRun(InterruptableRunnable r) {
        try {
            r.run();
        } catch(InterruptedException ie) {
            ie.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                // passing a lambda
                tryRun( () -> Thread.sleep(333) );
            }
        });

        t.start();
        // passing a method reference
        tryRun(t::join);
    }
}
person Radiodef    schedule 05.04.2015