Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不使用try-catch的情况下使用Java时忽略可能的ClassNotFoundException_Java_Reflection_Classnotfoundexception - Fatal编程技术网

如何在不使用try-catch的情况下使用Java时忽略可能的ClassNotFoundException

如何在不使用try-catch的情况下使用Java时忽略可能的ClassNotFoundException,java,reflection,classnotfoundexception,Java,Reflection,Classnotfoundexception,我有一个类,其方法仅在该类存在时才返回该类,如果未加载类路径,调用该方法将生成由ClassNotFoundException引起的NoClassDefFoundError异常(这是正确的,因为它不是强制性的) 当某些方法(或字段)可能未加载到类路径中时,如何从类#getMethods()获取方法?在检索方法/字段时是否可以忽略它们 请注意,使用try-catch将完全阻止整个过程工作,因此这不是解决方案 下面是我加载类的方式: try { String name = StringUtil

我有一个类,其方法仅在该类存在时才返回该类,如果未加载类路径,调用该方法将生成由ClassNotFoundException引起的
NoClassDefFoundError
异常(这是正确的,因为它不是强制性的)

当某些方法(或字段)可能未加载到类路径中时,如何从类#getMethods()获取方法?在检索方法/字段时是否可以忽略它们

请注意,使用try-catch将完全阻止整个过程工作,因此这不是解决方案

下面是我加载类的方式:

try {
    String name = StringUtil.format("Nifty{0}", (isBungee ? "Bungee" : "Bukkit"));
    Reflection main = new Reflection(name, StringUtil.format("net.netcoding.{0}", name.toLowerCase())); // net.netcoding.niftybukkit.NiftyBukkit
    Object mainObj = main.invokeMethod("getPlugin", null); // See below
    logger = (Logger)main.invokeMethod("getLogger", mainObj);
} catch (Exception ex) { }
以下是尝试在反射中定位方法的两个位:

public class Reflection {

    private static final transient ConcurrentHashMap<Class<?>, Class<?>> CORRESPONDING_TYPES = new ConcurrentHashMap<>();
    private final String className;
    private final String subPackage;
    private final String packagePath;

    static {
        CORRESPONDING_TYPES.put(Byte.class, byte.class);
        CORRESPONDING_TYPES.put(Short.class, short.class);
        CORRESPONDING_TYPES.put(Integer.class, int.class);
        CORRESPONDING_TYPES.put(Long.class, long.class);
        CORRESPONDING_TYPES.put(Character.class, char.class);
        CORRESPONDING_TYPES.put(Float.class, float.class);
        CORRESPONDING_TYPES.put(Double.class, double.class);
        CORRESPONDING_TYPES.put(Boolean.class, boolean.class);
    }

    public Reflection(String className, String packagePath) {
        this(className, "", packagePath);
    }

    public Reflection(String className, String subPackage, String packagePath) {
        this.className = className;
        this.subPackage = StringUtil.stripNull(subPackage).replaceAll("\\.$", "").replaceAll("^\\.", "");
        this.packagePath = packagePath;
    }

    public String getClassName() {
        return this.className;
    }

    public String getClassPath() {
        return this.getPackagePath() + (StringUtil.notEmpty(this.subPackage) ? "." + this.subPackage : "") + "." + this.getClassName();
    }

    public Class<?> getClazz() throws Exception {
        return Class.forName(this.getClassPath());
    }

    public Object invokeMethod(String name, Object obj, Object... args) throws Exception {
        return this.getMethod(name, toPrimitiveTypeArray(args)).invoke(obj, args);
    }

    private static Class<?> getPrimitiveType(Class<?> clazz) {
        return clazz != null ? CORRESPONDING_TYPES.containsKey(clazz) ? CORRESPONDING_TYPES.get(clazz) : clazz : null;
    }

    public Method getMethod(String name, Class<?>... paramTypes) throws Exception {
        Class<?>[] types = toPrimitiveTypeArray(paramTypes);

        // In this example, this.getClazz() simply returns
        // a Class of net.netcoding.niftybukkit.NiftyBukkit
        // this.getClazz().getMethods() throws the ClassNotFOundException
        // I want to still access the methods, even if one of them is not available
        for (Method method : this.getClazz().getMethods()) {
            Class<?>[] methodTypes = toPrimitiveTypeArray(method.getParameterTypes());

            if (method.getName().equals(name) && isEqualsTypeArray(methodTypes, types)) {
                method.setAccessible(true);
                return method;
            }
        }

        System.out.println(StringUtil.format("The method {0} was not found with parameters {1}!", name, Arrays.asList(types)));
        return null;
    }
公共类反射{
私有静态最终瞬态ConcurrentHashMap>对应的_类型=新ConcurrentHashMap();
私有最终字符串类名;
私有最终字符串子包;
私有最终字符串包路径;
静止的{
对应的_类型put(Byte.class,Byte.class);
对应的_类型put(Short.class,Short.class);
对应的_类型put(Integer.class,int.class);
对应的_类型put(Long.class,Long.class);
对应的_类型.put(Character.class,char.class);
对应的_类型put(Float.class,Float.class);
对应的_类型put(Double.class,Double.class);
对应的_类型.put(Boolean.class,Boolean.class);
}
公共反射(字符串类名称、字符串包路径){
这(类名称,“,packagePath);
}
公共反射(字符串类名称、字符串子包、字符串包路径){
this.className=className;
this.subPackage=StringUtil.stripNull(subPackage).replaceAll(“\\\.$”,“”)。replaceAll(“^\.”,“”);
this.packagePath=packagePath;
}
公共字符串getClassName(){
返回this.className;
}
公共字符串getClassPath(){
返回this.getPackagePath()+(StringUtil.notEmpty(this.subPackage)?“+this.subPackage:”)+“+this.getClassName();
}
公共类getClazz()引发异常{
返回Class.forName(this.getClassPath());
}
公共对象invokeMethod(字符串名称、对象obj、对象…args)引发异常{
返回此.getMethod(名称,toPrimitiveTypeArray(args)).invoke(obj,args);
}
私有静态类getPrimitiveType(类clazz){
return clazz!=null?对应的_类型。containsKey(clazz)?对应的_类型。get(clazz):clazz:null;
}
公共方法getMethod(字符串名称、类…paramTypes)引发异常{
类[]类型=TopPrimitiveTypeArray(paramTypes);
//在本例中,this.getClazz()只返回
//一类net.netcoding.niftybukkit.niftybukkit
//这个.getClazz().getMethods()抛出ClassNotFOundException
//我仍然希望访问这些方法,即使其中一个不可用
对于(方法:this.getClazz().getMethods()){
类[]methodTypes=toPrimitiveTypeArray(method.getParameterTypes());
if(method.getName().equals(name)和&isequalTypeArray(methodTypes,types)){
方法setAccessible(true);
返回法;
}
}
System.out.println(StringUtil.format(“找不到参数为{1}!、名称、数组、asList(类型))的方法{0}”);
返回null;
}
关于:

public Class<?> getClazz() {
    try {
        return Class.forName(this.getClassPath());
    } catch (ClassNotFoundException e) {
        // ignore or better log
    }
    return null;
}
public类getClazz(){
试一试{
返回Class.forName(this.getClassPath());
}catch(classnotfounde异常){
//忽略或更好地记录
}
返回null;
}
随后:

Class<?> clazz = this.getClazz();
if (clazz != null) {
    for (Method method : clazz.getMethods()) {
        // ....
    }
}
Class clazz=this.getClazz();
if(clazz!=null){
for(方法:clazz.getMethods()){
// ....
}
}

如果保留您的设计,您将创建依赖于非保证行为的不可移植代码

如果一个方法的返回类型引用了一个不可用的类,那么如果该方法的代码试图处理该类的缺失(return
null
或其他什么),或者该方法没有被调用,那么它就没有帮助

不仅是
类.getMethods
可能失败,还可能导致整个类不可用。问题是,如果无法解析直接引用的类,JVM可以自由决定何时抛出错误。一个有效点是类加载时间,因此,对于不同的JVM,可以实现这样的解析策略y、 您甚至无法调用
Class.getMethods()

让有效代码处理可选类的唯一方法是将直接引用的类与可选类解耦,例如

public static BaseType getOptionalFeature() {
  try {
    return (BaseType)Class.forName("OptionalType").newInstance();
  } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
    return null;
  }
}
假设
OptionalType
扩展或实现了
BaseType
,那么重要的一点是
BaseType
是一个始终可用的类型,所有非可选代码总是通过
BaseType
引用可选功能。您可能会有更多的代码直接访问
OptionalType
,这是您认为的如果
OptionalType
不可用,则不调用e,但也必须使用动态类加载将其与非可选代码分离


否则,您在急切地解析JVM时会面临完全失败的风险,而在懒洋洋地解析像Oracle这样的JVM时会面临虚假失败的风险。如果您不调用有问题的方法,它不会立即失败这一事实并不能保证您的行为——这只是一种优化。

要么加载一个类,要么定义所有方法ods是可用的,或者它没有加载,然后你就什么都没有了。你说有些方法(或字段)可能没有加载到类路径中是什么意思?我提供了一个帮助器方法来检索注册的服务,但是如果插件不在那里,它就不会被使用;但是