Nắm bắt nhiều ngoại lệ trong Java-8


71

Trong khi thử tính năng đa bắt tôi thấy trong m1()phương pháp của mình, mọi thứ đều hoạt động tốt như mong đợi.

Tuy nhiên, trong m2()cùng một mã không biên dịch. Tôi vừa thay đổi cú pháp để giảm số lượng dòng mã.

public class Main {

    public int m1(boolean bool) {
        try {
            if (bool) {
                throw new Excep1();
            }
            throw new Excep2();
            //This m1() is compiling  abs fine.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    public int m2(boolean b) {
        try {
            throw b ? new Excep1() : new Excep2();
            //This one is not compiling.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    private static interface I {
    }

    private static class Excep1 extends Exception implements I {
    }

    private static class Excep2 extends Exception implements I {
    }
}

Tại sao không m2()biên dịch phương thức ?


22
Bạn đang nhận được lỗi biên dịch nào?
Gavin

Câu trả lời:


79

Loại biểu thức

b ? new Excep1() : new Excep2()

Exception, vì đó là siêu kiểu phổ biến của Excep1Excep2.

Tuy nhiên, bạn không nắm bắt được Exception, vì vậy trình biên dịch phàn nàn về nó.

Nếu bạn bắt Exception, nó sẽ vượt qua quá trình biên dịch:

public int m2(boolean b) {
    try {
        throw b ? new Excep1() : new Excep2();
    } catch (Exception e) {
        return 0;
    }
}

Tôi đã cố gắng tìm mục JLS giải thích loại biểu thức ternary có điều kiện trong ví dụ của bạn.

Tất cả những gì tôi có thể tìm thấy là biểu thức cụ thể này là 15.25.3. Tham khảo biểu thức điều kiện .

Tôi không hoàn toàn chắc chắn nếu nó được tính là biểu thức poly hoặc biểu thức độc lập. Tôi nghĩ đó là độc lập (vì các biểu thức poly liên quan đến bối cảnh chuyển nhượng hoặc bối cảnh gọi và tôi không nghĩ rằng một throwcâu lệnh được tính là một trong hai biểu thức đó).

Đối với biểu thức độc lập: "Nếu toán hạng thứ hai và thứ ba có cùng loại (có thể là loại null), thì đó là loại của biểu thức điều kiện."

Trong trường hợp của bạn, thứ hai và toán hạng thứ ba có ba loại phổ biến - Object, ThrowableException- kiểu của biểu thức phải là một trong hai nước này, từ đó, "Các biểu trong một tuyên bố ném phải một trong hai biểu thị một biến hoặc giá trị của một loại tài liệu tham khảo có thể gán (§5.2) cho loại Có thể ném được. "

Dường như trình biên dịch chọn loại phổ biến cụ thể nhất ( Exception) và do đó sẽ catch (Exception e)giải quyết được lỗi biên dịch.

Tôi cũng đã cố gắng thay thế hai ngoại lệ tùy chỉnh của bạn bằng hai lớp con IOException, trong trường hợp đó sẽ catch (IOException e)giải quyết lỗi biên dịch.


11
@Smile loại biểu thức điều kiện ternary phải phổ biến cho cả hai toán hạng 2 và 3. Do đó, nó không thể Excep1hoặc Excep2. Nó chỉ có thể được Exception.
Eran

2
Điểm đạn cuối cùng trong 15.25.3 có câu trả lời: "Mặt khác, toán hạng thứ hai và thứ ba lần lượt là loại S1 và S2. Gọi T1 là loại kết quả từ việc áp dụng chuyển đổi quyền anh sang S1 và để T2 là loại kết quả từ việc áp dụng chuyển đổi quyền anh sang S2. Loại biểu thức có điều kiện là kết quả của việc áp dụng chuyển đổi bắt giữ (§5.1.10) sang mỡ (T1, T2). " Đây là Least Upper Bound, đây là siêu kiểu phổ biến gần nhất mà hai loại biểu thức chia sẻ.
amalloy

22

Bạn đang nhầm lẫn trình biên dịch với dòng này:

throw b ? new Excep1() : new Excep2();

Trình biên dịch thấy rằng kết quả của biểu thức (ở bên trái của cú ném) là siêu hạng phổ biến giữa Ngoại trừ1 và Ngoại trừ 2, là Ngoại lệ, và do đó loại hiệu quả mà bạn đang ném trở thành Ngoại lệ. Câu lệnh bắt không thể nhận ra rằng bạn đang cố gắng ném Ex8051 hoặc Ngoại trừ2.


4

Java hạn chế bạn bắt hoặc khai báo tất cả các loại ngoại lệ mà phương thức có thể ném,

Nó tìm kiếm cha mẹ chung cho cả hai (/ tất cả) Ngoại lệ và mong bạn bắt hoặc khai báo là ném, ví dụ nếu Excep1kéo dài, Throwablebạn cũng sẽ phải bắt

Trong trường hợp đầu tiên, Java chắc chắn rằng bạn đang ném Excep1hoặcExcep2

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.