簡體   English   中英

確定對象是否為原始類型

[英]Determining if an Object is of primitive type

我有一個Object[]數組,我試圖找到那些是基元的。 我嘗試使用Class.isPrimitive() ,但似乎我做錯了什么:

int i = 3;
Object o = i;

System.out.println(o.getClass().getName() + ", " +
                   o.getClass().isPrimitive());

打印java.lang.Integer, false

有沒有正確的方法或其他選擇?

在該類型的Object[]永遠不會真正原始的-因為你已經有了參考! 這里i的類型是into引用的對象的類型是Integer (由於自動裝箱)。

聽起來您需要確定該類型是否是“原始類型的包裝器”。 我認為標准庫中沒有為此內置任何內容,但是很容易編寫代碼:

import java.util.*;

public class Test
{
    public static void main(String[] args)        
    {
        System.out.println(isWrapperType(String.class));
        System.out.println(isWrapperType(Integer.class));
    }

    private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();

    public static boolean isWrapperType(Class<?> clazz)
    {
        return WRAPPER_TYPES.contains(clazz);
    }

    private static Set<Class<?>> getWrapperTypes()
    {
        Set<Class<?>> ret = new HashSet<Class<?>>();
        ret.add(Boolean.class);
        ret.add(Character.class);
        ret.add(Byte.class);
        ret.add(Short.class);
        ret.add(Integer.class);
        ret.add(Long.class);
        ret.add(Float.class);
        ret.add(Double.class);
        ret.add(Void.class);
        return ret;
    }
}

commons-lang ClassUtils有相關的方法

新版本有:

boolean isPrimitiveOrWrapped = 
    ClassUtils.isPrimitiveOrWrapper(object.getClass());

舊版本有wrapperToPrimitive(clazz)方法,該方法將返回原始對應關系。

boolean isPrimitiveOrWrapped = 
    clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;

Google 的 Guava 庫有一個Primitives 實用程序,可以檢查類是否是原始類型的包裝器類型: Primitives.isWrapperType(class)

Class.isPrimitive() 適用於基元

對於那些喜歡簡潔代碼的人。

private static final Set<Class> WRAPPER_TYPES = new HashSet(Arrays.asList(
    Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class));
public static boolean isWrapperType(Class clazz) {
    return WRAPPER_TYPES.contains(clazz);
}

從 Java 1.5 及更高版本開始,有一個稱為自動裝箱的新功能。 編譯器自己做這件事。 當它看到機會時,它會將原始類型轉換為其適當的包裝類。

這里可能發生的事情是當你聲明時

Object o = i;

編譯器會編譯這個語句說

Object o = Integer.valueOf(i);

這是自動裝箱。 這將解釋您收到的輸出。 Java 1.5 規范中的這個頁面更詳細地解釋了自動裝箱。

我認為這是由於自動裝箱

int i = 3;
Object o = i;
o.getClass().getName(); // prints Integer

您可以實現一個與這些特定裝箱類匹配的實用方法,並在某個類是原始類時提供給您。

public static boolean isWrapperType(Class<?> clazz) {
    return clazz.equals(Boolean.class) || 
        clazz.equals(Integer.class) ||
        clazz.equals(Character.class) ||
        clazz.equals(Byte.class) ||
        clazz.equals(Short.class) ||
        clazz.equals(Double.class) ||
        clazz.equals(Long.class) ||
        clazz.equals(Float.class);
}
public static boolean isValidType(Class<?> retType)
{
    if (retType.isPrimitive() && retType != void.class) return true;
    if (Number.class.isAssignableFrom(retType)) return true;
    if (AbstractCode.class.isAssignableFrom(retType)) return true;
    if (Boolean.class == retType) return true;
    if (Character.class == retType) return true;
    if (String.class == retType) return true;
    if (Date.class.isAssignableFrom(retType)) return true;
    if (byte[].class.isAssignableFrom(retType)) return true;
    if (Enum.class.isAssignableFrom(retType)) return true;
    return false;
}

Integer不是原始類型, Class.isPrimitive()沒有說謊。

你必須處理java的自動裝箱。
讓我們拿代碼

public class test
{
    public static void main(String [ ] args)
    {
        int i = 3;
        Object o = i;
        return;
    }
}
let's you inspect the generated bytecode. 你得到類 test.class 和讓你檢查生成的字節碼。
invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
如您所見,添加了 java 編譯器
調用靜態#2;  //方法java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
in o via astore_2 從您的 int 創建一個新的整數,然后通過 astore_2存儲在 o 中

只是為了讓您看到 isPrimitive 有可能返回 true(因為您有足夠的答案告訴您為什么它是 false):

public class Main
{
    public static void main(final String[] argv)
    {
        final Class clazz;

        clazz = int.class;
        System.out.println(clazz.isPrimitive());
    }
}

當方法接受“int”而不是“Integer”時,這在反射中很重要。

此代碼有效:

import java.lang.reflect.Method;

public class Main
{
    public static void main(final String[] argv)
        throws Exception
    {
        final Method method;

        method = Main.class.getDeclaredMethod("foo", int.class);
    }

    public static void foo(final int x)
    {
    }
}

此代碼失敗(找不到方法):

import java.lang.reflect.Method;

public class Main
{
    public static void main(final String[] argv)
        throws Exception
    {
        final Method method;

        method = Main.class.getDeclaredMethod("foo", Integer.class);
    }

