مقدمة
في عملية تعلم Java ، أعتقد أن الجميع تعلموا الفصل بشأن الاستثناءات ، ولن أتحدث عن الخصائص الأساسية واستخدام الاستثناءات هنا. ما هو الاستثناء؟ لا أعرف كيف يفهمها الجميع. ما أفهمه بسيط للغاية ، أي المواقف غير الطبيعية. على سبيل المثال ، أنا رجل الآن ، لكن لدي شيء فريد للنساء. في رأيي ، هذا بالتأكيد خلل ولا يمكنني تحمله. أعتقد أن الجميع يمكنهم فهمه واستخدامه بشكل صحيح.
ومع ذلك ، إذا كانت معالجة الاستثناء الأساسية البصرية واستخدامها غير كافية ، فليس من المخيف أن يحدث في العمل. في بعض الأحيان يكون من الضروري استخدام استثناءات لدفع معالجة الأعمال. على سبيل المثال: عند استخدام قاعدة بيانات ذات قيود فريدة ، إذا تم إدراج بيانات مكررة ، فيمكن معالجتها عن طريق التقاط استثناء القيد الفريد DupLicateKeyException. في هذا الوقت ، يمكن إلقاء الحالة المقابلة على طبقة الاتصال في طبقة الخادم ، وستقوم الطبقة العليا بمعالجةها وفقًا للحالة المقابلة. لذلك ، في بعض الأحيان تكون الاستثناءات طريقة قيادة للعمل.
بعض الناس سوف يخرجون الاستثناء بعد التقاط الاستثناء. أتساءل عما إذا كان الطلاب الحذرين قد لاحظوا شيئًا ما. ما هو استثناء الإخراج؟
هذا استثناء شائع:
java.lang.arithmeticexception: / by Zero at greenhouse.exceptiontest.testException (استثناء est.java:16) في sun.reflect.nativemethodaccessoriMpl.invoke0 (الطريقة الأصلية) في sun.reflect.nativempl.invoke Sun.Reflect.DelegatingMethodAccessorImpl.invoke (devatingMethodAccessorImpl.java:25) في java.lang.reflect.method.invoke (method.java:597) على org.junit.runners.model.frameworkmeToD $ 1. في org.junit.internal.runners.model.reflectivecallable.run (respectivecallable.java:15) في org.junit.runners.model.frameworkmethod.invokeexplosivaly (Frameworkmethod.java:41) org.junit.internal.runners.statements.invokemethod.evaluate (invokemethod.java:20) at org.junit.runners.blockjunit4classrunner.Runchild (blockjunit4classrunner.java:76) at org.junit.runners.blockjunit4classrunner.runchild (blockjunit4classrunner.java:50) at org.junit.runners.parentrunner $ $ (infertrunner.java:193) في org.junit.runners.parentrunner org.junit.runners.parentrunner.runchildren (parentrunner.java:191) في org.junit.runners.parentrunner.Access 000 $ (ParentRunner.Java:42) في org.junit.runners.parentrunner $ 2.evaluit org.junit.runners.parentrunner.run (parentrunner.java:236) at org.junit.runner.junitcore.run (junitcore.java:157) at com.intellij.junit4.junit4ideatestertrunner.startrunner. com.intellij.rt.execution.junit.ideatestrunner $ Repeater.StarTrunnerWithargs (ideatestrunner.java:47) على com.intellij.rt.execution.junit.junitstarter.preparestramsand (junitstarter.java:242) at com.intellij.rt.execution.junit.junitstarter.main (junitstarter.java:70)
استثناء مؤشر فارغ:
java.lang.nullpointerxception في greenhouse.exceptiontest.testException (استثناء est.java:16) في sun.reflect.nativemethodaccoriMpl.Invoke0 (الطريقة الأصلية) في sun.reflect.nativemetcessorimpl.invoke Sun.Reflect.DelegatingMethodAccessorImpl.invoke (devatingMethodAccessorImpl.java:25) في java.lang.reflect.method.invoke (method.java:597) على org.junit.runners.model.frameworkmeToD $ 1. في org.junit.internal.runners.model.reflectivecallable.run (respectivecallable.java:15) في org.junit.runners.model.frameworkmethod.invokeexplosivaly (Frameworkmethod.java:41) org.junit.internal.runners.statements.invokemethod.evaluate (invokemethod.java:20) at org.junit.runners.blockjunit4classrunner.Runchild (blockjunit4classrunner.java:76) at org.junit.runners.blockjunit4classrunner.runchild (blockjunit4classrunner.java:50) at org.junit.runners.parentrunner $ $ (infertrunner.java:193) في org.junit.runners.parentrunner org.junit.runners.parentrunner.runchildren (parentrunner.java:191) في org.junit.runners.parentrunner.Access 000 $ (ParentRunner.Java:42) في org.junit.runners.parentrunner $ 2.evaluit org.junit.runners.parentrunner.run (parentrunner.java:236) at org.junit.runner.junitcore.run (junitcore.java:157) at com.intellij.junit4.junit4ideatestertrunner.startrunner. com.intellij.rt.execution.junit.ideatestrunner $ Repeater.StarTrunnerWithargs (ideatestrunner.java:47) على com.intellij.rt.execution.junit.junitstarter.preparestramsand (junitstarter.java:242) at com.intellij.rt.execution.junit.junitstarter.main (junitstarter.java:70)
هل وجدت ميزة مفادها أن إخراج الاستثناء هو الموقع الذي يحدث فيه الاستثناء بدقة ، ويتم طباعة الكثير من مكالمات عملية التنفيذ لاحقًا. من أين تأتي هذه المعلومات؟ يتم الحصول على هذه المعلومات من المكدس. عند طباعة سجل الاستثناء ، سيتم الحصول على معلومات الاتصال هذه من المكدس. من الجيد بالطبع أن نكون قادرين على تحديد موقع الاستثناءات بدقة ، ولكن في بعض الأحيان عندما ننظر في أداء البرنامج وبعض المتطلبات ، لا نحتاج أحيانًا إلى طباعة هذه المعلومات تمامًا ، والحصول على المعلومات المقابلة من مكدس استدعاء الطريقة ، وهو استهلاك الأداء. بالنسبة لبعض البرامج ذات المتطلبات العالية الأداء ، يمكننا تحسين أداء البرنامج في هذا الجانب تمامًا.
إذن كيف تتجنب إخراج معلومات المكدس هذه؟ ثم يمكن أن تحل الاستثناءات المخصصة هذه المشكلة:
أولاً ، يحتاج الاستثناء التلقائي إلى ورث RunTimeException ، ثم إعادة كتابة طريقة FillInstackTrace و ToString. على سبيل المثال ، أقوم بتحديد استثناء AppException أدناه:
package com.green.monitor.common.Exception ؛ استيراد java.text.messageformat ؛/*** فئة الاستثناء المخصصة*/الفئة العامة appexception يمتد runtimeexception {private boolean issuccess = false ؛ مفتاح السلسلة الخاص ؛ معلومات السلسلة الخاصة ؛ Public AppException (مفتاح السلسلة) {super (key) ؛ this.key = المفتاح ؛ this.info = المفتاح ؛ } public AppException (مفتاح السلسلة ، رسالة السلسلة) {super (messageformat.format ("{0} [{1}]" ، مفتاح ، رسالة))) ؛ this.key = المفتاح ؛ this.info = message ؛ } public appexception (رسالة السلسلة ، مفتاح السلسلة ، معلومات السلسلة) {super (message) ؛ this.key = المفتاح ؛ this.info = info ؛ ) } السلسلة العامة getKey () {return Key ؛ } public void setKey (مفتاح سلسلة) {this.key = key ؛ } السلسلة العامة getInfo () {return info ؛ } public void setInfo (string info) {this.info = info ؛ } Override public fillInstackTrace () {return this ؛ } Override Public String ToString () {return messageformat.format ("{0} [{1}]" ، this.key ، this.info) ؛ }}فلماذا إعادة كتابة FillInstackTrace ، وطرق tostring؟ دعونا نلقي نظرة أولاً على ما هو رمز المصدر.
الطبقة العامة RunTimeException يمتد الاستثناء {static Final Long SerialVersionuid = -7034897190745766939L ؛ /** يقوم بإنشاء استثناء جديد للوقت مع <code> null </code> كرسالة* التفاصيل. لا يتم تهيئة السبب ، وقد يتم تهيئتها لاحقًا عن طريق مكالمة إلى {link #InitCause}. */ public RunTimeException () {super () ؛ } /** يقوم بإنشاء استثناء جديد لوقت التشغيل مع رسالة التفاصيل المحددة. * لا يتم تهيئة السبب ، ويمكن تهيئتها عن طريق مكالمة * إلى {link #InitCause}. * * param رسالة رسالة التفاصيل. يتم حفظ رسالة التفاصيل من أجل * الاسترجاع لاحقًا بواسطة طريقة {link #getmessage ()}. */ public RunTimeException (رسالة سلسلة) {super (message) ؛ } /** * يقوم بإنشاء استثناء جديد لوقت التشغيل مع رسالة التفاصيل المحددة و * السبب. <p> لاحظ أن الرسالة التفصيلية المرتبطة بـ * <code> السبب </code> هي <i> not </i> تم دمجها تلقائيًا في رسالة تفاصيل استثناء وقت التشغيل. * * param message رسالة التفاصيل (التي يتم حفظها لاسترجاعها لاحقًا * بواسطة {link #getmessage ()} طريقة). * param تسبب في السبب (الذي يتم حفظه لاسترجاعه لاحقًا بواسطة طريقة * {link #getcause ()}). (A <tt> null </tt> قيمة * مسموح بها * ، وتشير إلى أن السبب غير موجود أو غير معروف.) * since 1.4 */ public RunTimeException (رسالة سلسلة ، سبب قابلة للارتفاع) {super (message ، cause) ؛ }/** يقوم بإنشاء استثناء جديد لوقت التشغيل مع السبب المحدد ورسالة * التفاصيل من <tt> (السبب == null؟ null: cause.toString ()) </tt> * (التي تحتوي عادة على فئة ورسالة تفصيلية لـ * <TT> السبب </tt>). يعد هذا المُنشئ مفيدًا لاستثناءات وقت التشغيل * التي لا تزيد قليلاً عن الأغلفة للأقوام الأخرى. * * param تسبب في السبب (الذي يتم حفظه لاسترجاعه لاحقًا بواسطة طريقة * {link #getcause ()}). (A <tt> null </tt> قيمة * مسموح بها * ، وتشير إلى أن السبب غير موجود أو غير معروف.) * since 1.4 */ public RuntimeException (سبب رمي) {super (السبب) ؛ }}يرث RunTimeException استثناء ، لكنه يطلق فقط طريقة الفئة الأصل ، ولا يقوم بأي عمليات أخرى. لذلك ، دعنا نستمر في رؤية ما يجري باستثناء؟
يمتد استثناء الطبقة العامة القابلة للتسمية {Static Final Long SerialVersionuid = -3387516993124229948L ؛ /*** يبني استثناءً جديدًا مع <code> null </code> كرسالة تفصيلية. * لا يتم تهيئة السبب ، ويمكن تهيئتها لاحقًا عن طريق مكالمة * إلى {link #InitCause}. */ استثناء عام () {super () ؛ } /*** يبني استثناءً جديدًا مع رسالة التفاصيل المحددة. لا يتم تهيئة السبب * ، وقد يتم تهيئتها لاحقًا بواسطة * مكالمة إلى {link #InitCause}. * * param رسالة رسالة التفاصيل. يتم حفظ رسالة التفاصيل من أجل * الاسترجاع لاحقًا بواسطة طريقة {link #getmessage ()}. */ استثناء عام (رسالة سلسلة) {super (message) ؛ } /** * يبني استثناءً جديدًا مع رسالة التفاصيل المحددة و * السبب. <p> لاحظ أن الرسالة التفصيلية المرتبطة بـ * <code> السبب </code> هي <i> لا </i> تم دمجها تلقائيًا في رسالة تفاصيل هذا الاستثناء. * * param message رسالة التفاصيل (التي يتم حفظها لاسترجاعها لاحقًا * بواسطة {link #getmessage ()} طريقة). * param تسبب في السبب (الذي يتم حفظه لاسترجاعه لاحقًا بواسطة طريقة * {link #getcause ()}). (A <tt> null </tt> قيمة * مسموح بها * ، وتشير إلى أن السبب غير موجود أو غير معروف.) * since 1.4 */ استثناء عام (رسالة سلسلة ، سبب قابلة للارتفاع) {super (message ، cause) ؛ }/** * يبني استثناءً جديدًا مع السبب المحدد ورسالة * تفاصيل * من <tt> (السبب == null؟ null: cause.toString ()) </tt> (الذي يحتوي عادة على فئة ورسالة تفصيلية لـ <tt> السبب </tt>). * هذا المُنشئ مفيد للاستثناءات التي لا تزيد قليلاً عن * مغلفة للأقراص الأخرى (على سبيل المثال ، {link * java.security.privilegedActionException}). * * param تسبب في السبب (الذي يتم حفظه لاسترجاعه لاحقًا بواسطة طريقة * {link #getcause ()}). (A <tt> null </tt> قيمة * مسموح بها * ، وتشير إلى أن السبب غير موجود أو غير معروف.) * since 1.4 */ public issission (سبب رمي) {super (cause) ؛ }}كما يتضح من الكود المصدري ، تسمى طريقة الفئة الأصل مباشرة باستثناء. مثل RunTimeException ، لم أفعل شيئًا بالفعل. لذلك دعونا نلقي نظرة على ما يجري في رمي:
الطبقة العامة الأدوات القابلة للتسمية {public throwable (رسالة سلسلة) {fillInStackTrace () ؛ التفاصيل = رسالة ؛ } /*** يملأ تتبع مكدس التنفيذ. تسجل هذه الطريقة في هذا * <code> رمي </code> معلومات الكائن حول الحالة الحالية لـ * إطارات المكدس للمعلومات الحالية. * * regurn مرجع إلى هذا المثيل <code> قابل للتسمية </code>. * see java.lang.throwable#printStackTrace () */ 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 = getStackTracedEpth () ؛ StackTrace = stackTraceElement جديد [العمق] ؛ لـ (int i = 0 ؛ i <depth ؛ i ++) stacktrace [i] = getStackTraceElement (i) ؛ } إرجاع stacktrace ؛ } /** * إرجاع عدد العناصر في تتبع المكدس (أو 0 إذا كان تتبع المكدس * غير متوفر). * * حماية الحزمة للاستخدام من قبل المشاركين. */ native int getStackTracedEpth () ؛ /*** إرجاع العنصر المحدد من تتبع المكدس. * * حماية الحزمة للاستخدام من قبل المشاركين. * * فهرس فهرس Param للعنصر للعودة. * throws indexoutofBoundSexception if <tt> index <0 || * index> = getStackTracePth () </tt> */ stackTraceElement الأصلي getStackTraceElement (int index) ؛ /*** يعيد وصفًا قصيرًا لهذا الرمي. * والنتيجة هي تسلسل: * <ul> * <li> {linkplain class #getName () name} من فئة هذا الكائن * <li> <tt> null </tt> ، ثم فقط * يتم إرجاع اسم الفصل. * * @إعادة تمثيل سلسلة من هذا الرمي. */ public string toString () {string s = getClass (). getName () ؛ رسالة سلسلة = getLocalizedMessage () ؛ العودة (الرسالة! = فارغة)؟ (S + ":" + رسالة): s ؛ }من رمز المصدر ، يكون تقريبًا خلال نهاية الرمي. طريقة FillInstackTrace () هي طريقة أصلية. ستستدعي هذه الطريقة لغة C الأساسية ، وإرجاع كائن قابل للارتفاع ، وطريقة tostring ، ويعيد وصفًا قصيرًا للرمي. في طريقة getStackTrace و getourstacktrace ، تسمى الطريقة الأصلية getStackTraceElement. تقوم هذه الطريقة بإرجاع معلومات عنصر المكدس المحدد ، لذلك يجب أن تستهلك هذه العملية الأداء. بعد ذلك ، يمكننا إعادة كتابة طريقة ToString وطريقة FillInstackTrace في استثناءات مخصصة وإخراجها مباشرة دون الحصول على معلومات استثناء من المكدس. هذا ليس "ثقيلًا" نسبيًا للنظام والبرنامج ، وهو وسيلة جيدة للغاية لتحسين الأداء. إذن كيف يبدو ذلك إذا حدث استثناء مخصص؟ يرجى الاطلاع أدناه:
test public void testException () {try {String str = null ؛ System.out.println (str.charat (0)) ؛ } catch (استثناء e) {رمي appexception جديد ("000001" ، "استثناء مؤشر فارغ") ؛ }}ثم عندما يكون الاستثناء غير طبيعي ، سيقوم النظام بطباعة معلومات الاستثناء المخصصة لدينا:
000001 [استثناء مؤشر فارغ] انتهت العملية برمز الخروج -1
لذلك ، فهو موجز بشكل خاص ويحسن أداء برنامج النظام ، مما يجعل البرنامج أقل "ثقلًا" ، وبالتالي فإن النظام ذو متطلبات الأداء الخاصة مطلوب. اسرع وتخصيص استثناء الخاص بك!
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.