如何捕获NoClassDefFoundError异常以使用可选案例?

时间:2017-04-09 13:05:34

标签: java android android-studio

有时我致电NoClassDefFoundError会引发Toast例外,我会抓住它然后显示public static void show(View v, CharSequence snapbarString, CharSequence snapbarTitle) { try { Snackbar.make(v, snapbarString, Snackbar.LENGTH_LONG) .setAction(snapbarTitle, new View.OnClickListener() { @Override public void onClick(View v) { // no implementation required } }).show(); } catch (Exception e) { Toast.makeText(v.getContext(), snapbarString, Toast.LENGTH_LONG).show(); } } ,但我的下面的代码不能抓住这个例外,我该怎么做?

# a is your 1-D binary tensor
r = tf.range(1, a.get_shape()[0].value)
result = a / r

1 个答案:

答案 0 :(得分:2)

如何捕获NoClassDefFoundError?

NoClassDefFoundErrorError而不是Exception。如果你真的想抓住它,你需要把它作为Error而不是Exception来抓住它。

 try {
    Snackbar.make(v, snapbarString, Snackbar.LENGTH_LONG)
            .setAction(snapbarTitle, new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // no implementation required
                }
            }).show();
} catch (NoClassDefFoundError e) {
    Toast.makeText(v.getContext(), snapbarString, Toast.LENGTH_LONG).show();
}

如果库不存在,如何使用可选案例?

如果你想使用本地吐司作为可选的,isSnackbarPresent的优点是只检查库是否只出现一次。例如:

private static final boolean isSnackbarPresent; 

static{                                                             
      isSnackbarPresent = classPresent("${package}.Snackbar");
}

private static boolean classPresent(String className) {
    try {
        ClassLoader.getSystemClassLoader().loadClass(className);
        return true;
    } catch (ClassNotFoundException ex) {
        return false;
    }
}

public static void show(View v
                       , CharSequence snapbarString
                       , CharSequence snapbarTitle) {

  if(isSnackbarPresent){
    Snackbar.make(v, snapbarString, Snackbar.LENGTH_LONG)
            .setAction(snapbarTitle, new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // no implementation required
                }
            }).show();
  }else{
    Toast.makeText(v.getContext(), snapbarString, Toast.LENGTH_LONG).show();
  }
}

高级使用可选案例

如果您不想检查isSnackbarPresent每个调用的show方法,您可以这样做:

public static void show(View v
                       , CharSequence snapbarString
                       , CharSequence snapbarTitle) {
    toaster.show(v, snapbarString, snapbarTitle);
}

private static final Toaster toaster = classPresent("${package}.Snackbar") 
                                     ? snackbar() 
                                     : locally();

private static Toaster locally() {
    return (view, message, title) -> Toast.makeText(view.getContext()
                                                   , message
                                                   , Toast.LENGTH_LONG).show(); 
}

private static Toaster snackbar() {
    View.OnClickListener NOTHING = (view)->{};
    return (view, message, title) -> {
        Snackbar.make(view, message, Snackbar.LENGTH_LONG)
                .setAction(title, NOTHING).show();
    };
}

interface Toaster {
    void show(View view, CharSequence message, CharSequence title);
}

private static boolean classPresent(String className) {
    try {
        ClassLoader.getSystemClassLoader().loadClass(className);
        return true;
    } catch (ClassNotFoundException ex) {
        return false;
    }
}

增强

这个模式是如此灵活,可以从所有烤面包机中选择一个可用的Toaster,例如:

interface ToasterProvider{
   /**
    *  @see classPresent(String)
    *  @return return true if the library is presented in classpath
    */
   boolean isPresent();
   /**
    * @throws NoSuchElementException thrown if toaster library is not present
    */
   Toaster toaster() throws NoSuchElementException;
}

List<ToasterProvider>  providers = ...;

Toaster toaster = providers.stream()
                           .filter(ToasterProvider::isPresent)
                           .findFirst().map(ToasterProvider::toaster)
                           .orElse(locally());