คำนำ
ในกระบวนการเรียนรู้ Java ฉันเชื่อว่าทุกคนได้เรียนรู้บทเกี่ยวกับข้อยกเว้นและฉันจะไม่พูดถึงลักษณะพื้นฐานและการใช้ข้อยกเว้นที่นี่ ข้อยกเว้นคืออะไร? ฉันไม่รู้ว่าทุกคนเข้าใจได้อย่างไร ความเข้าใจของฉันง่ายมากนั่นคือสถานการณ์ที่ผิดปกติ ตัวอย่างเช่นตอนนี้ฉันเป็นผู้ชาย แต่ฉันมีสิ่งที่ไม่เหมือนใครสำหรับผู้หญิง ในความคิดของฉันนี่เป็นความผิดปกติอย่างแน่นอนและฉันไม่สามารถทนได้ ฉันเชื่อว่าทุกคนสามารถเข้าใจและใช้งานได้อย่างถูกต้อง
อย่างไรก็ตามหากการประมวลผลข้อยกเว้นพื้นฐานทางแสงและการใช้งานไม่เพียงพอก็ไม่น่ากลัวที่จะเกิดขึ้นในการทำงาน บางครั้งจำเป็นต้องใช้ข้อยกเว้นเพื่อผลักดันการประมวลผลของธุรกิจ ตัวอย่างเช่น: เมื่อใช้ฐานข้อมูลที่มีข้อ จำกัด ที่ไม่ซ้ำกันหากมีการแทรกข้อมูลที่ซ้ำกันก็สามารถประมวลผลได้โดยการจับข้อ จำกัด ที่ไม่ซ้ำกัน DuplicateKeyException ในเวลานี้สถานะที่สอดคล้องกันสามารถถูกส่งไปยังเลเยอร์การโทรในเลเยอร์เซิร์ฟเวอร์และเลเยอร์ด้านบนจะประมวลผลตามสถานะที่เกี่ยวข้อง ดังนั้นบางครั้งข้อยกเว้นจึงเป็นวิธีการขับขี่สำหรับธุรกิจ
บางคนจะส่งออกข้อยกเว้นหลังจากจับข้อยกเว้น ฉันสงสัยว่านักเรียนที่ระมัดระวังได้สังเกตเห็นอะไรบางอย่าง ข้อยกเว้นผลลัพธ์คืออะไร?
นี่คือข้อยกเว้นทั่วไป:
java.lang.arithmeticexception: / โดยศูนย์ที่ Greenhouse.exceptiontest.testexception (ExcendTest.java:16) ที่ Sun.reflect.nativemethodaccessorimpl.invoke0 sun.reflect.delegatingMethodaccessorimpl.invoke (มอบหมาย Methodaccessorimpl.java:25) ที่ java.lang.reflect.method.invoke (method.java:597) ที่ org.junit.runners.model.frameworkmethod $ 1.runreflectivecall (frameworkmethod.java:44) ที่ org.junit.internal.runners.model.reflectivecallable.run org.junit.runners.model.frameworkmethod.invokeexplosively (frameworkmethod.java:41) ที่ org.junit.internal.runners.statements.invokemethod.evaluate org.junit.runners.blockjunit4classrunner.runchild (blockjunit4classrunner.java:76) ที่ org.junit.runners.blockjunit4classrunner.runchild (blockjunit4classrunner.java:50) org.junit.runners.parentrunner $ 3.Run (ParentRunner.java:193) ที่ org.junit.runners.parentrunner $ 1.Schedule (ParentRunner.java:52) ที่ org.junit.runners.parentrunner org.junit.runners.parentrunner.access $ 000 (Parentrunner.java:42) ที่ org.junit.runners.parentrunner $ 2.Evaluate (Parentrunner.java:184) ที่ org.junit.runners.parentrunner.runner org.junit.runner.junitcore.run (junitcore.java:157) ที่ com.intellij.junit4.junit4ideStunner.startrunnerwithargs (junit4ideStunner.java:68) com.intellij.rt.execution.junit.ideatestrunner $ repeater.startrunnerwithargs (ideatestrunner.java:47) ที่ com.intellij.rt.execution.junit.junitstarter.preparestreamsandstart com.intellij.rt.execution.junit.junitstarter.main (junitstarter.java:70)
ข้อยกเว้นตัวชี้ว่าง:
java.lang.nullpointerexception ที่ Greenhouse.exceptiontest.testexception (ExcendTest.java:16) ที่ Sun.reflect.nativemethodaccessorimpl.invoke0 (วิธีการดั้งเดิม) ที่ Sun.reflect.nativeMethodaccessorimpl.invoke sun.reflect.delegatingMethodaccessorimpl.invoke (มอบหมาย Methodaccessorimpl.java:25) ที่ java.lang.reflect.method.invoke (method.java:597) ที่ org.junit.runners.model.frameworkmethod $ 1.runreflectivecall (frameworkmethod.java:44) ที่ org.junit.internal.runners.model.reflectivecallable.run org.junit.runners.model.frameworkmethod.invokeexplosively (frameworkmethod.java:41) ที่ org.junit.internal.runners.statements.invokemethod.evaluate org.junit.runners.blockjunit4classrunner.runchild (blockjunit4classrunner.java:76) ที่ org.junit.runners.blockjunit4classrunner.runchild (blockjunit4classrunner.java:50) org.junit.runners.parentrunner $ 3.Run (ParentRunner.java:193) ที่ org.junit.runners.parentrunner $ 1.Schedule (ParentRunner.java:52) ที่ org.junit.runners.parentrunner org.junit.runners.parentrunner.access $ 000 (Parentrunner.java:42) ที่ org.junit.runners.parentrunner $ 2.Evaluate (Parentrunner.java:184) ที่ org.junit.runners.parentrunner.runner org.junit.runner.junitcore.run (junitcore.java:157) ที่ com.intellij.junit4.junit4ideStunner.startrunnerwithargs (junit4ideStunner.java:68) com.intellij.rt.execution.junit.ideatestrunner $ repeater.startrunnerwithargs (ideatestrunner.java:47) ที่ com.intellij.rt.execution.junit.junitstarter.preparestreamsandstart com.intellij.rt.execution.junit.junitstarter.main (junitstarter.java:70)
คุณพบคุณสมบัติที่เอาต์พุตของข้อยกเว้นคือตำแหน่งที่มีข้อยกเว้นเกิดขึ้นอย่างถูกต้องและการโทรกระบวนการดำเนินการจำนวนมากจะถูกพิมพ์ออกมาในภายหลัง ข้อมูลนี้มาจากไหน? ข้อมูลนี้ได้มาจากสแต็ก เมื่อพิมพ์บันทึกข้อยกเว้นข้อมูลการโทรนี้จะได้รับจากสแต็ก แน่นอนว่าเป็นการดีที่จะสามารถค้นหาข้อยกเว้นได้อย่างถูกต้อง แต่บางครั้งเมื่อเราพิจารณาประสิทธิภาพของโปรแกรมและข้อกำหนดบางอย่างบางครั้งเราไม่จำเป็นต้องพิมพ์ข้อมูลนี้อย่างสมบูรณ์และรับข้อมูลที่เกี่ยวข้องจากการเรียกใช้วิธีการ สำหรับบางโปรแกรมที่มีความต้องการประสิทธิภาพสูงเราสามารถปรับปรุงประสิทธิภาพของโปรแกรมในด้านนี้ได้อย่างสมบูรณ์
ดังนั้นจะหลีกเลี่ยงการส่งออกข้อมูลสแต็กเหล่านี้ได้อย่างไร? ข้อยกเว้นที่กำหนดเองสามารถแก้ปัญหานี้ได้:
ขั้นแรกข้อยกเว้นอัตโนมัติจะต้องสืบทอด RuntimeException จากนั้นเขียนวิธี FillinstackTrace และ ToString ใหม่ ตัวอย่างเช่นฉันกำหนดข้อยกเว้น AppException ด้านล่าง:
แพ็คเกจ com.green.monitor.common.exception; นำเข้า java.text.messageFormat;/*** คลาสข้อยกเว้นที่กำหนดเอง*/คลาสสาธารณะ AppException ขยาย runtimeException {private boolean issuccess = false; คีย์สตริงส่วนตัว ข้อมูลสตริงส่วนตัว; AppException สาธารณะ (คีย์สตริง) {super (คีย์); this.key = key; this.info = key; } AppException สาธารณะ (คีย์สตริง, ข้อความสตริง) {super (messageFormat.format ("{0} [{1}]", คีย์, ข้อความ)); this.key = key; this.info = ข้อความ; } AppException สาธารณะ (ข้อความสตริง, คีย์สตริง, ข้อมูลสตริง) {super (ข้อความ); this.key = key; this.info = ข้อมูล; } บูลีนสาธารณะ issuccess () {return issuccess; } Public String getKey () {return key; } โมฆะสาธารณะ setKey (คีย์สตริง) {this.key = key; } สตริงสาธารณะ getInfo () {ข้อมูลส่งคืน; } โมฆะสาธารณะ setInfo (ข้อมูลสตริง) {this.info = ข้อมูล; } @Override Public Trowable FillInstackTrace () {ส่งคืนสิ่งนี้; } @Override สตริงสาธารณะ toString () {return messageFormat.format ("{0} [{1}]", this.key, this.info); -เหตุใดจึงต้องเขียนใหม่ FillinstackTrace และวิธีการ ToString? ก่อนอื่นดูว่าซอร์สโค้ดคืออะไร
ระดับสาธารณะ RuntimeException ขยายข้อยกเว้น {คงที่สุดท้าย Long SerialVersionUID = -7034897190745766939L; /** สร้างข้อยกเว้นรันไทม์ใหม่ด้วย <code> NULL </code> เป็น* ข้อความรายละเอียด สาเหตุไม่ได้เริ่มต้นและอาจเป็น * เริ่มต้นด้วยการโทรไปที่ {@link #initcause} */ public runtimeException () {super (); } /** สร้างข้อยกเว้นรันไทม์ใหม่ด้วยข้อความรายละเอียดที่ระบุ * สาเหตุไม่ได้เริ่มต้นและอาจเริ่มต้นด้วยการโทร * ไปยัง {@link #initcause} * * @param ข้อความข้อความรายละเอียด ข้อความรายละเอียดจะถูกบันทึกไว้สำหรับ * การดึงข้อมูลในภายหลังโดยเมธอด {@link #getMessage ()} */ public runtimeException (ข้อความสตริง) {super (ข้อความ); } /** * สร้างข้อยกเว้นรันไทม์ใหม่ด้วยข้อความรายละเอียดที่ระบุและ * สาเหตุ <p> โปรดทราบว่าข้อความโดยละเอียดที่เกี่ยวข้องกับ * <code> สาเหตุ </code> คือ <i> ไม่ใช่ </i> รวมโดยอัตโนมัติใน * ข้อความรายละเอียดของรันไทม์ข้อยกเว้นนี้ * * @param ข้อความข้อความรายละเอียด (ซึ่งบันทึกไว้สำหรับการดึงข้อมูลในภายหลัง * โดยเมธอด {@link #getMessage ()}) * @param สาเหตุสาเหตุ (ซึ่งบันทึกไว้สำหรับการดึงข้อมูลในภายหลังโดยวิธี * {@link #getCause ()}) (A <tt> null </tt> ค่าได้รับอนุญาต * และระบุว่าสาเหตุนั้นไม่มีอยู่หรือไม่ทราบ *) * @since 1.4 */ RuntimeException สาธารณะ (ข้อความสตริง, สาเหตุที่โยนได้) {super (ข้อความ, สาเหตุ); }/** การสร้างข้อยกเว้นรันไทม์ใหม่พร้อมสาเหตุที่ระบุและข้อความรายละเอียดของ <tt> (สาเหตุ == null? null: cause.toString ()) </tt> * (ซึ่งโดยทั่วไปจะมีคลาสและข้อความรายละเอียดของ * <tt> สาเหตุ </tt>) ตัวสร้างนี้มีประโยชน์สำหรับข้อยกเว้นรันไทม์ * ที่มีมากกว่า wrappers เล็กน้อยสำหรับ throwables อื่น ๆ * * @param สาเหตุสาเหตุ (ซึ่งบันทึกไว้สำหรับการดึงข้อมูลในภายหลังโดยวิธี * {@link #getCause ()}) (A <tt> null </tt> ค่าได้รับอนุญาต * และระบุว่าสาเหตุนั้นไม่มีอยู่หรือไม่ทราบ *) * @Since 1.4 */ RuntimeException สาธารณะ (สาเหตุที่โยนได้) {Super (สาเหตุ); -RuntimeException สืบทอดข้อยกเว้น แต่เรียกใช้เมธอดคลาสแม่เท่านั้นและไม่ได้ดำเนินการอื่นใด ดังนั้นมาดูกันว่าเกิดอะไรขึ้นในข้อยกเว้น
ข้อยกเว้นระดับสาธารณะขยาย {serialversionuid ยาวคงที่ {คงที่สุดท้าย = -3387516993124229948L; /*** สร้างข้อยกเว้นใหม่ด้วย <code> NULL </code> เป็นข้อความรายละเอียด * สาเหตุไม่ได้เริ่มต้นและต่อมาอาจเริ่มต้นด้วยการโทร * ไปยัง {@link #initcause} */ ข้อยกเว้นสาธารณะ () {super (); } /*** สร้างข้อยกเว้นใหม่ด้วยข้อความรายละเอียดที่ระบุ สาเหตุ * ไม่ได้เริ่มต้นและอาจเริ่มต้นโดย * การโทรไปยัง {@link #initcause} * * @param ข้อความข้อความรายละเอียด ข้อความรายละเอียดจะถูกบันทึกไว้สำหรับ * การดึงข้อมูลในภายหลังโดยเมธอด {@link #getMessage ()} */ ข้อยกเว้นสาธารณะ (ข้อความสตริง) {super (ข้อความ); } /** * สร้างข้อยกเว้นใหม่ด้วยข้อความรายละเอียดที่ระบุและ * สาเหตุ <p> โปรดทราบว่าข้อความโดยละเอียดที่เกี่ยวข้องกับ * <code> สาเหตุ </code> คือ <i> ไม่ใช่ </i> รวมอยู่ใน * ข้อความรายละเอียดของข้อยกเว้นนี้โดยอัตโนมัติ * * @param ข้อความข้อความรายละเอียด (ซึ่งบันทึกไว้สำหรับการดึงข้อมูลในภายหลัง * โดยเมธอด {@link #getMessage ()}) * @param สาเหตุสาเหตุ (ซึ่งบันทึกไว้สำหรับการดึงข้อมูลในภายหลังโดยวิธี * {@link #getCause ()}) (A <tt> null </tt> ค่าได้รับอนุญาต * และระบุว่าสาเหตุไม่มีอยู่หรือไม่ทราบ *) * @since 1.4 */ ข้อยกเว้นสาธารณะ (ข้อความสตริง, สาเหตุที่โยนได้) {super (ข้อความ, สาเหตุ); }/** * สร้างข้อยกเว้นใหม่ด้วยสาเหตุที่ระบุและรายละเอียด * ข้อความของ <tt> (สาเหตุ == null? null: cause.toString ()) </tt> (ซึ่งโดยทั่วไป * จะมีคลาสและข้อความรายละเอียดของ <tt> สาเหตุ </tt>) * ตัวสร้างนี้มีประโยชน์สำหรับข้อยกเว้นที่มีน้อยกว่า * wrappers สำหรับ throwables อื่น ๆ (ตัวอย่างเช่น {@link * java.security.privilegedActionException}) * * @param สาเหตุสาเหตุ (ซึ่งบันทึกไว้สำหรับการดึงข้อมูลในภายหลังโดยวิธี * {@link #getCause ()}) (A <tt> null </tt> ค่าได้รับอนุญาต * และระบุว่าสาเหตุไม่มีอยู่หรือไม่ทราบ *) * @Since 1.4 */ ข้อยกเว้นสาธารณะ (สาเหตุที่โยนได้) {super (สาเหตุ); -ดังที่เห็นได้จากซอร์สโค้ดเมธอดคลาสแม่จะเรียกโดยตรงในข้อยกเว้น เช่นเดียวกับ RuntimeException ฉันไม่ได้ทำอะไรเลย ลองมาดูกันว่าเกิดอะไรขึ้นในการโยน:
คลาสสาธารณะที่โยนได้สามารถใช้งานได้แบบ serializable {สาธารณะ throwable (ข้อความสตริง) {fillinstacktrace (); DetailMessage = ข้อความ; } /*** เติมในการติดตามการดำเนินการสแต็ก วิธีการนี้บันทึกภายในข้อมูลนี้ * <code> throwable </code> ข้อมูลวัตถุเกี่ยวกับสถานะปัจจุบันของ * เฟรมสแต็กสำหรับเธรดปัจจุบัน * * @return การอ้างอิงถึงอินสแตนซ์ <code> throwable </code> นี้ * @see java.lang.-hrowable#printstacktrace () */ public synchronized native fillinstacktrace (); /** * ให้การเข้าถึงการเขียนโปรแกรมไปยังข้อมูลการติดตามสแต็กที่พิมพ์โดย * {@link #printstacktrace ()} ส่งคืนอาร์เรย์ขององค์ประกอบการติดตามสแต็ก * แต่ละอันแสดงถึงหนึ่งเฟรมสแต็ก องค์ประกอบ Zeroth ของอาร์เรย์ * (สมมติว่าความยาวของอาร์เรย์ไม่ใช่ศูนย์) แสดงถึงด้านบนของ * สแต็กซึ่งเป็นวิธีการเรียกใช้วิธีสุดท้ายในลำดับ โดยทั่วไป * นี่คือจุดที่สร้างและโยนทิ้งได้ * องค์ประกอบสุดท้ายของอาร์เรย์ (สมมติว่าความยาวของอาร์เรย์ไม่ใช่ศูนย์) * หมายถึงด้านล่างของสแต็กซึ่งเป็นวิธีการเรียกใช้วิธีแรก * ในลำดับ * * <p> เครื่องเสมือนบางเครื่องอาจละเว้นหนึ่งเฟรม * หรือมากกว่านั้นจากการติดตามสแต็ก ในกรณีที่รุนแรง * เครื่องเสมือนที่ไม่มีข้อมูลการติดตามสแต็กที่เกี่ยวข้องกับ * ที่สามารถโยนได้นี้ได้รับอนุญาตให้ส่งคืนอาร์เรย์ที่มีความยาวเป็นศูนย์จากวิธี * นี้ โดยทั่วไปอาร์เรย์ที่ส่งคืนโดยวิธีนี้จะ * มีองค์ประกอบหนึ่งสำหรับทุกเฟรมที่จะพิมพ์โดย * <tt> printstacktrace </tt> * * @return องค์ประกอบของการติดตามสแต็กที่แสดงถึงการติดตามสแต็ก * ที่เกี่ยวข้องกับการโยนได้นี้ * @Since 1.4 */ Public StackTraceElement [] getStackTrace () {return (stacktraceElement []) getourStackTrace (). clone (); } stackTraceElement แบบซิงโครไนซ์ส่วนตัว [] getourStackTrace () {// เริ่มต้นการติดตามสแต็กหากนี่คือการโทรครั้งแรกไปยังวิธีนี้ถ้า (stacktrace == null) {int depth = getStackTracePth (); stacktrace = stacktracelement ใหม่ [ความลึก]; สำหรับ (int i = 0; i <depth; i ++) stacktrace [i] = getStackTraceElement (i); } return stacktrace; } /** * ส่งคืนจำนวนองค์ประกอบในการติดตามสแต็ก (หรือ 0 ถ้าสแต็ก * ไม่สามารถใช้งานได้) * * การป้องกันแพ็คเกจสำหรับใช้งานโดย SharedSecrets */ native int getStackTracedEpth (); /*** ส่งคืนองค์ประกอบที่ระบุของการติดตามสแต็ก * * การป้องกันแพ็คเกจสำหรับใช้งานโดย SharedSecrets * * ดัชนีดัชนี @param ขององค์ประกอบที่จะส่งคืน * @throws indexoutofboundsexception ถ้า <tt> ดัชนี <0 || * index> = getStackTracedEpth () </tt> */ native stacktraceElement getStackTraceElement (INT ดัชนี); /*** ส่งคืนคำอธิบายสั้น ๆ ของการโยนได้นี้ * ผลลัพธ์คือการต่อกันของ: * <ul> * <li> คลาส {@linkplain #getName () ชื่อ} ของคลาสของวัตถุนี้ * <li> ":" (ลำไส้ใหญ่และพื้นที่) * <li> ผลลัพธ์ของการเรียกใช้วัตถุนี้ {@link #getLocalizedMessage} * <tt> null </tt> จากนั้นเพียงแค่ * ชื่อคลาสจะถูกส่งคืน * * @return การแสดงสตริงของการโยนที่สามารถโยนได้นี้ */ สตริงสาธารณะ toString () {string s = getClass (). getName (); ข้อความสตริง = getLocalizedMessage (); return (ข้อความ! = null)? (s + ":" + ข้อความ): s; -จากซอร์สโค้ดมันเกือบจะสิ้นสุดลง วิธี FillInstackTrace () เป็นวิธีการดั้งเดิม วิธีนี้จะเรียกภาษา C พื้นฐานส่งคืนวัตถุที่โยนได้วิธีการทอร์ตริ่งและส่งคืนคำอธิบายสั้น ๆ ของสิ่งที่โยนได้ ในวิธี getStackTrace และ getourstacktrace วิธีการดั้งเดิม getStackTraceElement เรียกว่า วิธีนี้ส่งคืนข้อมูลองค์ประกอบสแต็กที่ระบุดังนั้นกระบวนการนี้จะต้องใช้ประสิทธิภาพ จากนั้นเราสามารถเขียนวิธี ToString และวิธีการ FillInstackTrace ในข้อยกเว้นที่กำหนดเองและส่งออกโดยตรงโดยไม่ได้รับข้อมูลข้อยกเว้นจากสแต็ก นี่ไม่ใช่ "หนัก" สำหรับระบบและโปรแกรมและเป็นวิธีที่ดีมากในการเพิ่มประสิทธิภาพประสิทธิภาพ แล้วจะมีลักษณะอย่างไรถ้ามีข้อยกเว้นที่กำหนดเองเกิดขึ้น? โปรดดูด้านล่าง:
@Test โมฆะสาธารณะ testException () {ลอง {string str = null; System.out.println (str.charat (0)); } catch (Exception e) {โยน appexception ใหม่ ("000001", "ข้อยกเว้นตัวชี้ว่าง"); -จากนั้นเมื่อข้อยกเว้นผิดปกติระบบจะพิมพ์ข้อมูลข้อยกเว้นที่กำหนดเองของเรา:
000001 [ข้อยกเว้นตัวชี้ NULL] กระบวนการเสร็จสิ้นด้วยรหัสออก -1
ดังนั้นจึงมีความรัดกุมโดยเฉพาะอย่างยิ่งและเพิ่มประสิทธิภาพประสิทธิภาพของโปรแกรมระบบทำให้โปรแกรม "หนัก" น้อยลงดังนั้นระบบที่มีข้อกำหนดด้านประสิทธิภาพพิเศษจึงจำเป็น รีบและปรับแต่งข้อยกเว้นของคุณเอง!
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com