Подтвердить что ты не робот

Можно ли завершить работу после вызова конструктора, создающего исключение?

Есть ли какие-либо сведения о том, очищен ли объект с помощью finalize(), если этот конструктор объекта исключает.

Когда этот метод вызывается, как известно, плохо определено. Согласно руководству:

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

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize%28%29

Я не смог запустить метод finalize таким образом. Кто-нибудь знает, является ли он безоговорочным, чтобы не быть вызванным или если он в некоторых случаях вызван после того, как конструктор не смог инициализировать объект (thew исключение).

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

4b9b3361

Ответ 1

Мой тест показывает, что он может

public class Test1 {

    Test1() {
        throw new RuntimeException();
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalized");
    }

    public static void main(String[] args) throws Exception {
        try {
            new Test1();
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        System.gc();
        Thread.sleep(1000);
    }
}

печатает

java.lang.RuntimeException
    at test.Test1.<init>(Test1.java:13)
    at test.Test1.main(Test1.java:24)
finalized

находится на Java HostSpot Client VM 1.7.0_03

Ответ 2

Согласно разделу 12.6.1. Внедрение Завершения JLS:

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

Если ваш конструктор создает исключение после завершения конструктора Object, ваш объект должен быть финализирован, поэтому finalize() все равно можно вызвать.

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

Ответ 3

Чтобы продемонстрировать более четко:

public class Test1 {

    public static class LifeBoat extends RuntimeException
    {
        private Test1 passenger;
        public Test1 getPassenger(){return passenger;}
        public LifeBoat(Test1 passenger){this.passenger=passenger;}
    }

    Test1() {
        super(); //once this is finished, there is an Object to GC per JLS 12.6.1. 
        throw new LifeBoat(this);
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalized");
    }

    public static void main(String[] args) throws Exception {
        try {
            new Test1();
        } catch (LifeBoat e) {
            Test1 obj;
            obj=e.getPassenger();
            System.out.println(obj);
        }
        System.gc();
        Thread.sleep(1000);
    }
}

печатает

java.lang.RuntimeException
    at test.Test1.<init>(Test1.java:13)
    at test.Test1.main(Test1.java:24)
[email protected]
finalized