ChuckNorrisException không thể so sánh được


596

Có thể xây dựng một đoạn mã trong Java để làm cho một giả thuyết java.lang.ChuckNorrisExceptionkhông thể so sánh được không?

Những suy nghĩ nảy ra trong đầu đang sử dụng ví dụ đánh chặn hoặc lập trình hướng theo khía cạnh .



2
bằng cách sử dụng đề xuất từ ​​liên kết @jschoen đã cung cấp (vô hiệu hóa trình xác minh mã byte), bạn có thể ném thứ gì đó không mở rộng Ném được! được mô tả trong câu trả lời của tôi dưới đây.
jtahlborn

4
Đoạn trích từ câu trả lời của aioobe tổng hợp câu hỏi @jschoen được liên kết khá tốt: "Tức là, câu hỏi của bạn có thể được hiểu là 'Nếu một JVM đi chệch khỏi đặc tả, thì nó có thể làm những điều kỳ lạ như ném mồi" và câu trả lời là tất nhiên, Đúng."
Dan đang loay hoay bởi Firelight

2
@Max - Bạn có thể giải thích về cách sử dụng thực tế cho việc này không?
Vineet Bhatia

3
Làm thế nào về một ngoại lệ mà suy nghĩ lại về chính nó finalize()?
Lie Ryan

Câu trả lời:


314

Tôi đã không cố gắng này, vì vậy tôi không biết nếu JVM sẽ hạn chế một cái gì đó như thế này, nhưng có lẽ bạn có thể biên dịch mã mà ném ChuckNorrisException, nhưng trong thời gian chạy cung cấp một định nghĩa lớp ChuckNorrisExceptionkhông mở rộng Throwable .

CẬP NHẬT:

Nó không hoạt động. Nó tạo ra một lỗi xác minh:

Exception in thread "main" java.lang.VerifyError: (class: TestThrow, method: ma\
in signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestThrow.  Program will exit.

CẬP NHẬT 2:

Trên thực tế, bạn có thể làm cho nó hoạt động nếu bạn vô hiệu hóa trình xác minh mã byte! ( -Xverify:none)

CẬP NHẬT 3:

Đối với những người theo dõi từ nhà, đây là kịch bản đầy đủ:

Tạo các lớp sau:

public class ChuckNorrisException
    extends RuntimeException // <- Comment out this line on second compilation
{
    public ChuckNorrisException() { }
}

public class TestVillain {
    public static void main(String[] args) {
        try {
            throw new ChuckNorrisException();
        }
        catch(Throwable t) {
            System.out.println("Gotcha!");
        }
        finally {
            System.out.println("The end.");
        }
    }
}

Biên dịch các lớp:

javac -cp . TestVillain.java ChuckNorrisException.java

Chạy:

java -cp . TestVillain
Gotcha!
The end.

Nhận xét "mở rộng RuntimeException" và chỉ biên dịch lạiChuckNorrisException.java :

javac -cp . ChuckNorrisException.java

Chạy:

java -cp . TestVillain
Exception in thread "main" java.lang.VerifyError: (class: TestVillain, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestVillain.  Program will exit.

Chạy mà không cần xác minh:

java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"

18
OK, vậy nếu bạn bắt Objectthay vì Throwablevậy thì sao? (Trình biên dịch sẽ không cho phép nhưng vì chúng tôi đã vô hiệu hóa trình xác minh, nên có thể người ta có thể hack mã byte để làm điều đó.)
Ilmari Karonen

11
Theo những gì bạn có thể ném trong Java, bạn vẫn có thể bắt được những thứ không thể mở rộng được, nhưng ném và bắt chúng là hành vi không xác định.
VoliverseDream

8
@dzieciou Họ có thể đúng với nhau. Bạn có thể bắt chúng bằng phiên bản môi trường Java của bạn trên phiên bản cụ thể của hệ điều hành trên loại bộ xử lý của bạn. Nhưng nếu nó không được chỉ định trong tiêu chuẩn liệu nó có thể bị bắt hay không, thì nó được gọi là hành vi không xác định, bởi vì các triển khai khác của Java có thể chọn làm cho nó không thể bắt được.
heinrich5991

2
Hừm. Tôi đã hy vọng rằng với 176 lượt upvote, bạn đã viết một số mã JNI để vá toàn bộ ngăn xếp cuộc gọi để lấy lại ngoại lệ của bạn (dĩ nhiên là do ctor gọi).
kdgregory

3
Khi làm tất cả những điều này, bạn cũng nên đứng trên một chân, vỗ đầu và xoa bụng trong khi huýt sáo ...;);)
Glen Best

120

Sau khi suy nghĩ về điều này, tôi đã tạo thành công một ngoại lệ không thể so sánh được. Tôi đã chọn đặt tên cho nó JulesWinnfield, tuy nhiên, thay vì Chuck, bởi vì nó là một ngoại lệ của một đám mây hình nấm. Hơn nữa, nó có thể không chính xác như những gì bạn đã nghĩ, nhưng chắc chắn nó không thể bị bắt. Quan sát:

public static class JulesWinnfield extends Exception
{
    JulesWinnfield()
    {
        System.err.println("Say 'What' again! I dare you! I double dare you!");
        System.exit(25-17); // And you shall know I am the LORD
    }
}


public static void main(String[] args)
{       
    try
    {
        throw new JulesWinnfield();
    } 
    catch(JulesWinnfield jw)
    {
        System.out.println("There's a word for that Jules - a bum");
    }
}

Et voila! Không ngoại lệ.

Đầu ra:

chạy:

Hãy nói điều đó lại một lần! Tao thách mày! Tôi thách bạn hai lần!

Kết quả Java: 8

BUILD SUCCESSFUL (tổng thời gian: 0 giây)

Khi tôi có thêm một chút thời gian, tôi sẽ xem liệu tôi có thể nghĩ ra điều gì khác không.

Ngoài ra, hãy kiểm tra điều này:

public static class JulesWinnfield extends Exception
{
    JulesWinnfield() throws JulesWinnfield, VincentVega
    {
        throw new VincentVega();
    }
}

public static class VincentVega extends Exception
{
    VincentVega() throws JulesWinnfield, VincentVega
    {
        throw new JulesWinnfield();
    }
}


public static void main(String[] args) throws VincentVega
{

    try
    {
        throw new JulesWinnfield();
    }
    catch(JulesWinnfield jw)
    {

    }
    catch(VincentVega vv)
    {

    }
}

Gây ra lỗi tràn ngăn xếp - một lần nữa, các ngoại lệ vẫn chưa được xử lý.


32
+1 để sử dụng Stack Overflow trong câu trả lời của bạn. Đùa thôi, trả lời thực sự tốt.
Giô

7
Một "ngoại lệ không thể so sánh" thích hợp sẽ đảm bảo rằng tất cả các khối cuối cùng được bao quanh sẽ thực thi mà không có bất kỳ sự can thiệp nào. Giết hệ thống không ném ngoại lệ - nó chỉ giết chết hệ thống.
supercat

4
Làm thế nào để bạn "ném" JulesWinfield? Hệ thống sẽ không dừng lại trước khi nó bị ném?
supercat

6
@mikeTheLiar: Hệ thống thoát trong quá trình xây dựng, phải không? Tuyên bố throw new Whatever()thực sự là hai phần: Whatever it = new Whatever(); throw it;và hệ thống chết trước khi đến phần thứ hai.
supercat

5
@mikeTheLiar bạn thực sự có thể bắt Jules hoặc Vincent khá dễ dàng ... nếu bạn quản lý để ném nó. Thật dễ dàng để tạo một ngoại lệ mà bạn không thể ném:class cn extends exception{private cn(){}}
John Dvorak

85

Với một ngoại lệ như vậy rõ ràng sẽ bắt buộc phải sử dụng một System.exit(Integer.MIN_VALUE);từ hàm tạo bởi vì đây là điều sẽ xảy ra nếu bạn ném một ngoại lệ như vậy;)


32
+1; IMO đây là giải pháp khả thi duy nhất. Một ngoại lệ không thể so sánh là nên chấm dứt chương trình ...
nhà

7
Không, đó sẽ không phải là điều xảy ra khi bạn ném một ngoại lệ như vậy. Một ngoại lệ chưa được lưu sẽ chấm dứt một luồng duy nhất, nó sẽ không thoát khỏi jvm, trong một số bối cảnh System.exit thậm chí sẽ gây ra SecurityException - không phải mọi đoạn mã đều được phép tắt chương trình.
josefx

3
Bạn có thể sử dụng while(true){}thay vì System.exit().
Piotr Praszmo

2
thực tế, bạn có thể ngăn không cho System.exit()làm việc bằng cách cài đặt trình quản lý bảo mật không cho phép. điều đó sẽ biến hàm tạo thành một ngoại lệ khác (SecurityException), có thể bị bắt.
jtahlborn

5
Umm, về mặt kỹ thuật bạn không bao giờ ném một ngoại lệ. Bạn thậm chí chưa xây dựng đối tượng để ném!
Thomas Eding

46

Bất kỳ mã nào cũng có thể bắt được throwable. Vì vậy, không, bất kỳ ngoại lệ nào bạn tạo sẽ là một lớp con của Ném được và sẽ bị bắt.


11
Có thể hangném chính nó trong một nỗ lực để bắt ChuckNorrisException: P
PermGenError

35
public class ChuckNorrisException extends Exception {
    public ChuckNorrisException() {
        System.exit(1);
    }
}

(Cấp, về mặt kỹ thuật , ngoại lệ này không bao giờ thực sự bị ném, nhưng ChuckNorrisExceptionkhông thể ném đúng - nó sẽ ném bạn trước.)


4
Một đồng nghiệp của tôi đã đề nghị gắn bó 'cho (;;) {}' khi anh ta cảm thấy một cuộc gọi 'System.exit (1)' có thể tạo ra Ngoại lệ bảo mật. Tôi đang bầu chọn cái này cho sự sáng tạo!
Đường Phil

Tôi đồng ý với kết thúc câu trả lời của bạn. Không bao giờ gây rối với ChuckNorris, Ngoại lệ hay không.
Benj

28

Bất kỳ ngoại lệ nào bạn ném phải mở rộng Ném được, vì vậy nó luôn có thể bị bắt. Vì vậy, câu trả lời là không.

Nếu bạn muốn làm cho nó khó khăn để xử lý, bạn có thể ghi đè lên các phương pháp getCause(), getMessage(), getStackTrace(), toString()để ném nhau java.lang.ChuckNorrisException.


2
Hmm, bắt (throwable t) gọi bất kỳ phương thức nào hoặc làm đột biến đối tượng? Có thể gây ra một mệnh đề bắt để ném thêm một ngoại lệ để làm cho nó không thể.
Colton

1
Tôi nghĩ rằng catch(Throwable t)chỉ lưu trữ nó thành biến nên các đề xuất của tôi chỉ áp dụng trong khối tiếp theo khi người dùng muốn đối phó với ngoại lệ
mirelon

24

Câu trả lời của tôi dựa trên ý tưởng của @ jtahlborn, nhưng đó là một chương trình Java hoạt động hoàn toàn , có thể được đóng gói thành tệp JAR và thậm chí được triển khai đến máy chủ ứng dụng yêu thích của bạn như một phần của ứng dụng web .

Trước hết, hãy định nghĩa ChuckNorrisExceptionlớp để nó không bị lỗi JVM ngay từ đầu (Chuck thực sự thích làm hỏng JVMs BTW :)

package chuck;

import java.io.PrintStream;
import java.io.PrintWriter;

public class ChuckNorrisException extends Exception {

    public ChuckNorrisException() {
    }

    @Override
    public Throwable getCause() {
        return null;
    }

    @Override
    public String getMessage() {
        return toString();
    }

    @Override
    public void printStackTrace(PrintWriter s) {
        super.printStackTrace(s);
    }

    @Override
    public void printStackTrace(PrintStream s) {
        super.printStackTrace(s);
    }
}

Bây giờ đi đến Expendableslớp để xây dựng nó:

package chuck;

import javassist.*;

public class Expendables {

    private static Class clz;

    public static ChuckNorrisException getChuck() {
        try {
            if (clz == null) {
                ClassPool pool = ClassPool.getDefault();
                CtClass cc = pool.get("chuck.ChuckNorrisException");
                cc.setSuperclass(pool.get("java.lang.Object"));
                clz = cc.toClass();
            }
            return (ChuckNorrisException)clz.newInstance();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

Và cuối cùng là Mainlớp để đá mông:

package chuck;

public class Main {

    public void roundhouseKick() throws Exception {
        throw Expendables.getChuck();
    }

    public void foo() {
        try {
            roundhouseKick();
        } catch (Throwable ex) {
            System.out.println("Caught " + ex.toString());
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("before");
            new Main().foo();
            System.out.println("after");
        } finally {
            System.out.println("finally");
        }
    }
}

Biên dịch và chạy nó với lệnh sau:

java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main

Bạn sẽ nhận được đầu ra sau:

before
finally

Không có gì ngạc nhiên - đó là một cú đá tròn


rất đẹp! Bản thân tôi đã không làm gì nhiều với thao tác định nghĩa lớp. Bạn vẫn cần "xác minh: không" trên dòng lệnh?
jtahlborn

@jtahlborn Có, cố gắng ném một đối tượng không phải là hậu duệ của throwable không thành công mà không "xác minh: không".
Cháy rừng

oh, tôi có ấn tượng này bằng cách nào đó có xung quanh ràng buộc đó. vậy điều này khác với câu trả lời của tôi như thế nào?
jtahlborn

2
Sự khác biệt chính là mã java hoạt động mà không cần hack thời gian biên dịch
Wildfire

15

Trong hàm tạo, bạn có thể bắt đầu một chuỗi liên tục gọi originalThread.stop (ChuckNorisException.this)

Sợi chỉ có thể bắt ngoại lệ nhiều lần nhưng sẽ tiếp tục ném nó cho đến khi nó chết.


13

Không. Tất cả các ngoại lệ trong Java phải phân lớp java.lang.Throwablevà mặc dù nó có thể không phải là thông lệ tốt, bạn có thể nắm bắt mọi loại ngoại lệ như vậy:

try {
    //Stuff
} catch ( Throwable T ){
    //Doesn't matter what it was, I caught it.
}

Xem tài liệu java.lang.Throwable để biết thêm thông tin.

Nếu bạn đang cố gắng tránh các ngoại lệ được kiểm tra (những trường hợp phải được xử lý rõ ràng) thì bạn sẽ muốn phân lớp Lỗi hoặc RuntimeException.


9

Trên thực tế, câu trả lời được chấp nhận là không tốt vì Java cần được chạy mà không cần xác minh, tức là mã sẽ không hoạt động trong các trường hợp thông thường.

AspectJ để giải cứu cho giải pháp thực sự !

Lớp ngoại lệ:

package de.scrum_master.app;

public class ChuckNorrisException extends RuntimeException {
    public ChuckNorrisException(String message) {
        super(message);
    }
}

Khía cạnh:

package de.scrum_master.aspect;

import de.scrum_master.app.ChuckNorrisException;

public aspect ChuckNorrisAspect {
    before(ChuckNorrisException chuck) : handler(*) && args(chuck) {
        System.out.println("Somebody is trying to catch Chuck Norris - LOL!");
        throw chuck;
    }
}

Ứng dụng mẫu:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        catchAllMethod();
    }

    private static void catchAllMethod() {
        try {
            exceptionThrowingMethod();
        }
        catch (Throwable t) {
            System.out.println("Gotcha, " + t.getClass().getSimpleName() + "!");
        }
    }

    private static void exceptionThrowingMethod() {
        throw new ChuckNorrisException("Catch me if you can!");
    }
}

Đầu ra:

Somebody is trying to catch Chuck Norris - LOL!
Exception in thread "main" de.scrum_master.app.ChuckNorrisException: Catch me if you can!
    at de.scrum_master.app.Application.exceptionThrowingMethod(Application.java:18)
    at de.scrum_master.app.Application.catchAllMethod(Application.java:10)
    at de.scrum_master.app.Application.main(Application.java:5)

8

Một biến thể của chủ đề là một thực tế đáng ngạc nhiên rằng bạn có thể ném các ngoại lệ được kiểm tra không được khai báo từ mã Java. Vì nó không được khai báo trong chữ ký phương thức, trình biên dịch sẽ không cho phép bạn bắt ngoại lệ, mặc dù bạn có thể bắt nó dưới dạng java.lang.Exception.

Đây là một lớp trợ giúp cho phép bạn ném bất cứ thứ gì, tuyên bố hay không:

public class SneakyThrow {
  public static RuntimeException sneak(Throwable t) {
    throw SneakyThrow.<RuntimeException> throwGivenThrowable(t);
  }

