Document directory
- The try-finally syntax in the seh exception model is referenced and introduced.
- All exceptions must be inherited from throwable.
- Stricter and more rigorous exception handling management!
- Pay special attention to runtimeexception
- Summary
For a programmer who is very familiar with the c ++ Exception Handling Model, it can hardly be trained or learned without any additional training, you can fully accept and easily use the exception handling programming methods in Java. This is because the Exception Processing Model in Java has almost 99% similarity with the Exception Processing Model in C ++. Both of them are almost identical in terms of syntax rules and semantics.
Of course, if you have a better understanding of the Exception Handling Model in Java, you can still find many differences between the Java Exception Handling Model and the Exception Handling Model in C ++. Yes, the Java language is a complete release version of the C ++ language. Therefore, the exception handling model in the Java language will inevitably inherit the style and advantages of the C ++ Exception Handling Model. However, good things do not only need to inherit advantages, but more importantly, they need to "go to its dregs and extract its essence". They need to develop !!! Without a doubt, the exception handling model in the Java language has completely reached this "development" level. It is safer, higher, stronger, and richer than the C ++ Exception Handling Model.
In the following content, I am not going to introduce the specific syntax and rules for Java exception handling programming in detail. This is almost the same as exception handling in C ++, and this basic knowledge has been elaborated in too many books on Java programming. A Yu believes: what we need here is a summary. What we need is comparison. What we need is emphasis and what we need is the key. Therefore, the Exception Handling Model in Java is compared with the c ++ Exception Handling Model. Let's thoroughly analyze the development of the model? What are the advantages? What are the differences between the Exception Handling Model and the C ++ Exception Handling Model? Why?
The try-finally syntax in the seh exception model is referenced and introduced.
The biggest difference between the Java Exception Handling Model and the Exception Handling Model in C ++ is that the try-finally syntax is introduced in the Java Exception Handling Model, AI believes this is a reference from Microsoft's Seh. In the previous articles, we learned that seh is mainly designed for the C language when we elaborate on the seh Exception Handling Model in detail, the window driver developed by third-party vendors provides better and higher security. In addition to try-exclude t, the seh Exception Handling Model also has a try-finally syntax, which is mainly used to clear allocated resources (due to exceptions, as a result, these resources cannot be released in the normal order. Remember? This is called "unwind"). Try-finally is essentially similar to the destructor in Object-Oriented Programming. Due to the existence of this mechanism, seh is very powerful and elegant.
Now, the Java Exception Handling Model also incorporates this design. But we know that both Java and C ++ have "destructor! They can use the oriented destructor to automatically release resources! Yes, that's right! In theory, this is the case. However, in practice, we may find or often encounter that only using destructor to release resources is not so easy. For example, we often need to dynamically allocate objects from the stack, in this case, the delete function must be explicitly called to release the object to trigger the execution of the destructor of the object. If an exception occurs during this period, not only the memory of the object in the heap cannot reach the result of being released, but also, some code that releases more resources in the destructor of this object cannot be executed. Therefore, these consequences are very serious. This is also a major defect in the C ++ Exception Handling Model! (Although C ++ has other remedial measures, "smart pointer" is used to ensure the timely and effective release of some objects ). In addition, there are many similar examples, such as shutting down a kernel handle and other operations (closehandle ).
In Java, because it uses the garbage collection technology, therefore, it can effectively avoid the embarrassing situation that the resources in the C ++ language cannot be correctly released due to exceptions. However, it still introduces the try-finally syntax in its exception handling model, because, in any case, it will at least bring great convenience to programmers, for example, the following program snippets can fully reflect how important try-finally is to improve the quality and beauty of our code.
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Bufferedreader RD = NULL;
Writer wR = NULL;
Try
{
File srcfile = new file (ARGs [0]);
File dstfile = new file (ARGs [1]);
RD = new bufferedreader (New inputstreamreader (New fileinputstream (srcfile), argS [2]);
WR = new outputstreamwriter (New fileoutputstream (dstfile), argS [3]);
While (true)
{
String Sline = RD. Readline ();
If (Sline = NULL) break;
Wr. Write (Sline );
Wr. Write ("/R/N ");
}
}
Finally
{
// Under which circumstances can the file stream handle be properly closed?
// This method is mainly used to clear non-memory resources (the garbage collection mechanism cannot
// Processed resources, such as database connections, socket closures, and file closures ).
Wr. Flush ();
Wr. Close ();
Rd. Close ();
}
}
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
}
All exceptions must be inherited from throwable.
In the C ++ Exception Handling model, it gives programmers the maximum freedom and space to play (consistent with the design philosophy dominated by C ++ ), for example, it allows programmers to throw any exception object they want. It can be a variety of simple data types (such as int, float, and double) provided in the language system ), it can also be a user-defined abstract data object (such as a class object instance ). Although, from any perspective, we should all closely combine exception handling with object-oriented methods (using a hierarchical Class Object Structure with inheritance characteristics to describe various exceptions in the system ), however, the C ++ language specification does not have this constraint. Besides, even if everyone uses an object-oriented method to describe "exceptions ", however, because each subsystem (basic operating database) is not designed by a single vendor (individual), the exception object systems designed by each subsystem are very different from each other. This brings a lot of inconsistency and even a lot of trouble to the programmers who finally use (reuse) these libraries, we not only need to spend a lot of valuable time learning and familiarizing ourselves with these different abnormal object subsystems, but also a bigger problem is the semantic inconsistency between these different subsystems, when programmers finally handle these exceptions, it is difficult to unify them. For example, in the MFC library system, cmemoryexception is used to indicate an exception related to memory operations; in other database systems, another class may be used to indicate an exception error in memory operations. Essentially, this is due to the lack of standardization and unification. Therefore, if these problems are fully taken into account during language design, they will be incorporated into the unified language specification, this is undoubtedly a good thing for programmers.
The Java language can do this without a doubt. It requires that all throw exceptions must be derived from throwable in Java programs (no matter who writes the Code, for example, the following code cannot be passed during compilation.
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Bufferedreader RD = NULL;
Writer wR = NULL;
Try
{
File srcfile = new file (ARGs [0]);
File dstfile = new file (ARGs [1]);
RD = new bufferedreader (New inputstreamreader (New fileinputstream (srcfile), argS [2]);
WR = new outputstreamwriter (New fileoutputstream (dstfile), argS [3]);
// Errors will be reported during compilation
// The correct method can be throw new exception ("error! Test! ");
If (RD = NULL | wR = NULL) throw new string ("error! Test! ");
While (true)
{
String Sline = RD. Readline ();
If (Sline = NULL) break;
Wr. Write (Sline );
Wr. Write ("/R/N ");
}
}
Finally
{
Wr. Flush ();
Wr. Close ();
Rd. Close ();
}
}
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
}
During compilation, the output error message is as follows:
E:/work // TRANS. Java: 20: incompatible types
Found: Java. Lang. String
Required: Java. Lang. throwable
If (RD = NULL | wR = NULL) throw new string ("error! Test! ");
1 error
Of course, in actual Java programming, the JDK platform has designed a rich and complete exception object classification model for us. Therefore, Java programmers generally do not need to redefine their own exception objects. In addition, even the custom exception object to be extended is often derived from exception. Therefore, for Java programmers, it generally only needs to catch (exception ex) in its top-level functions to capture all the exception objects, instead of using catch (…) in C ++ (...) That is a nondescribable but helpless syntax. Therefore, catch (…) is not required in Java (...) This syntax.
As for the specific exception object classification model on the JDK platform, the hero, a Yu, is going to discuss it in a separate article. Here I will just give a brief summary: the underlying classes of all Exception objects are throwable, which is directly inherited from the object (which is mandatory by the Java System ), and it implements the serializable interface (this makes the most material preparations for all abnormal objects to easily cross the Java component system ). Exception classes derived directly from throwable include exception and error. Exception is the most familiar to Java Programmers. It generally represents the basic class of exception objects in the real sense. That is to say, the exception and all exceptions derived from it are the types of exceptions that the application can catch and can recover and handle exceptions. An error indicates that a very serious Exception error occurs in the Java System, and the error may be unrecoverable by the application, such as linkageerror or threaddeath.
Stricter and more rigorous exception handling management!
It is also compared with the c ++ Exception Handling model. In Java systems, it manages exception handling more strictly and strictly! Why? Next, let's hear from you!
Let's look at an example first! The Code is as follows:
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Bufferedreader RD = NULL;
Writer wR = NULL;
Try
{
File srcfile = new file (ARGs [0]);
File dstfile = new file (ARGs [1]);
RD = new bufferedreader (New inputstreamreader (New fileinputstream (srcfile), argS [2]);
WR = new outputstreamwriter (New fileoutputstream (dstfile), argS [3]);
// Do you have any problems with the following statement?
If (RD = NULL | wR = NULL) throw new exception ("error! Test! ");
While (true)
{
String Sline = RD. Readline ();
If (Sline = NULL) break;
Wr. Write (Sline );
Wr. Write ("/R/N ");
}
}
Finally
{
Wr. Flush ();
Wr. Close ();
Rd. Close ();
}
}
Catch (ioexception ex)
{
Ex. printstacktrace ();
}
}
}
Programmers familiar with the Java language, do you think the above program has any problems? Can the compilation pass? If not, why? Now, with your own analysis and expectations, compile the above small program! The results are as expected? Yes, it is indeed a compilation error. The error message is as follows:
E:/Trans. Java: 20: unreported exception java. Lang. exception; must be caught or declared to be thrown
If (RD = NULL | wR = NULL) throw new exception ("error! Test! ");
1 error
The above compilation error message, I believe Java programmers must have seen it (it may not be uncommon !), In addition, this is also the most confusing and confusing place for many programmers who have just transferred from C ++ to writing Java programs (not yet actually written, "Is there no problem with the code? Why is there a problem with compilation "!
Haha! AI believes that some sophisticated Java programmers must be very clear about the cause of the above compilation errors. That is, in the error message ("Must be caught") As described, in the Java Exception Handling Model, all thrown exceptions must have a corresponding" Exception Handling Module ". That is to say, if you throw an exception in the program, you must catch this exception (handle this exception) in your program (in the function ). For example, in the above example, you throw an exception type exception in the code of line 3, but in this function, there is no catch and the exception is handled. Therefore, even if such a program can be compiled, the runtime is fatal (possibly causing program crash). Therefore, the Java language simply checks (and gets stuck) as much as possible during compilation) this kind of error should not occur, which is undoubtedly helpful for improving the program reliability. On the contrary, this is not the case in C ++. It gives more things and responsibilities to C ++ programmers. It always believes that C ++ programmers are the best, it will handle all these tasks on its own. If an uncaptured exception occurs in the program, the system (actually in the C ++ Runtime Library) considers this as a fatal and unrecoverable error, call the terminate function to terminate the process. (The NT System is slightly responsible. A "system error" dialog box is displayed, and some exception-related error messages are reported ).
From the above analysis, we can see that the Java Exception Handling Model is indeed more rigorous and secure than the C ++ Exception Handling Model. In fact, this is also reflected in more aspects. For example, in the C ++ Exception Handling Model, the exception declaration can already be part of the declaration function interface, however, this is not what the language requires. Although many excellent library systems regard this as a necessary Convention and even programming specifications during design, for example, there are many functions that may throw exceptions in MFC, are explicitly declared, such as the cfile: Read function. The declaration is as follows:
VirtualUintRead (Void *Lpbuf,UintNcount);
Throw (Cfileexception);
However, this is required in Java. If a function may throw an exception to the caller function at the upper layer during runtime, it must explicitly indicate in the declaration of the function (using the throws keyword, similar to C ++ ). Do you still remember the compilation error message? "Must be caught or declared to be thrown", Where"Must be caught"What about the last half? "Declared to be thrown"What does it mean? In fact, it refers to "a function must be explicitly declared and may throw an exception to the outside." That is to say, if a function is internal, it may throw a type of exception, however, this function does not want to catch or handle exceptions of this type internally. In this case, it must (note that this is required! Please! C ++ is not mandatory.) using the throws keyword to declare the function may throw an exception to the outside, so that the caller of the function can know and promptly handle this type of exception. The following code compares these conditions:
// Example program 1, which can be compiled
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Test ();
}
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
Static void test ()
{
Try
{
Throw new exception ("test ");
}
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
}
// Example Program 2, which cannot be compiled
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Test ();
}
// Although exceptions of the exception type can be caught here
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
Static void test ()
{
Throw new exception ("test ");
}
}
// Example Program 3, which can be compiled again
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Test ();
}
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
// The exception type may be thrown due to function declaration
Static void test () throws exception
{
Throw new exception ("test ");
}
}
// Example program 4, which cannot be compiled
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
// Although the test () function does not actually throw an exception of the exception type
// However, because of its function declaration, it may throw an exception of the exception type.
// Therefore, it cannot be compiled here.
// Haha! I have learned the rigor of the Java Exception Handling Model!
Test ();
}
Catch (ioexception ex)
{
Ex. printstacktrace ();
}
}
Static void test () throws exception
{
}
}
I don't know whether the examples that have been linked above can bring you an "open-minded" feeling. Frankly speaking, the exception handling model provided by Java is not complex, I believe that too many Java programmers have a deeper understanding than Ayu. Maybe Ah Yu is a joke about these simple and trivial things! However, ayu insisted that it is necessary to thoroughly elaborate these simple but useful principles. The following code adds an exception:
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Test ();
}
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
Static void test () throws Error
{
Throw new error ("intentionally throwing an error ");
}
}
Friends! Can the above program be compiled? Note: In the Java Exception Handling Model, all thrown exceptions must have catch blocks! The above program cannot be compiled, because both error and exception are derived directly from throwable, and the test function declares that it may throw an error type exception, but there is no catch (error) or catch (throwable) block in the main function, so it should be compiled incorrectly! Really? Try it! Haha! The result is not what we expected, but it is exactly the correct compilation. Why? Why? Why?
In fact, the reason is very simple, that is, because of the special nature of the error exception. The Java Exception Handling Model stipulates that error and all exceptions derived from it indicate a very serious Exception error in the system, and this error may not be recoverable by the application (as mentioned above ). Therefore, if an error type exception occurs in the system, it indicates that the system is in a state that cannot be recovered due to a crash. At this time, you are writing Java applications, it is no longer necessary (and cannot) to handle such exceptions. Therefore, the javac compiler does not need to ensure that "during compilation, all error exceptions have their corresponding error handling modules ". Of course, errors are generally thrown when the system encounters a fatal error, which is finally handled by the Java Virtual Machine. As a Java programmer, you may never consider throwing an error type exception. Therefore, error is a special case!
Pay special attention to runtimeexception
I have discussed the error-type Exception Handling. Java programmers generally do not need to pay attention to it (to handle this exception ). In addition, in fact, there is also a special "exception" type in exception objects, that is, runtimeexception, although it is derived directly from exception, however, the Java compiler (javac) is specially treated for runtimeexception and takes care of it. Don't believe it. Let's take a look at the two examples below! The Code is as follows:
// Example 1
// It cannot be compiled. We can understand it.
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Test ();
}
Static void test ()
{
// Note this statement
Throw new exception ("throwing an exception intentionally ");
}
}
// Example 2
// But why can it be compiled?
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Test ();
}
Static void test ()
{
// Note this statement
Throw new runtimeexception ("intentionally throwing a runtimeexception ");
}
}
For the above two similar programs, javac encountered two completely different processing methods during compilation. It is reasonable to say that the 2nd sample programs should also be like the 1st sample programs, an error occurred while compiling! However, when javac compiles it, it is allowed to pass it with exceptions, and this exception is also caught by the Java Virtual Machine at runtime, and detailed exception information is printed on the console. The running result is as follows:
Java. Lang. runtimeexception:Intentionally throwRuntimeexception
At Trans. Test (trans. Java: 13)
At trans. Main (trans. Java: 8)
Exception in thread "Main"
Why does the javac and Java virtual machines specially handle runtimeexception types (and the exception types derived from it? You know, this is in conflict with the design principles of "more rigorous and safer Java Exception Handling models! Why? This is simply incomprehensible! The hero, a Yu, advised everyone to be cautious. We may wish to change our perspective to compare and analyze the C ++ Exception Handling Model. Maybe this will make us feel at ease!
In C ++ Exception Handling implemented by VC (based on the seh mechanism), there are generally two types of exceptions. One is the exception thrown by the programmer in the Code through the throw Statement (an error is dynamically monitored during the runtime). What about the other one? This is a system exception, that is, the seh exception that we have been discussing earlier, for example, "0 division", "Block Storage protection exception", and "invalid handle, this type of exception can actually be avoided by programmers (as long as we are careful and rigorous enough to make the written code safe and reliable enough), but in fact, this may not be completely done, too idealistic. Therefore, in order to completely solve this hidden danger and improve the overall reliability of the Program (we can tolerate some bugs left by programmers, at least because the coding is not considered weekly, or a small bug left by a small negligence, as a result, the entire application system crashes at runtime !), In the C ++ exception handling process provided by VC, it can capture system exceptions of the seh type. When such exceptions are handled, they are first taken over by the Interrupt System of the operating system (that is, when such exceptions occur in applications, this will trigger a system "interruption" Event). Then, the operating system will be based on the application (actually the VC Runtime Library) A series of "exception" callback functions and other information are set to forward control of the "System exception" to the "VC Exception Handling Model" at the application layer. Remember the methods and technical principles in the previous article "how to convert Seh-type system exceptions into C ++-type exceptions? Let's take a look back. After "converting a Seh-type system exception to a C ++-type exception", it provides a good technical method, in the C ++ exception handling process provided by VC, the "System exception" is fully handled by C ++.
There is no doubt that this technology is very good! Great! Similarly, in the Exception Handling Model of Java, it should also have this technical feature (who makes it the development of C ++ ?), Dear friends, have you understood this question? Yes, in fact, the role of the runtimeexception exception is equivalent to the seh_exception_base exception designed for C ++ in the previous article. They basically implement the same functions. However, in Java, runtimeexception is uniformly incorporated into Java and JDK specifications. Please refer to the following code to verify our understanding!
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Test ();
}
Static void test ()
{
Int I = 4;
Int J = 0;
// An arithmeticexception is triggered during running.
// Arithmeticexception is derived from runtimeexception
System. Out. println ("I/J =" + I/J );
}
}
The running result is as follows:
Java. Lang. arithmeticexception:/by zero
At Trans. Test (trans. Java: 16)
At trans. Main (trans. Java: 8)
Exception in thread "Main"
The following example also generates a runtimeexception. The Code is as follows:
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Test ();
}
Static void test ()
{
String STR = NULL;
// During running, an nullpointerexception is triggered here
// Nullpointerexception is derived from runtimeexception
Str. compareto ("ABC ");
}
}
Therefore, for runtimeexception exceptions, javac cannot determine which functions (or code in which regions) are based on static syntax detection during compilation) this type of exception may be thrown (it depends entirely on the running state or the running state), and because of this, the"Must be caught or declared to be thrown"The rule does not apply to runtimeexception (so there is a strange compilation phenomenon mentioned above, which is also a special rule ). However, Java virtual machines need to effectively capture and handle such exceptions. Of course, runtimeexception can also be explicitly thrown by the programmer. For program reliability, for some code regions that may encounter "runtimeexception, it is best for programmers to promptly handle these unexpected exceptions, that is, catch (runtimeexcetion) or catch (exception) to catch them. The following sample code is as follows:
Import java. Io .*;
Public class Trans
{
Public static void main (string [] ARGs)
{
Try
{
Test ();
}
// It is best to catch all Exception exceptions in the upper-layer function call!
Catch (exception E)
{
System. Out. println ("go here! ");
E. printstacktrace ();
}
}
// It is better to explicitly declare it here, indicating that this function may throw a runtimeexception
Static void test () throws runtimeexception
{
String STR = NULL;
// During running, an nullpointerexception is triggered here
// Nullpointerexception is derived from runtimeexception
Str. compareto ("ABC ");
}
}
Summary
• The biggest difference between the Java Exception Handling Model and the Exception Handling Model in C ++ is that the try-finally syntax is introduced in the Java Exception Handling Model, it is mainly used to clear non-memory resources (resources that cannot be processed by the garbage collection mechanism), such as database connections, socket closures, and file stream closures.
• All exceptions must be inherited from throwable. Unlike C ++, exceptions of any type can be thrown. Therefore, in Java exception programming, there is no catch (…) in C ++ (...) And its catch (throwable e) can completely replace catch (…) in C ++ (...) .
• In the Java Exception Handling Model, all thrown exceptions must have a corresponding "Exception Handling Module ". That is to say, if you throw an exception in the program, you must catch this exception (handle this exception) in your program (in the function ). However, exceptions of the runtimeexception and error types (and their subclass exceptions) are exceptions. Here, error indicates that a very serious Exception error occurs in the Java System. While runtimeexception is a subclass of exception, but it represents runtime exceptions (this is the most inadequate in the C ++ Exception Handling model, although the Exception Handling Model Implemented by VC is good)
• If a function may throw an exception to the callback function at the upper layer during runtime, it must be explicitly indicated in the declaration of the function (using the throws keyword, similar to C ++ ).
Although this article is a bit long, if you can take a full look at it, I believe you have a deeper understanding of the Java Exception Handling Model (of course, due to the limited level of AI, there will inevitably be many mistakes in understanding or understanding. You are welcome to give me some advice! Haha! Can also be discussed and communicated ). In the next article, ayu will continue to analyze and elaborate some more detailed syntax features and usage skills in the Java Exception Handling Model, as well as precautions. If you are interested, continue! Go!