التفاف الاستثناءات التي كتبها استثناءات وقت التشغيل مع الشرح

StackOverflow https://stackoverflow.com/questions/1052568

سؤال

هل هناك طريقة لتعليم طريقة لذلك كل الاستثناءات القيت يتم تحويلها إلى استثناء وقت التشغيل التلقائى؟

@MagicAnnotation
// no throws clause!
void foo()
{
  throw new Exception("bar")'
}
هل كانت مفيدة؟

المحلول

وبأي حال من الأحوال للقيام بذلك، على الأقل حتى الآن يمكنني استخدام الحل مثل هذا (المبسطة):

@SuppressWarnings({"rawtypes", "unchecked"})
public class Unchecked {
    public static interface UncheckedDefinitions{
        InputStream openStream();
        String readLine();
            ...
    }

  private static Class proxyClass = Proxy.getProxyClass(Unchecked.class.getClassLoader(), UncheckedDefinitions.class);

    public static UncheckedDefinitions unchecked(final Object target){
        try{
            return (UncheckedDefinitions) proxyClass.getConstructor(InvocationHandler.class).newInstance(new InvocationHandler(){
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (target instanceof Class){
                        return MethodUtils.invokeExactStaticMethod((Class) target, method.getName(), args);
                    }

                  return MethodUtils.invokeExactMethod(target, method.getName(), args);
                }
            });
        }
        catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}

واستخدام يشبه:

import static ....Unchecked.*;

...

Writer w = ...;
unchecked(w).write(str, off, len);

والحيلة هي أن واجهة هو "الانتهاء أبدا"، وفي كل مرة كنت بحاجة الى طريقة دون رادع في مكان ما، وأنا التفاف أن الكائن في حالها والسماح IDE توليد توقيع الأسلوب في الواجهة.

والتنفيذ ومن ثم عام (عاكس و "بطيء" ولكن عادة بسرعة كافية)

وهناك بعض التعليمات البرمجية في مرحلة ما بعد المعالجات وبايت كود النساجين ولكن هذا لم يكن من الممكن (ولا حتى اوب أو لغة أخرى استنادا JVM) لمشروعي الحالي، لذلك كان هذا "اخترع".

نصائح أخرى

و

ومشروع لومبوك @SneakyThrows وربما ما كنت تبحث عنه. لا التفاف حقا استثناء الخاص بك (لأنه يمكن أن يكون مشكلة في الكثير من الحالات)، فقط لا رمي خطأ أثناء الترجمة.

@SneakyThrows
void foo() {
    throw new Exception("bar")'
}

ويمكنك القيام بذلك مع AspectJ. قمت بتعريف joinpoint (في هذه الحالة الاحتجاج على طريقة فو) و "تليين" الاستثناء.

تعديل لوضع قليلا على هذا:

ويقول لديك Bar الطبقة يلي:

public class Bar {

    public void foo() throws Exception {
    }
}

... وكان لديك اختبار مثل هذا:

import junit.framework.TestCase;

public class BarTest extends TestCase {

    public void testTestFoo() {
        new Bar().foo();
    }
}

وثم من الواضح أن الاختبار لن ترجمة. وسوف تعطي خطأ:

Unhandled exception type Exception  BarTest.java(line 6)

والآن للتغلب على هذه مع AspectJ، أن تكتب جانب بسيط جدا:

public aspect SoftenExceptionsInTestCode {

    pointcut inTestCode() : execution(void *Test.test*());

    declare soft : Exception : inTestCode();
}

وأما الجانب يقول أساسا أن أي رمز من داخل اختبار (أي: الأسلوب الذي يبدأ ب "اختبار" في فئة التي تنتهي في "اختبار" والعوائد "الفراغ") يطرح استثناء يجب أن تكون مقبولة من قبل AspectJ مترجم. إذا حدث استثناء، وسيتم التفاف عليها والقيت باعتباره RuntimeException من قبل المجمع AspectJ.

والواقع، إذا قمت بتشغيل هذا الاختبار كجزء من مشروع AspectJ من داخل الكسوف (مع AJDT تثبيت) ثم فإن الاختبار تنجح، في حين دون الجانب لن حتى ترجمة.

وأعتقد أنه من الممكن مع بايت كود إعادة الهندسة، مترجم مخصصة أو ربما الجانب البرمجة الموجهة <سوب> 1 . في مخالفة للجافا، C # لديها استثناءات دون رادع فقط <سوب> 2 في

هل لي أن أسأل لماذا تريد قمع التحقق من الاستثناءات؟

<سوب> 1 وفقا ل<م> مارتن Winkels هذا ممكن.
<سوب> 2 في وهم التفكير في إدخال تلك التحقق منها، وفقا لبعض قناة 9 أفلام.

تعديل: بالنسبة السؤال: من الممكن بمعنى أنه يمكنك تعليم أساليب لعلم لهم ليكون مرشحا لقمع استثناء محددا. ثم يمكنك استخدام بعض الوقت الترجمة أو خدعة وقت التشغيل لتطبيق قمع الفعلي / التفاف.

ولكن، وكما لا أرى البيئة المحيطة قضيتك، التفاف استثناء في هذه الطرق قد تخلط بين العملاء من هذا الأسلوب - أنها قد لا تكون مستعدة للتعامل مع RuntimeException. على سبيل المثال: طريقة يطرح IOException وعملائك أدرك أنها FileNotFoundException لعرض مربع حوار خطأ. ولكن إذا كنت التفاف استثناء الخاص بك إلى RuntimeException، ويحصل على الحوار خطأ يظهر أبدا وربما كان يقتل الخيط المتصل أيضا. (IMHO).

والاستثناءات تم الفحص هي المسئولية لتنفيذ الأسلوب. تأخذ بعناية فائقة جدا هذه الحقيقة. إذا يمكنك عدم استخدام الحل القطع الأثرية من هذا القبيل.

ويمكنك القيام بذلك في أي حال عن طريق استخدام حقيقة أن Class.newInstance <م> لا التفاف على Exception القيت من قبل منشئ عدم الارجنتين في InvocationTargetException. بل يلقي عليه <م> بصمت :

class ExUtil {
  public static void throwSilent(Exception e) { //NOTICE NO THROWS CLAUSE
      tl.set(e);
      SilentThrower.class.newInstance(); //throws silently
  }

  private static ThreadLocal<Exception> tl = new ThreadLocal<Exception>();
  private static class SilentThrower {
      SilentThrower() throws Exception {
          Exception e = tl.get();
          tl.remove();
          throw e;
      }
  }
}

وبعد ذلك يمكنك استخدام هذه الأداة في أي مكان:

ExUtil.throwSilent(new Exception());
//or
try {
  ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }

وبالمناسبة، هذا هو <قوية> فكرة سيئة حقا : ل-)

وأنا استخدم نظام إنجاز / قالب من الكسوف التفاف أي كتلة من التعليمات البرمجية بسهولة.

وهنا هو القالب الخاص بي:

try { // Wrapp exceptions

${line_selection}${cursor}

} catch (RuntimeException e) { // Forward runtime exception
throw e;
} catch (Exception e) { // Wrap into runtime exception
throw new RuntimeException(
    "Exception wrapped in #${enclosing_method}", 
    e); 
}

ومع جافا 8 فإنه من السهل مثل: soften(() -> methodThatMayThrow())

HTTP: //iirekm.blogspot كوم / 2014/05 / الإصلاح-مشاكل مع جافا checked.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top