    public static void foo(final int x)
    {
    }
}

我遲到了,但如果你正在測試一個領域,你可以使用getGenericType

import static org.junit.Assert.*;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

import org.junit.Test;

public class PrimitiveVsObjectTest {

    private static final Collection<String> PRIMITIVE_TYPES = 
            new HashSet<>(Arrays.asList("byte", "short", "int", "long", "float", "double", "boolean", "char"));

    private static boolean isPrimitive(Type type) {
        return PRIMITIVE_TYPES.contains(type.getTypeName());
    }

    public int i1 = 34;
    public Integer i2 = 34;

    @Test
    public void primitive_type() throws NoSuchFieldException, SecurityException {
        Field i1Field = PrimitiveVsObjectTest.class.getField("i1");
        Type genericType1 = i1Field.getGenericType();
        assertEquals("int", genericType1.getTypeName());
        assertNotEquals("java.lang.Integer", genericType1.getTypeName());
        assertTrue(isPrimitive(genericType1));
    }

    @Test
    public void object_type() throws NoSuchFieldException, SecurityException {
        Field i2Field = PrimitiveVsObjectTest.class.getField("i2");
        Type genericType2 = i2Field.getGenericType();
        assertEquals("java.lang.Integer", genericType2.getTypeName());
        assertNotEquals("int", genericType2.getTypeName());
        assertFalse(isPrimitive(genericType2));
    }
}

Oracle 文檔列出了 8 種原始類型。

正如一些人已經說過的,這是由於自動裝箱

可以創建一個實用方法來檢查對象的類是否為IntegerDouble等。但是無法知道對象是否是通過自動裝箱原始對象創建的 一旦被裝箱,它看起來就像一個明確創建的對象。

因此,除非您確定您的數組在沒有自動裝箱的情況下永遠不會包含包裝類,否則沒有真正的解決方案。

原始包裝器類型不會響應此值。 這是用於基元的類表示,盡管除了反射之外,我想不出太多的用途。 所以,例如

System.out.println(Integer.class.isPrimitive());

打印“假”,但

public static void main (String args[]) throws Exception
{
    Method m = Junk.class.getMethod( "a",null);
    System.out.println( m.getReturnType().isPrimitive());
}

public static int a()
{
    return 1;
}

打印“真”

這是我能想到的最簡單的方法。 包裝類只存在於java.lang包中。 除了包裝類之外, java.lang沒有其他類具有名為TYPE字段。 您可以使用它來檢查類是否為 Wrapper 類。

public static boolean isBoxingClass(Class<?> clazz)
{
    String pack = clazz.getPackage().getName();
    if(!"java.lang".equals(pack)) 
        return false;
    try 
    {
        clazz.getField("TYPE");
    } 
    catch (NoSuchFieldException e) 
    {
        return false;
    }           
    return true;        
}

從 Spring 獲取 BeanUtils http://static.springsource.org/spring/docs/3.0.x/javadoc-api/

Apache 變體(commons beans)可能具有類似的功能。

您可以通過下面的語句確定對象是否為包裝類型:

***objClass.isAssignableFrom(Number.class);***

您還可以使用 isPrimitive() 方法確定原始對象

public class CheckPrimitve {
    public static void main(String[] args) {
        int i = 3;
        Object o = i;
        System.out.println(o.getClass().getSimpleName().equals("Integer"));
        Field[] fields = o.getClass().getFields();
        for(Field field:fields) {
            System.out.println(field.getType());
        }
    }
}  

Output:
true
int
int
class java.lang.Class
int

十年,這個問題仍然是最新的,至少對我來說......如果'isPrimitive'與原語實例不兼容,它的關系是什么? 我知道'int.class'是原始的,所以我不需要問這個......好吧,我做了這個:

import java.lang.reflect.*;
class Test{
  public static void main(String[] args) throws Exception{
    char x=3; boolean b=true; int i=2;
    Object o= i;
    Object name =o.getClass().getField("TYPE").get(o);
    System.out.println(""+name);
  }
}

這將返回一個字符串,如“int”,“char”,“boolean”等。所有八個基元都有一個包裝類,它具有包含這些值的“TYPE”字段。 void類型也有。

另一種方式,實用:

import java.util.*;
import java.lang.reflect.*;
class Test{
  static void print(Object O){System.out.println(O);}
  public static void main(String[] args) throws Exception{
    List list2 = new ArrayList<Object>(List.of("word",2,3.0f,4.0,(char)65, a)); //where a= any user class instance. 
//And see like this list simulates a tuple like in Pyhton, another lack i see in Java.
//But indeed, this kind of List<Object> is still better then a immutable tuple. 
//And this was another of my doubts (tuples), and of other's people, as i've seen in my searchs at web.
    ver(list2);

  }
  static void ver(List lis){
    List prims = new ArrayList<String>(List.of("Boolean","Character","Byte","Double","Float","Integer","Long","Short"));
    for(Object o: lis){
      String s=o.getClass().getSimpleName();
      print((prims.contains(s)?"Yes":"No"));
    }
  }

輸出:否是是是是否

對於javapoet 的用戶,還有這種方式:

private boolean isBoxedPrimitive(Class<?> type) {
    return TypeName.get(type).isBoxedPrimitive();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM