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 * https://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 * 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: 029 * <p> 030 * You might see such a typesafe API as: 031 * <pre>{@code 032 * class Typesafe { 033 * <T> T obtain(Class<T> type, ...); 034 * } 035 * } 036 * </pre> 037 * Consumed in the manner of: 038 * <pre> 039 * Foo foo = typesafe.obtain(Foo.class, ...); 040 * </pre> 041 * Yet, you run into problems when you want to do this with a parameterized type: 042 * <pre>{@code 043 * List<String> listOfString = typesafe.obtain(List.class, ...); // could only give us a raw List 044 * }</pre> 045 * {@link java.lang.reflect.Type} might provide some value: 046 * <pre>{@code 047 * Type listOfStringType = ...; // firstly, how to obtain this? Doable, but not straightforward. 048 * List<String> listOfString = (List<String>) typesafe.obtain(listOfStringType, ...); // nongeneric Type would necessitate a cast 049 * }</pre> 050 * The "type literal" concept was introduced to provide an alternative, i.e.: 051 * <pre>{@code 052 * class Typesafe { 053 * <T> T obtain(TypeLiteral<T> type, ...); 054 * } 055 * }</pre> 056 * Consuming code looks like: 057 * <pre>{@code 058 * List<String> listOfString = typesafe.obtain(new TypeLiteral<List<String>>() {}, ...); 059 * }</pre> 060 * <p> 061 * This has the effect of "jumping up" a level to tie a {@link java.lang.reflect.Type} 062 * to a type variable while simultaneously making it short work to obtain a 063 * {@link Type} instance for any given type, inline. 064 * </p> 065 * <p>Additionally {@link TypeLiteral} implements the {@link Typed} interface which 066 * is a generalization of this concept, and which may be implemented in custom classes. 067 * It is suggested that APIs be defined in terms of the interface, in the following manner: 068 * </p> 069 * <pre>{@code 070 * <T> T obtain(Typed<T> typed, ...); 071 * }</pre> 072 * 073 * @param <T> the type 074 * @since 3.2 075 */ 076public abstract class TypeLiteral<T> implements Typed<T> { 077 078 @SuppressWarnings("rawtypes") 079 private static final TypeVariable<Class<TypeLiteral>> T = TypeLiteral.class.getTypeParameters()[0]; 080 081 /** 082 * Represented type. 083 */ 084 public final Type value; 085 086 private final String toString; 087 088 /** 089 * Constructs a new instance. 090 */ 091 protected TypeLiteral() { 092 this.value = 093 Validate.notNull(TypeUtils.getTypeArguments(getClass(), TypeLiteral.class).get(T), 094 "%s does not assign type parameter %s", getClass(), TypeUtils.toLongString(T)); 095 096 this.toString = String.format("%s<%s>", TypeLiteral.class.getSimpleName(), TypeUtils.toString(value)); 097 } 098 099 @Override 100 public final boolean equals(final Object obj) { 101 if (obj == this) { 102 return true; 103 } 104 if (!(obj instanceof TypeLiteral)) { 105 return false; 106 } 107 final TypeLiteral<?> other = (TypeLiteral<?>) obj; 108 return TypeUtils.equals(value, other.value); 109 } 110 111 @Override 112 public Type getType() { 113 return value; 114 } 115 116 @Override 117 public int hashCode() { 118 return 37 << 4 | value.hashCode(); 119 } 120 121 @Override 122 public String toString() { 123 return toString; 124 } 125}