com.feilong.core.lang.reflect.TypeUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of feilong Show documentation
Show all versions of feilong Show documentation
feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.
/*
* 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.reflect;
import static com.feilong.core.bean.ConvertUtil.convert;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.feilong.core.Validate;
import com.feilong.core.bean.ConvertUtil;
import com.feilong.core.bean.ToStringConfig;
/**
* Utility methods focusing on type inspection, particularly with regard to generics.
*
* 关于获取Class泛型说明:
*
*
*
*
*
* - {@link Class#getGenericSuperclass()} 返回此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type.
*
* - 如果超类是参数化类型,则返回的 Type 对象,必须准确反映源代码中所使用的实际类型参数.
* - 如果以前未曾创建表示超类的参数化类型,则创建这个类型.有关参数化类型创建过程的语义,请参阅 {@link ParameterizedType} 声明.
* - 如果此 Class 表示 Object 类、接口、基本类型或 void,则返回 null.
* - 如果此对象表示一个数组类,则返回表示 Object 类的 Class 对象.
*
*
*
* - {@link Class#getGenericInterfaces()} 返回某些接口的 Type,这些接口由此对象所表示的类或接口直接实现
*
* - 如果超接口是参数化类型,则为它返回的 Type 对象必须准确反映源代码中所使用的实际类型参数.
* - 如果以前未曾创建表示每个超接口的参数化类型,则创建这个类型.有关参数化类型创建过程的语义,请参阅 {@link ParameterizedType} 声明.
* -
* 如果此对象表示一个类,则返回一个包含这样一些对象的数组,这些对象表示该类实现的所有接口.
* 数组中接口对象顺序与此对象所表示的类的声明的 implements 子句中接口名顺序一致.
* 对于数组类,接口 Cloneable 和 Serializable 以该顺序返回.
*
* - 如果此对象表示一个接口,则该数组包含表示该接口直接扩展的所有接口的对象.数组中接口对象顺序与此对象所表示的接口的声明的 extends 子句中接口名顺序一致.
* - 如果此对象表示一个不实现任何接口的类或接口,则此方法返回一个长度为 0 的数组.
* - 如果此对象表示一个基本类型或 void,则此方法返回一个长度为 0 的数组.
*
*
*
*
*
*
* @author feilong
* @see "org.apache.commons.lang3.reflect.TypeUtils"
* @see "org.springframework.core.GenericTypeResolver"
* @see "org.springframework.core.GenericTypeResolver#getTypeVariableMap(Class)"
* @see "org.springframework.core.ParameterizedTypeReference"
* @see java.lang.reflect.Type
* @see java.lang.reflect.ParameterizedType
* @see java.lang.reflect.GenericArrayType
* @see java.lang.reflect.TypeVariable
* @see java.lang.reflect.WildcardType
* @since 1.0.8
* @since jdk 1.5
*/
public final class TypeUtil{
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory.getLogger(TypeUtil.class);
/** Don't let anyone instantiate this class. */
private TypeUtil(){
//AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化.
//see 《Effective Java》 2nd
throw new AssertionError("No " + getClass().getName() + " instances for you!");
}
//---------------------------------------------------------------
/**
* 获得类的 父类 上的泛型参数的类型.
*
* 示例:
*
*
*
*
* public class SkuItemRepositoryImpl extends BaseSolrRepositoryImpl{@code } implements SkuItemRepository
*
*
*
* 这样的类,如果想要取到父类的泛型参数 [SkuItem.class,Long.class],可以使用:
*
*
*
* TypeUtil.getGenericSuperclassParameterizedRawTypes(SkuItemRepositoryImpl.class)
*
*
*
*
* @param klass
* the klass
* @return 如果 klass
是null,抛出 {@link NullPointerException}
* 如果 klass
没有父类(除了Object),抛出 {@link NullPointerException}
* 如果 klass
有父类(除了Object)但是父类没有泛型参数,抛出 {@link NullPointerException}
* @since 1.1.1
*/
public static Class[] getGenericSuperclassParameterizedRawTypes(Class klass){
Validate.notNull(klass, "klass can't be null/empty!");
ParameterizedType parameterizedType = getGenericSuperclassParameterizedType(klass);
return extractActualTypeArgumentClassArray(parameterizedType);
}
/**
* 获得类的 接口 上的泛型参数的类型.
*
* 示例:
*
*
*
*
* 对于以下的场景:
*
*
*
*
* public interface BaseSolrRepository{@code } {
*
* }
*
* public class SkuItemRepositoryInterfaceImpl implements BaseSolrRepository{@code }{
*
* }
*
*
*
*
* 如果你需要提取 SkuItemRepositoryInterfaceImpl类 接口 BaseSolrRepository{@code }中的泛型参数
*
*
* 你可以使用:
*
*
* Class{@code }[] rawTypes = TypeUtil
* .getGenericInterfacesParameterizedRawTypes(SkuItemRepositoryInterfaceImpl.class, BaseSolrRepository.class);
*
* assertArrayEquals(toArray(SkuItem.class, Long.class), rawTypes);
*
*
*
*
* @param klass
* the klass
* @param extractInterfaceClass
* 待抽取的接口类型
* @return 如果 klass
是null,抛出 {@link NullPointerException}
* 如果 extractInterfaceClass
是null,抛出 {@link NullPointerException}
* 如果 klass
是没有泛型接口,抛出 {@link NullPointerException}
* 如果 klass
有泛型接口但是其中没有指定的接口类型extractInterfaceClass
,抛出 {@link NullPointerException}
* @since 1.1.1
*/
public static Class[] getGenericInterfacesParameterizedRawTypes(Class klass,Class extractInterfaceClass){
Validate.notNull(klass, "klass can't be null/empty!");
Validate.notNull(extractInterfaceClass, "extractInterfaceClass can't be null/empty!");
ParameterizedType parameterizedType = getGenericInterfacesParameterizedType(klass, extractInterfaceClass);
return extractActualTypeArgumentClassArray(parameterizedType);
}
//---------------------------------------------------------------
/**
* 获得 generic interfaces parameterized type.
*
* @param klass
* the klass
* @param extractInterfaceClass
* the extract interface class
* @return 如果 klass没有泛型接口,返回null
* @see java.lang.Class#getGenericInterfaces()
* @see java.lang.reflect.ParameterizedType#getRawType()
* @since 1.1.1
*/
private static ParameterizedType getGenericInterfacesParameterizedType(Class klass,Class extractInterfaceClass){
Type[] genericInterfaces = klass.getGenericInterfaces();
for (Type genericInterface : genericInterfaces){
if (!(genericInterface instanceof ParameterizedType)){
continue;
}
//---------------------------------------------------------------
ParameterizedType genericInterfacesType = (ParameterizedType) genericInterface;
Type rawType = genericInterfacesType.getRawType();
if (extractInterfaceClass == rawType){
return genericInterfacesType;
}
}
return null;
}
/**
* 获得 superclass parameterized type.
*
* @param klass
* the klass
* @return 如果没有父类或者父类没有泛型参数,返回null
* @see java.lang.Class#getGenericSuperclass()
*/
private static ParameterizedType getGenericSuperclassParameterizedType(Class klass){
Class useClass = klass;
Type type = useClass.getGenericSuperclass(); //com.feilong.....BaseSolrRepositoryImpl
while (!(type instanceof ParameterizedType) && Object.class != useClass){
useClass = useClass.getSuperclass();
type = useClass.getGenericSuperclass();
}
return (ParameterizedType) type;
}
/**
* 提取实际的泛型参数数组.
*
* @param parameterizedType
* the parameterized type
* @return 如果 parameterizedType
是null,抛出 {@link NullPointerException}
* 如果 parameterizedType
没有实际的泛型参数 {@link ParameterizedType#getActualTypeArguments()},抛出
* {@link NullPointerException}
* @see java.lang.reflect.ParameterizedType#getActualTypeArguments()
* @since 1.1.1
*/
private static Class[] extractActualTypeArgumentClassArray(ParameterizedType parameterizedType){
Validate.notNull(parameterizedType, "parameterizedType can't be null/empty!");
if (LOGGER.isTraceEnabled()){
LOGGER.trace("parameterizedType info:[{}]", parameterizedType);
}
//---------------------------------------------------------------
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Validate.notNull(actualTypeArguments, "actualTypeArguments can't be null/empty!");
//---------------------------------------------------------------
if (LOGGER.isTraceEnabled()){
LOGGER.trace("actualTypeArguments:[{}]", ConvertUtil.toString(actualTypeArguments, ToStringConfig.DEFAULT_CONNECTOR));
}
return convert(actualTypeArguments, Class[].class);
}
}