com.feilong.core.lang.ClassUtil Maven / Gradle / Ivy
/*
* Copyright (C) 2008 feilong
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.feilong.core.lang;
import static com.feilong.core.lang.StringUtil.formatPattern;
import java.lang.reflect.Modifier;
import com.feilong.core.Validate;
import com.feilong.core.lang.reflect.ReflectException;
/**
* {@link java.lang.Class} 工具类.
*
* 关于 Class {@link java.lang.Class#getCanonicalName() getCanonicalName()} VS {@link java.lang.Class#getName() getName()} VS
* {@link java.lang.Class#getSimpleName() getSimpleName()}
*
*
*
* 假设class 是 {@link com.feilong.core.DatePattern}
*
*
*
*
* 字段
* 说明
* 示例
*
*
*
* {@link java.lang.Class#getCanonicalName() getCanonicalName()}
* 返回 Java Language Specification 中所定义的底层类的规范化名称。
* 如果底层类没有规范化名称(即如果底层类是一个组件类型没有规范化名称的本地类、匿名类或数组),则返回 null。
* "com.feilong.core.date.DatePattern"
*
*
*
* {@link java.lang.Class#getName() getName()}
* 除了数组外,其他的类都是输出类全名,以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
*
*
* - 1、此类对象表示的是非数组类型的引用类型
* - 返回该类的二进制名称,Java Language Specification, Second Edition 对此作了详细说明。
*
* - 2、此类对象表示一个基本类型或 void
* - 返回的名字是一个与该基本类型或 void 所对应的 Java 语言关键字相同的 String。
*
* - 3、此类对象表示一个数组类
* - 名字的内部形式为:表示该数组嵌套深度的一个或多个 '[' 字符加元素类型名。
*
*
*
* "com.feilong.core.date.DatePattern"
*
*
*
* {@link java.lang.Class#getSimpleName() getSimpleName()}
*
* 返回源代码中给出的底层类的简称。
* 如果底层类是匿名的则返回一个空字符串。
* 数组的简称即附带 "[]" 的组件类型的简称。特别地,组件类型为匿名的数组的简称是 "[]"。
*
* "DatePattern"
*
*
*
*
*
* {@link java.lang.Class#getCanonicalName() getCanonicalName()} 和 {@link java.lang.Class#getName() getName()} 其实这两个方法,对于大部分class来说,没有什么不同的
*
* 但是对于array就显示出来了.
*
*
*
* - {@link java.lang.Class#getName() getName()} 返回的是[[Ljava.lang.String之类的表现形式,
* - 而 {@link java.lang.Class#getCanonicalName() getCanonicalName()} 返回的就是跟我们声明类似的形式.
*
*
*
*
* instanceof运算符/isAssignableFrom/isInstance(Object obj) 区别
*
*
*
*
*
* 字段
* 说明
*
*
*
* instanceof运算符
* 针对实例,是用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例
* 格式是:oo instanceof TypeName
* 第一个参数是对象实例名,第二个参数是具体的类名或接口名
* instanceof是Java的一个二元操作符,{@code ==,>,<}和是同一类东东,作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据
*
*
*
* isAssignableFrom
* 针对class对象,是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口.
* 通常调用格式是Class1.isAssignableFrom(Class2)
* 调用者和参数都是java.lang.Class类型.
*
*
*
* isInstance(Object obj)方法
* obj是被测试的对象,如果obj是调用这个方法的class或接口 的实例,则返回true.
* 这个方法是instanceof运算符的动态等价
*
*
*
*
*
* instanceof :子 {@code ----->} 父
* isAssignableFrom :父 {@code ----->} 子
*
*
*
* @author feilong
* @see Class的getName、getSimpleName与getCanonicalName的区别
* @see com.feilong.lib.lang3.ClassUtils
* @since 1.0.0
*/
public final class ClassUtil{
/** Don't let anyone instantiate this class. */
private ClassUtil(){
//AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化.
//see 《Effective Java》 2nd
throw new AssertionError("No " + getClass().getName() + " instances for you!");
}
//---------------------------------------------------------------
/**
* 判断一个对象 obj
是不是某个类 klass
的实例.
*
* 说明:
*
*
* - instanceof :子 {@code ----->} 父
* - isAssignableFrom :父 {@code ----->} 子
*
*
*
* 示例:
*
*
*
*
* ClassUtil.isInstance(new User(), null) = false
* ClassUtil.isInstance(new User(), Comparable.class) = true
* ClassUtil.isInstance("1234", CharSequence.class) = true
* ClassUtil.isInstance("1234", Integer.class) = false
* ClassUtil.isInstance(null, CharSequence.class) = false
* ClassUtil.isInstance(null, Integer.class) = false
*
*
*
*
* instanceof 运算符/isAssignableFrom/isInstance(Object obj) 区别
*
*
*
*
*
* 字段
* 说明
*
*
*
* instanceof运算符
*
* 针对实例,是用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例
* instanceof是Java的一个二元操作符,和{@code ==,>,<}是同一类东东,作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据
* 格式是: oo instanceof TypeName
* 第一个参数是对象实例名,第二个参数是具体的类名或接口名
*
*
*
*
* isAssignableFrom
*
* 针对class对象,是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口.
* 格式是: Class1.isAssignableFrom(Class2)
* 调用者和参数都是java.lang.Class类型.
*
*
*
*
* java.lang.Class.isInstance(Object obj)方法
*
* obj是被测试的对象,如果obj是调用这个方法的class或接口 的实例,则返回true.
* 这个方法是instanceof运算符的 动态等价
*
*
*
*
*
*
* @param obj
* 实例
* @param klass
* 类
* @return 如果 obj 是此类的实例,则返回 true;
* 如果 obj
是null,返回 false
* 如果 klass
是null,返回 false
* @see java.lang.Class#isInstance(Object)
*/
public static boolean isInstance(Object obj,Class> klass){
return null != klass && klass.isInstance(obj);
}
/**
* 判断 obj
是否isInstance 任意的一个 klasses
.
*
* 示例:
*
*
*
*
* ClassUtil.isInstanceAnyClass(null, toArray(Integer.class, CharSequence.class)) = false
* ClassUtil.isInstanceAnyClass("1234", toArray(Comparable.class, CharSequence.class)) = true
* ClassUtil.isInstanceAnyClass(new User(), null) = false
* ClassUtil.isInstanceAnyClass(new User(), toArray(Comparable.class, CharSequence.class)) = true
* ClassUtil.isInstanceAnyClass(new User(), toArray(Integer.class, CharSequence.class)) = false
*
*
*
*
* @param obj
* 任意的对象
* @param klasses
* the klasses
* @return 如果 null == klasses
,返回 false
* true, if checks if is instance;
* @since 1.5.6
*/
public static boolean isInstanceAnyClass(Object obj,Class>...klasses){
if (null == klasses){
return false;
}
//---------------------------------------------------------------
for (Class> klass : klasses){
if (isInstance(obj, klass)){
return true;
}
}
return false;
}
/**
* Checks if is assignable from.
*
*
* instanceof :子 {@code ----->} 父
* isAssignableFrom :父 {@code ----->} 子
*
*
* 示例:
*
*
*
*
* ClassUtil.isAssignableFrom(Comparable.class, new User().getClass()) = true
* ClassUtil.isAssignableFrom(null, new User().getClass()) = false
* ClassUtil.isAssignableFrom(CharSequence.class, "1234".getClass()) = true
* ClassUtil.isAssignableFrom(CharSequence.class, null) = false
*
*
*
*
* @param klass
* the klass
* @param cls
* the cls
* @return 如果 klass
是null,返回false
* 如果 cls
是null,返回false
* @see java.lang.Class#isAssignableFrom(Class)
* @see com.feilong.lib.lang3.ClassUtils#isAssignable(Class, Class)
* @since 1.4.0
*/
public static boolean isAssignableFrom(Class> klass,Class> cls){
return null != klass && null != cls && klass.isAssignableFrom(cls);
}
/**
* 判断类 ownerClass
是否是接口.
*
* 示例:
*
*
*
*
* ClassUtil.isInterface(null) = false
* ClassUtil.isInterface(DatePattern.class) = false
* ClassUtil.isInterface(Validator.class) = false
* ClassUtil.isInterface(CharSequence.class) = true
* ClassUtil.isInterface(List.class) = true
* ClassUtil.isInterface(Map.class) = true
*
*
*
*
* @param ownerClass
* 对象class
* @return 是返回true
* 如果 ownerClass
是null,返回false
* @see java.lang.Class#getModifiers()
* @see java.lang.reflect.Modifier#isInterface(int)
*/
public static boolean isInterface(Class> ownerClass){
return null != ownerClass && Modifier.isInterface(ownerClass.getModifiers());// 对类和成员访问修饰符进行解码
}
/**
* 解析对象参数 paramValues
,获得参数类型.
*
* 示例:
*
*
*
*
* assertArrayEquals(new Class[] { String.class, String.class }, ClassUtil.toClass("a", "a"));
* assertArrayEquals(new Class[] { Integer.class, Boolean.class }, ClassUtil.toClass(1, true));
*
*
*
*
* @param paramValues
* 参数值
* @return 如果 paramValues
是null,返回 null
* @see com.feilong.lib.lang3.ClassUtils#toClass(Object...)
* @see com.feilong.lib.lang3.ClassUtils#convertClassNamesToClasses(java.util.List)
* @since 1.1.1
*/
public static Class>[] toClass(Object...paramValues){
return null == paramValues ? null : com.feilong.lib.lang3.ClassUtils.toClass(paramValues);
}
//---------------------------------------------------------------
/**
* JVM查找并加载指定的类.
*
* 示例:
*
*
*
*
*
* FeiLongVersion feiLongVersion = ClassUtil.loadClass("com.feilong.core.FeiLongVersion");
*
*
*
*
* 和直接调用 {@link Class#forName(String)}的区别:
*
*
*
* - 一般情况下 = {@link Class#forName(String)}
*
* - Returns the class represented by {@code className} using the {@code classLoader}.
* 支持 " {@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}", and
* "{@code [Ljava.util.Map$Entry;}".
*
* -
*
* 会尝试从下面的顺序加载class:
*
*
*
* - From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
* - From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
*
*
*
*
*
*
* 对比:
*
*
*
*
* 字段
* 说明
*
*
*
* Class klass=对象引用o.{@link java.lang.Object#getClass() getClass()};
* 返回引用o运行时真正所指的对象(因为:儿子对象的引用可能会赋给父对象的引用变量中)所属的类O的Class的对象.
* 谈不上对类O做什么操作.
*
*
*
* Class klass=A.class;
* JVM将使用类A的类装载器,将类A装入内存(前提:类A还没有装入内存),不对类A做类的初始化工作.
* 返回类A的Class的对象.
*
*
*
* Class klass={@link java.lang.Class#forName(String) Class.forName}("类全名");
* 装载连接初始化类.
*
*
*
* Class klass={@link java.lang.ClassLoader#loadClass(String) ClassLoader.loadClass}("类全名");
* 装载类,不连接不初始化.
*
*
*
*
*
* @param className
* 包名+类名,比如 "com.feilong.core.FeiLongVersion"
* @return 如果 className
是null,抛出 {@link NullPointerException}
* 如果 className
是blank,抛出 {@link IllegalArgumentException}
* 如果 className
找不到相关类,那么抛出 {@link ReflectException}
* @see java.lang.ClassLoader#loadClass(String)
* @see java.lang.Class#forName(String)
* @see java.lang.Class#forName(String, boolean, ClassLoader)
* @see com.feilong.lib.lang3.ClassUtils#getClass(String)
* @see com.feilong.lib.lang3.ClassUtils#getClass(ClassLoader, String, boolean)
* @see "org.springframework.util.ClassUtils#forName(String, ClassLoader)"
* @since 1.6.2
*/
public static Class> getClass(String className){
Validate.notBlank(className, "className can't be blank!");
//---------------------------------------------------------------
try{
return com.feilong.lib.lang3.ClassUtils.getClass(className);
}catch (Exception e){
throw new ReflectException(formatPattern("className:[{}]", className), e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy