    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
    017    package com.google.common.primitives;
    018
    019    import static com.google.common.base.Preconditions.checkNotNull;
    020
    021    import java.util.Collections;
    022    import java.util.HashMap;
    023    import java.util.Map;
    024    import java.util.Set;
    025
    026    /**
    027     * Contains static utility methods pertaining to primitive types and their
    028     * corresponding wrapper types.
    029     *
    030     * @author Kevin Bourrillion
    031     * @since 1.0
    032     */
    033    public final class Primitives {
    034      private Primitives() {}
    035
    036      /** A map from primitive types to their corresponding wrapper types. */
    037      private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;
    038
    039      /** A map from wrapper types to their corresponding primitive types. */
    040      private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
    041
    042      // Sad that we can't use a BiMap. :(
    043
    044      static {
    045        Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
    046        Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
    047
    048        add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
    049        add(primToWrap, wrapToPrim, byte.class, Byte.class);
    050        add(primToWrap, wrapToPrim, char.class, Character.class);
    051        add(primToWrap, wrapToPrim, double.class, Double.class);
    052        add(primToWrap, wrapToPrim, float.class, Float.class);
    053        add(primToWrap, wrapToPrim, int.class, Integer.class);
    054        add(primToWrap, wrapToPrim, long.class, Long.class);
    055        add(primToWrap, wrapToPrim, short.class, Short.class);
    056        add(primToWrap, wrapToPrim, void.class, Void.class);
    057
    058        PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
    059        WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
    060      }
    061
    062      private static void add(Map<Class<?>, Class<?>> forward,
    063          Map<Class<?>, Class<?>> backward, Class<?> key, Class<?> value) {
    064        forward.put(key, value);
    065        backward.put(value, key);
    066      }
    067
    068      /**
    069       * Returns an immutable set of all nine primitive types (including {@code
    070       * void}). Note that a simpler way to test whether a {@code Class} instance
    071       * is a member of this set is to call {@link Class#isPrimitive}.
    072       *
    073       * @since 3.0
    074       */
    075      public static Set<Class<?>> allPrimitiveTypes() {
    076        return PRIMITIVE_TO_WRAPPER_TYPE.keySet();
    077      }
    078
    079      /**
    080       * Returns an immutable set of all nine primitive-wrapper types (including
    081       * {@link Void}).
    082       *
    083       * @since 3.0
    084       */
    085      public static Set<Class<?>> allWrapperTypes() {
    086        return WRAPPER_TO_PRIMITIVE_TYPE.keySet();
    087      }
    088
    089      /**
    090       * Returns {@code true} if {@code type} is one of the nine
    091       * primitive-wrapper types, such as {@link Integer}.
    092       *
    093       * @see Class#isPrimitive
    094       */
    095      public static boolean isWrapperType(Class<?> type) {
    096        return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(checkNotNull(type));
    097      }
    098
    099      /**
    100       * Returns the corresponding wrapper type of {@code type} if it is a primitive
    101       * type; otherwise returns {@code type} itself. Idempotent.
    102       * <pre>
    103       *     wrap(int.class) == Integer.class
    104       *     wrap(Integer.class) == Integer.class
    105       *     wrap(String.class) == String.class
    106       * </pre>
    107       */
    108      public static <T> Class<T> wrap(Class<T> type) {
    109        checkNotNull(type);
    110
    111        // cast is safe: long.class and Long.class are both of type Class<Long>
    112        @SuppressWarnings("unchecked")
    113        Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(type);
    114        return (wrapped == null) ? type : wrapped;
    115      }
    116
    117      /**
    118       * Returns the corresponding primitive type of {@code type} if it is a
    119       * wrapper type; otherwise returns {@code type} itself. Idempotent.
    120       * <pre>
    121       *     unwrap(Integer.class) == int.class
    122       *     unwrap(int.class) == int.class
    123       *     unwrap(String.class) == String.class
    124       * </pre>
    125       */
    126      public static <T> Class<T> unwrap(Class<T> type) {
    127        checkNotNull(type);
    128
    129        // cast is safe: long.class and Long.class are both of type Class<Long>
    130        @SuppressWarnings("unchecked")
    131        Class<T> unwrapped = (Class<T>) WRAPPER_TO_PRIMITIVE_TYPE.get(type);
    132        return (unwrapped == null) ? type : unwrapped;
    133      }
    134    }