java判断类是否存在吗,在java中如何判斷一個類是否存在

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());

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 。

但是在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 參數表示是否進行鏈接。

81ad61572581b5142af0b88f8c1ee57e.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值