001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3.reflect; 018 019import java.lang.reflect.Type; 020import java.lang.reflect.TypeVariable; 021 022import org.apache.commons.lang3.Validate; 023 024/** 025 * <p>Type literal comparable to {@code javax.enterprise.util.TypeLiteral}, 026 * made generally available outside the JEE context. Allows the passing around of 027 * a "token" that represents a type in a typesafe manner, as opposed to 028 * passing the (non-parameterized) {@link Type} object itself. Consider:</p> 029 * <p> 030 * You might see such a typesafe API as: 031 * <pre> 032 * class Typesafe { 033 * <T> T obtain(Class<T> type, ...); 034 * } 035 * </pre> 036 * Consumed in the manner of: 037 * <pre> 038 * Foo foo = typesafe.obtain(Foo.class, ...); 039 * </pre> 040 * Yet, you run into problems when you want to do this with a parameterized type: 041 * <pre> 042 * List<String> listOfString = typesafe.obtain(List.class, ...); // could only give us a raw List 043 * </pre> 044 * {@code java.lang.reflect.Type} might provide some value: 045 * <pre> 046 * Type listOfStringType = ...; // firstly, how to obtain this? Doable, but not straightforward. 047 * List<String> listOfString = (List<String>) typesafe.obtain(listOfStringType, ...); // nongeneric Type would necessitate a cast 048 * </pre> 049 * The "type literal" concept was introduced to provide an alternative, i.e.: 050 * <pre> 051 * class Typesafe { 052 * <T> T obtain(TypeLiteral<T> type, ...); 053 * } 054 * </pre> 055 * Consuming code looks like: 056 * <pre> 057 * List<String> listOfString = typesafe.obtain(new TypeLiteral<List<String>>() {}, ...); 058 * </pre> 059 * <p> 060 * This has the effect of "jumping up" a level to tie a {@code java.lang.reflect.Type} 061 * to a type variable while simultaneously making it short work to obtain a 062 * {@code Type} instance for any given type, inline. 063 * </p> 064 * <p>Additionally {@link TypeLiteral} implements the {@link Typed} interface which 065 * is a generalization of this concept, and which may be implemented in custom classes. 066 * It is suggested that APIs be defined in terms of the interface, in the following manner: 067 * </p> 068 * <pre> 069 * <T> T obtain(Typed<T> typed, ...); 070 * </pre> 071 * 072 * @since 3.2 073 */ 074public abstract class TypeLiteral<T> implements Typed<T> { 075 076 @SuppressWarnings("rawtypes") 077 private static final TypeVariable<Class<TypeLiteral>> T = TypeLiteral.class.getTypeParameters()[0]; 078 079 /** 080 * Represented type. 081 */ 082 public final Type value; 083 084 private final String toString; 085 086 /** 087 * The default constructor. 088 */ 089 protected TypeLiteral() { 090 this.value = 091 Validate.notNull(TypeUtils.getTypeArguments(getClass(), TypeLiteral.class).get(T), 092 "%s does not assign type parameter %s", getClass(), TypeUtils.toLongString(T)); 093 094 this.toString = String.format("%s<%s>", TypeLiteral.class.getSimpleName(), TypeUtils.toString(value)); 095 } 096 097 @Override 098 public final boolean equals(final Object obj) { 099 if (obj == this) { 100 return true; 101 } 102 if (!(obj instanceof TypeLiteral)) { 103 return false; 104 } 105 final TypeLiteral<?> other = (TypeLiteral<?>) obj; 106 return TypeUtils.equals(value, other.value); 107 } 108 109 @Override 110 public int hashCode() { 111 return 37 << 4 | value.hashCode(); 112 } 113 114 @Override 115 public String toString() { 116 return toString; 117 } 118 119 @Override 120 public Type getType() { 121 return value; 122 } 123}