/*
* Copyright 2013 Cameron Beccario
*
* 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 net.nullschool.reflect;
import java.lang.reflect.*;
import static net.nullschool.reflect.TypeTools.buildArrayType;
/**
* 2013-04-03<p/>
*
* A type operator that performs
* <a href="http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20type%20erasure?">
* type erasure</a>.
*
* @author Cameron Beccario
*/
final class Eraser extends AbstractTypeOperator<Class<?>> {
static final Eraser INSTANCE = new Eraser();
/**
* The erasure of a class object is the class object itself. Object --> Object
*/
@Override public Class<?> apply(Class<?> clazz) {
return clazz;
}
/**
* The erasure of a parameterized type is the erasure of its raw type. Set<Long> --> Set
*
* @throws NullPointerException if the argument is null.
*/
@Override public Class<?> apply(ParameterizedType pt) {
return apply(pt.getRawType());
}
/**
* The erasure of a generic array type is the class object representing an array of the erasure of the
* component type. E[] --> Object[]
*
* @throws NullPointerException if the argument is null.
*/
@Override public Class<?> apply(GenericArrayType gat) {
return buildArrayType(apply(gat.getGenericComponentType()));
}
/**
* The erasure of a wildcard type is Object for unbounded or lower-bounded wildcards, and is the erasure of
* the upper bound for upper-bounded wildcards. Examples:
* <ul>
* <li>? --> Object.class</li>
* <li>? super Number --> Object.class</li>
* <li>? extends Callable<Number> --> Callable.class</li>
* </ul>
*
* @throws NullPointerException if the argument is null.
*/
@Override public Class<?> apply(WildcardType wt) {
return wt.getLowerBounds().length != 0 ? Object.class : apply(wt.getUpperBounds()[0]);
}
/**
* The erasure of a type variable is its left-most bound or Object if unbounded. Examples:
* <ul>
* <li>E --> Object.class</li>
* <li>E extends Enum<E> --> Enum.class</li>
* <li>E extends Serializable & Comparable<E> --> Serializable.class</li>
* </ul>
*
* @throws NullPointerException if the argument is null.
*/
@Override public Class<?> apply(TypeVariable<?> tv) {
return apply(tv.getBounds()[0]);
}
}