在java中如何判断一个类是否存在

来源:互联网 发布:笑傲江湖ol辅助软件 编辑:程序博客网 时间:2024/04/20 09:11

Apache Commons-Logging 中的解决方案:

public class LogSource {    // ------------------------------------------------------- Class Attributes    static protected Hashtable logs = new Hashtable();    /** Is log4j available (in the current classpath) */    static protected boolean log4jIsAvailable = false;    /** Is JDK 1.4 logging available */    static protected boolean jdk14IsAvailable = false;    /** Constructor for current log class */    static protected Constructor logImplctor = null;    // ----------------------------------------------------- Class Initializers    static {        // Is Log4J Available?        try {            log4jIsAvailable = null != Class.forName("org.apache.log4j.Logger");        } catch (Throwable t) {            log4jIsAvailable = false;        }        // Is JDK 1.4 Logging Available?        try {            jdk14IsAvailable = null != Class.forName("java.util.logging.Logger") &&                               null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger");        } catch (Throwable t) {            jdk14IsAvailable = false;        }        // Set the default Log implementation        String name = null;        try {            name = System.getProperty("org.apache.commons.logging.log");            if (name == null) {                name = System.getProperty("org.apache.commons.logging.Log");            }        } catch (Throwable t) {        }        if (name != null) {            try {                setLogImplementation(name);            } catch (Throwable t) {                try {                    setLogImplementation("org.apache.commons.logging.impl.NoOpLog");                } catch (Throwable u) {                    // ignored                }            }        } else {            try {                if (log4jIsAvailable) {                    setLogImplementation("org.apache.commons.logging.impl.Log4JLogger");                } else if (jdk14IsAvailable) {                    setLogImplementation("org.apache.commons.logging.impl.Jdk14Logger");                } else {                    setLogImplementation("org.apache.commons.logging.impl.NoOpLog");                }            } catch (Throwable t) {                try {                    setLogImplementation("org.apache.commons.logging.impl.NoOpLog");                } catch (Throwable u) {                    // ignored                }            }        }    }    //...}

核心的代码:

boolean isPresent = null != Class.forName("org.apache.log4j.Logger");

!= 的优先级大于=
所以以上的代码对应于:

boolean isPresent = (null != Class.forName("org.apache.log4j.Logger"));

SpringMVC 中的解决方案:

public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConverter {    private static final boolean jaxb2Present =            ClassUtils.isPresent("javax.xml.bind.Binder", AllEncompassingFormHttpMessageConverter.class.getClassLoader());    private static final boolean jackson2Present =            ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader()) &&                    ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", AllEncompassingFormHttpMessageConverter.class.getClassLoader());    private static final boolean jackson2XmlPresent =            ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader());    private static final boolean gsonPresent =            ClassUtils.isPresent("com.google.gson.Gson", AllEncompassingFormHttpMessageConverter.class.getClassLoader());    public AllEncompassingFormHttpMessageConverter() {        addPartConverter(new SourceHttpMessageConverter<Source>());        if (jaxb2Present && !jackson2XmlPresent) {            addPartConverter(new Jaxb2RootElementHttpMessageConverter());        }        if (jackson2Present) {            addPartConverter(new MappingJackson2HttpMessageConverter());        }        else if (gsonPresent) {            addPartConverter(new GsonHttpMessageConverter());        }        if (jackson2XmlPresent) {            addPartConverter(new MappingJackson2XmlHttpMessageConverter());        }    }}
    /**     * Determine whether the Class identified by the supplied name is present and can be loaded.      * 判断由提供的类名(类的全限定名)标识的类是否存在并可以加载     * 如果类或其中一个依赖关系不存在或无法加载,则返回false     * @param className 要检查的类的名称     * @param classLoader 加载该类使用的类加载器     * 可以是 null, 表明使用默认的类加载器     * @return 指定的类是否存在     */    public static boolean isPresent(String className, ClassLoader classLoader) {        try {            forName(className, classLoader);            return true;        }        catch (Throwable ex) {            // Class or one of its dependencies is not present...            return false;        }    }

可见,以上都是用了Class.forName来完成。
Class.forName 在没有找到该类时抛出ClassNotFoundException 异常。
我们所需要做的仅仅是屏蔽该异常,并设置一个表示当前类不存在的标识。

那么问题来了,我们都知道Class.forName 会导致我们加载的类去执行静态代码块(当然也可以设置不进行初始化),以及静态属性的初始化。在JVM中对应于
invokeSpecial <cint>
但是在java中如何判断一个类是否存在 这一简单问题似乎没有必要这样做。

那么如下的代码似乎更符合我们的要求吧?

    public static boolean isPresent(String name) {        try {            Thread.currentThread().getContextClassLoader().loadClass(name);            return true;        } catch (ClassNotFoundException e) {            return false;        }    }

以上的loadClass(String name) 方法会去调用该类中的protected方法 java.lang.ClassLoader#loadClass(java.lang.String, boolean)

public Class<?> loadClass(String name) throws ClassNotFoundException {        return loadClass(name, false);    }
    protected Class<?> loadClass(String name, boolean resolve)        throws ClassNotFoundException    {        synchronized (getClassLoadingLock(name)) {            // First, check if the class has already been loaded            Class<?> c = findLoadedClass(name);            if (c == null) {                long t0 = System.nanoTime();                try {                    if (parent != null) {                        c = parent.loadClass(name, false);                    } else {                        c = findBootstrapClassOrNull(name);                    }                } catch (ClassNotFoundException e) {                    // ClassNotFoundException thrown if class not found                    // from the non-null parent class loader                }                if (c == null) {                    // If still not found, then invoke findClass in order                    // to find the class.                    long t1 = System.nanoTime();                    c = findClass(name);                    // this is the defining class loader; record the stats                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);                    sun.misc.PerfCounter.getFindClasses().increment();                }            }            if (resolve) {                resolveClass(c);            }            return c;        }    }

resolve 参数表示是否进行链接。

这里写图片描述

两者的区别见:
http://blog.csdn.net/x_iya/article/details/73199280

原创粉丝点击