one. The definition of exception (recommended: java video tutorial)
is defined in "Java Programming Thoughts" as follows: Exception: a problem that prevents the current method or scope from continuing to execute. Although there is an exception handling mechanism in Java, it must be clear that exceptions should never be viewed with a "normal" attitude. Absolutely speaking, an exception is an error in a certain sense, a problem, and it may cause the program to fail. The reason why Java proposes an exception handling mechanism is to tell developers that something is abnormal in your program. Please pay attention.
I remember when I first learned Java, I was always confused about exceptions. I didn’t know what this exception meant and why there was this mechanism? But with the accumulation of knowledge, I gradually started to feel a little bit about the anomalies. Give an example to illustrate the use of exceptions.
public class Calculator { public int devide(int num1, int num2) { //判斷除數(shù)是否為0 if(num2 == 0) { throw new IllegalArgumentException("除數(shù)不能為零"); } return num1/num2; } }
Take a look at the division operation method in this class. If you are a novice, you may directly return the calculation result without considering whether the parameters are correct or legal (of course you can forgive it, everyone is like this) came over). But we should be as thorough as possible to nip the "signs" that may cause the program to fail in the cradle, so it is necessary to check the legality of the parameters.
The parameter illegal exception thrown by the parameter check is an abnormality of this method. Under normal circumstances, we will use the calculator correctly, but it is not ruled out that we accidentally assign the divisor to 0. If you haven't considered this situation before, and it happens that the user has a poor mathematical foundation, then you are screwed. But if you've considered this situation before, it's clear that the error is within your control.
two. Abnormal Literacy Action
I saw a joke when I was chatting with someone today: The most true dependence in the world is when you are trying and I am catching. No matter how angry you are, I will bear it silently and deal with it quietly. Most novices feel that Java exceptions are: try...catch.... Yes, this is the most used and the most practical. My feeling is: Java exceptions come from "try...catch...".
First, let’s get familiar with Java’s exception system:
The Throwable class is the super class of all errors or exceptions in the Java language (this is everything that can be thrown). It has two subclasses: Error and Exception.
Error: Used to indicate serious problems that reasonable applications should not attempt to catch. This situation is a big problem, too big for you to deal with, so just let it go and don't worry about it. For example, VirtualMachineError: This error is thrown when the Java virtual machine crashes or runs out of resources it needs to continue operating. Okay, even if this exception exists, when and how should it be handled? ? Leave it to the JVM, there is nothing more professional than it.
Exception: It indicates a condition that a reasonable application would want to catch. Exception is divided into two categories: one is CheckedException and the other is UncheckedException.
The main difference between these two Exceptions is that CheckedException needs to be captured using try...catch..., while UncheckedException does not need to be captured. Usually UncheckedException is also called RuntimeException.
Our common RuntimeExcepitons include IllegalArgumentException, IllegalStateException, NullPointerException, IndexOutOfBoundsException and so on. There are too many CheckedExceptions to mention. During the process of writing the program, the exceptions caught by try...catch... are all CheckedExceptions. IOException and its subclasses in the io package, these are CheckedException.
three. The use of exceptions
This part of the use of exceptions is mainly demonstration code, which we will encounter in the process of writing code (of course only a small part), do you want to inspire others!
Example 1. This example mainly demonstrates the execution flow of the code after an exception occurs by comparing two methods.
public static void testException1() { int[] ints = new int[] { 1, 2, 3, 4 }; System.out.println("異常出現(xiàn)前"); try { System.out.println(ints[4]); System.out.println("我還有幸執(zhí)行到嗎");// 發(fā)生異常以后,后面的代碼不能被執(zhí)行 } catch (IndexOutOfBoundsException e) { System.out.println("數(shù)組越界錯誤"); } System.out.println("異常出現(xiàn)后"); } /*output: 異常出現(xiàn)前 數(shù)組越界錯誤 4 異常出現(xiàn)后 */
public static void testException2() { int[] ints = new int[] { 1, 2, 3, 4 }; System.out.println("異常出現(xiàn)前"); System.out.println(ints[4]); System.out.println("我還有幸執(zhí)行到嗎");// 發(fā)生異常以后,他后面的代碼不能被執(zhí)行 }
First of all, point out the shortcomings in the example. IndexOutofBoundsException is an unchecked exception, so there is no need to try...catch... to display the capture, but my purpose is to use different processing for the same exception. method and see what difference it will produce (here I can only use it for a while). When an exception occurs, the first method just jumps out of the try block, but the code behind it will still be executed.
But the second one is different and jumps directly out of the method, which is tougher. From the first method, we see that try...catch... is a "transactional" guarantee. Its purpose is to ensure that the program completes running under abnormal circumstances, and it also notifies the programmer of the program. Detailed information about the error (the details sometimes depend on the programmer's design).
Example 2. Rethrow the exception
public class Rethrow { public static void readFile(String file) throws FileNotFoundException { try { BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); System.err.println("不知道如何處理該異?;蛘吒静幌胩幚硭遣蛔鎏幚碛植缓线m,這是重新拋出異常交給上一級處理"); //重新拋出異常 throw e; } } public static void printFile(String file) { try { readFile(file); } catch (FileNotFoundException e) { e.printStackTrace(); } } public static void main(String[] args) { printFile("D:/file"); } }
異常的本意是好的,讓我們試圖修復程序,但是現(xiàn)實中我們修復的幾率很小,我們很多時候就是用它來記錄出錯的信息。如果你厭倦了不停的處理異常,重新拋出異常對你來說可能是一個很好的解脫。原封不動的把這個異常拋給上一級,拋給調(diào)用這個方法的人,讓他來費腦筋吧。這樣看來,java異常(當然指的是受檢異常)又給我們平添很多麻煩,盡管它的出發(fā)點是好的。
例3. 異常鏈的使用及異常丟失
定義三個異常類:ExceptionA,ExceptionB,ExceptionC
public class ExceptionA extends Exception { public ExceptionA(String str) { super(); } } public class ExceptionB extends ExceptionA { public ExceptionB(String str) { super(str); } } public class ExceptionC extends ExceptionA { public ExceptionC(String str) { super(str); } }
異常丟失的情況:
public class NeverCaught { static void f() throws ExceptionB{ throw new ExceptionB("exception b"); } static void g() throws ExceptionC { try { f(); } catch (ExceptionB e) { ExceptionC c = new ExceptionC("exception a"); throw c; } } public static void main(String[] args) { try { g(); } catch (ExceptionC e) { e.printStackTrace(); } } } /* exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at exception.NeverCaught.main(NeverCaught.java:19) */
為什么只是打印出來了ExceptionC而沒有打印出ExceptionB呢?這個還是自己分析一下吧!
上面的情況相當于少了一種異常,這在我們排錯的過程中非常的不利。那我們遇到上面的情況應該怎么辦呢?這就是異常鏈的用武之地:保存異常信息,在拋出另外一個異常的同時不丟失原來的異常。
public class NeverCaught { static void f() throws ExceptionB{ throw new ExceptionB("exception b"); } static void g() throws ExceptionC { try { f(); } catch (ExceptionB e) { ExceptionC c = new ExceptionC("exception a"); //異常連 c.initCause(e); throw c; } } public static void main(String[] args) { try { g(); } catch (ExceptionC e) { e.printStackTrace(); } } } /* exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at exception.NeverCaught.main(NeverCaught.java:21) Caused by: exception.ExceptionB at exception.NeverCaught.f(NeverCaught.java:5) at exception.NeverCaught.g(NeverCaught.java:10) ... 1 more */
這個異常鏈的特性是所有異常均具備的,因為這個initCause()方法是從Throwable繼承的。
例4. 清理工作
清理工作對于我們來說是必不可少的,因為如果一些消耗資源的操作,比如IO,JDBC。如果我們用完以后沒有及時正確的關閉,那后果會很嚴重,這意味著內(nèi)存泄露。異常的出現(xiàn)要求我們必須設計一種機制不論什么情況下,資源都能及時正確的清理。這就是finally。
public void readFile(String file) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream(file))); // do some other work } catch (FileNotFoundException e) { e.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
例子非常的簡單,是一個讀取文件的例子。這樣的例子在JDBC操作中也非常的常見。(所以,我覺得對于資源的及時正確清理是一個程序員的基本素質(zhì)之一。)
Try...finally結(jié)構(gòu)也是保證資源正確關閉的一個手段。如果你不清楚代碼執(zhí)行過程中會發(fā)生什么異常情況會導致資源不能得到清理,那么你就用try對這段"可疑"代碼進行包裝,然后在finally中進行資源的清理。舉一個例子:
public void readFile() { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream("file"))); // do some other work //close reader reader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
我們注意一下這個方法和上一個方法的區(qū)別,下一個人可能習慣更好一點,及早的關閉reader。但是往往事與愿違,因為在reader.close()以前異常隨時可能發(fā)生,這樣的代碼結(jié)構(gòu)不能預防任何異常的出現(xiàn)。因為程序會在異常出現(xiàn)的地方跳出,后面的代碼不能執(zhí)行(這在上面應經(jīng)用實例證明過)。這時我們就可以用try...finally來改造:
public void readFile() { BufferedReader reader = null; try { try { reader = new BufferedReader(new InputStreamReader( new FileInputStream("file"))); // do some other work // close reader } finally { reader.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
及早的關閉資源是一種良好的行為,因為時間越長你忘記關閉的可能性越大。這樣在配合上try...finally就保證萬無一失了(不要嫌麻煩,java就是這么中規(guī)中矩)。
再說一種情況,假如我想在構(gòu)造方法中打開一個文件或者創(chuàng)建一個JDBC連接,因為我們要在其他的方法中使用這個資源,所以不能在構(gòu)造方法中及早的將這個資源關閉。那我們是不是就沒轍了呢?答案是否定的。看一下下面的例子:
public class ResourceInConstructor { BufferedReader reader = null; public ResourceInConstructor() { try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(""))); } catch (FileNotFoundException e) { e.printStackTrace(); } } public void readFile() { try { while(reader.readLine()!=null) { //do some work } } catch (IOException e) { e.printStackTrace(); } } public void dispose() { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
這一部分講的多了一點,但是異常確實是看起來容易用起來難的東西呀,java中還是有好多的東西需要深挖的。
四. 異常的誤用
對于異常的誤用著實很常見,上一部分中已經(jīng)列舉了幾個,大家仔細的看一下。下面再說兩個其他的。
例1. 用一個Exception來捕捉所有的異常,頗有"一夫當關萬夫莫開"的氣魄。不過這也是最傻的行為。
public void readFile(String file) { BufferedReader reader = null; Connection conn = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream(file))); // do some other work conn = DriverManager.getConnection(""); //... } catch (Exception e) { e.printStackTrace(); } finally { try { reader.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }
從異常角度來說這樣嚴格的程序確實是萬無一失,所有的異常都能捕獲。但是站在編程人員的角度,萬一這個程序出錯了我們該如何分辨是到底是那引起的呢,IO還是JDBC...所以,這種寫法很值得當做一個反例。大家不要以為這種做法很幼稚,傻子才會做。我在公司實習時確實看見了類似的情況:只不過是人家沒有用Exception而是用了Throwable。
例2.?這里就不舉例子了,上面的程序都是反例。異常是程序處理意外情況的機制,當程序發(fā)生意外時,我們需要盡可能多的得到意外的信息,包括發(fā)生的位置,描述,原因等等。
這些都是我們解決問題的線索。但是上面的例子都只是簡單的printStackTrace()。如果我們自己寫代碼,就要盡可能多的對這個異常進行描述。比如說為什么會出現(xiàn)這個異常,什么情況下會發(fā)生這個異常。如果傳入方法的參數(shù)不正確,告知什么樣的參數(shù)是合法的參數(shù),或者給出一個sample。
例3.?將try?block寫的簡短,不要所有的東西都扔在這里,我們盡可能的分析出到底哪幾行程序可能出現(xiàn)異常,只是對可能出現(xiàn)異常的代碼進行try。盡量為每一個異常寫一個try...catch,避免異常丟失。
For more java knowledge, please pay attention to the java basic tutorial column.
The above is the detailed content of Exceptions in java you must know. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

To correctly handle JDBC transactions, you must first turn off the automatic commit mode, then perform multiple operations, and finally commit or rollback according to the results; 1. Call conn.setAutoCommit(false) to start the transaction; 2. Execute multiple SQL operations, such as INSERT and UPDATE; 3. Call conn.commit() if all operations are successful, and call conn.rollback() if an exception occurs to ensure data consistency; at the same time, try-with-resources should be used to manage resources, properly handle exceptions and close connections to avoid connection leakage; in addition, it is recommended to use connection pools and set save points to achieve partial rollback, and keep transactions as short as possible to improve performance.

TheJVMenablesJava’s"writeonce,runanywhere"capabilitybyexecutingbytecodethroughfourmaincomponents:1.TheClassLoaderSubsystemloads,links,andinitializes.classfilesusingbootstrap,extension,andapplicationclassloaders,ensuringsecureandlazyclassloa

Use classes in the java.time package to replace the old Date and Calendar classes; 2. Get the current date and time through LocalDate, LocalDateTime and LocalTime; 3. Create a specific date and time using the of() method; 4. Use the plus/minus method to immutably increase and decrease the time; 5. Use ZonedDateTime and ZoneId to process the time zone; 6. Format and parse date strings through DateTimeFormatter; 7. Use Instant to be compatible with the old date types when necessary; date processing in modern Java should give priority to using java.timeAPI, which provides clear, immutable and linear

Pre-formanceTartuptimeMoryusage, Quarkusandmicronautleadduetocompile-Timeprocessingandgraalvsupport, Withquarkusoftenperforminglightbetterine ServerLess scenarios.2.Thyvelopecosyste,

Networkportsandfirewallsworktogethertoenablecommunicationwhileensuringsecurity.1.Networkportsarevirtualendpointsnumbered0–65535,withwell-knownportslike80(HTTP),443(HTTPS),22(SSH),and25(SMTP)identifyingspecificservices.2.PortsoperateoverTCP(reliable,c

Java's garbage collection (GC) is a mechanism that automatically manages memory, which reduces the risk of memory leakage by reclaiming unreachable objects. 1.GC judges the accessibility of the object from the root object (such as stack variables, active threads, static fields, etc.), and unreachable objects are marked as garbage. 2. Based on the mark-clearing algorithm, mark all reachable objects and clear unmarked objects. 3. Adopt a generational collection strategy: the new generation (Eden, S0, S1) frequently executes MinorGC; the elderly performs less but takes longer to perform MajorGC; Metaspace stores class metadata. 4. JVM provides a variety of GC devices: SerialGC is suitable for small applications; ParallelGC improves throughput; CMS reduces

Gradleisthebetterchoiceformostnewprojectsduetoitssuperiorflexibility,performance,andmoderntoolingsupport.1.Gradle’sGroovy/KotlinDSLismoreconciseandexpressivethanMaven’sverboseXML.2.GradleoutperformsMaveninbuildspeedwithincrementalcompilation,buildcac

defer is used to perform specified operations before the function returns, such as cleaning resources; parameters are evaluated immediately when defer, and the functions are executed in the order of last-in-first-out (LIFO); 1. Multiple defers are executed in reverse order of declarations; 2. Commonly used for secure cleaning such as file closing; 3. The named return value can be modified; 4. It will be executed even if panic occurs, suitable for recovery; 5. Avoid abuse of defer in loops to prevent resource leakage; correct use can improve code security and readability.
