001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.primitives;
018
019import static com.google.common.base.Preconditions.checkNotNull;
020
021import java.util.Collections;
022import java.util.HashMap;
023import java.util.Map;
024import java.util.Set;
025
026import javax.annotation.CheckReturnValue;
027
028/**
029 * Contains static utility methods pertaining to primitive types and their
030 * corresponding wrapper types.
031 *
032 * @author Kevin Bourrillion
033 * @since 1.0
034 */
035@CheckReturnValue
036public final class Primitives {
037  private Primitives() {}
038
039  /** A map from primitive types to their corresponding wrapper types. */
040  private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;
041
042  /** A map from wrapper types to their corresponding primitive types. */
043  private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
044
045  // Sad that we can't use a BiMap. :(
046
047  static {
048    Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
049    Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
050
051    add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
052    add(primToWrap, wrapToPrim, byte.class, Byte.class);
053    add(primToWrap, wrapToPrim, char.class, Character.class);
054    add(primToWrap, wrapToPrim, double.class, Double.class);
055    add(primToWrap, wrapToPrim, float.class, Float.class);
056    add(primToWrap, wrapToPrim, int.class, Integer.class);
057    add(primToWrap, wrapToPrim, long.class, Long.class);
058    add(primToWrap, wrapToPrim, short.class, Short.class);
059    add(primToWrap, wrapToPrim, void.class, Void.class);
060
061    PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
062    WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
063  }
064
065  private static void add(
066      Map<Class<?>, Class<?>> forward,
067      Map<Class<?>, Class<?>> backward,
068      Class<?> key,
069      Class<?> value) {
070    forward.put(key, value);
071    backward.put(value, key);
072  }
073
074  /**
075   * Returns an immutable set of all nine primitive types (including {@code
076   * void}). Note that a simpler way to test whether a {@code Class} instance
077   * is a member of this set is to call {@link Class#isPrimitive}.
078   *
079   * @since 3.0
080   */
081  public static Set<Class<?>> allPrimitiveTypes() {
082    return PRIMITIVE_TO_WRAPPER_TYPE.keySet();
083  }
084
085  /**
086   * Returns an immutable set of all nine primitive-wrapper types (including
087   * {@link Void}).
088   *
089   * @since 3.0
090   */
091  public static Set<Class<?>> allWrapperTypes() {
092    return WRAPPER_TO_PRIMITIVE_TYPE.keySet();
093  }
094
095  /**
096   * Returns {@code true} if {@code type} is one of the nine
097   * primitive-wrapper types, such as {@link Integer}.
098   *
099   * @see Class#isPrimitive
100   */
101  public static boolean isWrapperType(Class<?> type) {
102    return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(checkNotNull(type));
103  }
104
105  /**
106   * Returns the corresponding wrapper type of {@code type} if it is a primitive
107   * type; otherwise returns {@code type} itself. Idempotent.
108   * <pre>
109   *     wrap(int.class) == Integer.class
110   *     wrap(Integer.class) == Integer.class
111   *     wrap(String.class) == String.class
112   * </pre>
113   */
114  public static <T> Class<T> wrap(Class<T> type) {
115    checkNotNull(type);
116
117    // cast is safe: long.class and Long.class are both of type Class<Long>
118    @SuppressWarnings("unchecked")
119    Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(type);
120    return (wrapped == null) ? type : wrapped;
121  }
122
123  /**
124   * Returns the corresponding primitive type of {@code type} if it is a
125   * wrapper type; otherwise returns {@code type} itself. Idempotent.
126   * <pre>
127   *     unwrap(Integer.class) == int.class
128   *     unwrap(int.class) == int.class
129   *     unwrap(String.class) == String.class
130   * </pre>
131   */
132  public static <T> Class<T> unwrap(Class<T> type) {
133    checkNotNull(type);
134
135    // cast is safe: long.class and Long.class are both of type Class<Long>
136    @SuppressWarnings("unchecked")
137    Class<T> unwrapped = (Class<T>) WRAPPER_TO_PRIMITIVE_TYPE.get(type);
138    return (unwrapped == null) ? type : unwrapped;
139  }
140}