  private static <T extends Throwable> RuntimeException throwGivenThrowable(Throwable t) throws T {
    throw (T) t;
  }
}

Bây giờ throw SneakyThrow.sneak(new ChuckNorrisException());không ném ChuckNorrisException, nhưng trình biên dịch phàn nàn trong

try {
  throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}

về việc bắt một ngoại lệ không được ném nếu ChuckNorrisException là một ngoại lệ được kiểm tra.


6

Các ChuckNorrisExceptions duy nhất trong Java phải là OutOfMemoryErrorStackOverflowError.

Bạn thực sự có thể "bắt" chúng theo nghĩa là catch(OutOfMemoryError ex)sẽ thực thi trong trường hợp ngoại lệ được ném, nhưng khối đó sẽ tự động lấy lại ngoại lệ cho người gọi.

Tôi không nghĩ đó public class ChuckNorrisError extends Errorlà mánh khóe nhưng bạn có thể thử. Tôi không tìm thấy tài liệu nào về việc gia hạnError


2
Lỗi vẫn mở rộng Ném được vì vậy không có cách nào để ngăn chặn việc bắt nó. Đó là theo thiết kế của ngôn ngữ Java.
JasonM1

1
@ JasonM1 Tôi không nghĩ OP đã yêu cầu một ngoại lệ thực sự "không thể so sánh được" và tôi có nghĩa là Lỗi lan truyền ngay cả khi bạn bắt được nó. Vì vậy, bất kỳ Throwable là catchable nhưng cả hai cuối cùng sẽ tuyên truyền không có vấn đề gì bạn làm
usr-địa phương ΕΨΗΕΛΩΝ

Để được khéo léo ChuckNorrisException có thể mở rộng Ném trực tiếp thì đó không phải là Ngoại lệ hay Lỗi!
JasonM1

4
Lỗi không lan truyền ngay cả khi bạn bắt được nó, tôi không chắc bạn đã có ý tưởng đó ở đâu.
jtahlborn

3
Tôi nghĩ rằng bạn đang bối rối về Erros, chúng là những trường hợp ngoại lệ bình thường như mọi thứ mở rộng có thể Ném được hoặc thậm chí có thể Ném được.
bestsss

6

Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?

Có, và đây là câu trả lời: Thiết kế java.lang.ChuckNorrisExceptionsao cho nó không phải là một ví dụ java.lang.Throwable. Tại sao? Theo định nghĩa, một vật thể không thể phá hủy là không thể so sánh được bởi vì bạn không bao giờ có thể bắt được thứ gì đó không bao giờ có thể ném được.


2
Nhưng sau đó nó không phải là một ngoại lệ.
cá heo

8
@dolbi: Tôi không thể tìm thấy chỗ nào trong câu hỏi của OP rằng các quốc gia java.lang.ChuckNorrisExceptionphải là một ngoại lệ, chứ đừng nói là có thể ném được
Thomas Eding

1
Tôi đoán nó không được nêu, nhưng nó được ngụ ý. Bạn là một nhà toán học :-), phải không?
cá heo

3

Bạn có thể giữ ChuckNorris nội bộ hoặc riêng tư và gói gọn anh ta hoặc theo dõi anh ta ...

try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }


7
Tôi không tin ý tưởng là bắt nó. Tôi nghĩ ý tưởng là để ngăn chặn nó bị bắt.
Patrick Roberts

Sửa lỗi cho tôi nếu tôi sai nhưng nếu bạn thực hiện nội bộ, bạn không thể truy cập nó mà không có sự phản ánh.
Jay

5
có, nhưng miễn là bạn có thể bắt Ngoại lệ hoặc Ném được thì khả năng hiển thị của loại thực tế là không liên quan.
KeithS

3

Hai vấn đề cơ bản với xử lý ngoại lệ trong Java là nó sử dụng loại ngoại lệ để cho biết liệu có nên thực hiện hành động dựa trên nó hay không và rằng bất kỳ hành động nào dựa trên một ngoại lệ (ví dụ: "bắt" nó đều được coi là để giải quyết điều kiện cơ bản. Sẽ rất hữu ích khi có một phương tiện để một đối tượng ngoại lệ có thể quyết định trình xử lý nào sẽ thực thi và liệu các trình xử lý đã thực hiện cho đến nay có làm sạch mọi thứ đủ để phương thức hiện tại đáp ứng các điều kiện thoát của nó hay không. Mặc dù điều này có thể được sử dụng để tạo ra các ngoại lệ "không thể so sánh được", hai cách sử dụng lớn hơn sẽ là (1) tạo ra các ngoại lệ sẽ chỉ được xem xét xử lý khi chúng bị bắt bởi mã thực sự biết cách xử lý chúng,finallyFooExceptiontrong một finallykhối trong quá trình tháo gỡ của a BarException, cả hai ngoại lệ sẽ truyền lên ngăn xếp cuộc gọi; cả hai đều có thể bắt được, nhưng việc tháo gỡ nên tiếp tục cho đến khi cả hai bị bắt). Thật không may, tôi không nghĩ sẽ có bất kỳ cách nào để làm cho mã xử lý ngoại lệ hiện có hoạt động theo cách đó mà không phá vỡ mọi thứ.


một ý tưởng thú vị, nhưng tôi không nghĩ rằng mã cấp thấp sẽ biết ngoại lệ cụ thể "có nghĩa là gì" đối với người gọi, vì vậy tôi không nghĩ người ném sẽ quyết định xử lý nào sẽ xử lý.
jtahlborn

@jtahlborn: Ngay bây giờ, người ném quyết định xử lý ngoại lệ nào nên thực hiện thông qua lựa chọn loại ngoại lệ. Điều này làm cho tất cả nhưng không thể xử lý một số kịch bản sạch sẽ. Trong số những điều khác: (1) nếu một ngoại lệ xảy ra trong khi một finallykhối đang dọn sạch từ một ngoại lệ trước đó, thì hoàn toàn có thể là ngoại lệ, nếu không có ngoại lệ khác, có thể là điều mà mã sẽ được xử lý và tiếp tục, nhưng xử lý cái này và bỏ qua cái kia sẽ là xấu. Tuy nhiên, không có cơ chế để tạo ra một ngoại lệ tổng hợp mà cả hai trình xử lý sẽ xử lý.
supercat

@jtahlborn: Ngoài ra, điều này khiến cho việc cho phép các ngoại lệ xảy ra trong các cuộc gọi lại được xử lý bởi lớp ứng dụng bên ngoài rất khó khăn. Nếu ngoại lệ của cuộc gọi lại được bọc trong một loại ngoại lệ khác, loại ngoại lệ gọi lại có thể được sử dụng ở lớp bên ngoài để quyết định có bắt nó hay không; nếu nó không được bao bọc, một ngoại lệ giữa lớp "tình cờ" có thể bị nhầm lẫn với một trường hợp xảy ra trong cuộc gọi lại. Nếu một đối tượng ngoại lệ được bọc được thông báo khi nó được chuyển đến lớp ứng dụng bên ngoài, thì nó có thể bắt đầu trả lời các loại ngoại lệ được bọc.
supercat

Tôi không tranh luận về những điểm khác của bạn, chỉ là tuyên bố về đối tượng ngoại lệ quyết định người xử lý nào sẽ thực thi. ở một mức độ nào đó, các loại ngoại lệ đã làm điều đó rồi, nhưng có vẻ như bạn muốn thứ gì đó năng động hơn, điều mà tôi không đồng ý. Tôi nghĩ rằng đối số chính của bạn (mà bạn đang đi ngang) là nắm bắt càng nhiều thông tin càng tốt ở phía dưới và để các lớp trên nhìn thấy và làm việc với tất cả thông tin đó. Về điểm chung này, tôi đồng ý với bạn, tuy nhiên ma quỷ nằm trong chi tiết / cách thực hiện.
jtahlborn

@jtahlborn: Ý định của tôi là không để các phương thức ảo triển khai bất cứ thứ gì đặc biệt "động", mà về cơ bản là "Có một điều kiện của loại được chỉ định nên được áp dụng". Tuy nhiên, có một điều tôi quên đề cập đến là nên có một phương tiện thông qua mã mà các cuộc gọi Foocó thể phân biệt giữa một ngoại lệ Footự ném hoặc cố tình muốn giả vờ, từ một điều Fookhông mong muốn xảy ra khi nó xảy ra gọi một số phương pháp khác. Đó là khái niệm về các ngoại lệ "được kiểm tra" nên là "về".
supercat

1

Có thể dễ dàng mô phỏng một ngoại lệ chưa được phát hiện trên luồng hiện tại. Điều này sẽ kích hoạt hành vi thường xuyên của một ngoại lệ chưa được bắt gặp, và do đó hoàn thành công việc về mặt ngữ nghĩa. Tuy nhiên, nó sẽ không nhất thiết dừng quá trình thực thi của luồng hiện tại, vì không có ngoại lệ nào thực sự bị ném.

Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
    currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.

Điều này thực sự hữu ích trong các tình huống (rất hiếm), ví dụ khi Errorcần xử lý đúng cách , nhưng phương thức được gọi từ một khung bắt (và loại bỏ) bất kỳ Throwable.


0

Gọi System.exit (1) trong finalizevà chỉ cần ném một bản sao của ngoại lệ từ tất cả các phương thức khác, để chương trình sẽ thoát.

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.