web-dev-qa-db-ja.com

オブジェクトがプリミティブ型かどうかを判断する

_Object[]_配列があり、プリミティブな配列を見つけようとしています。 Class.isPrimitive()を使用しようとしましたが、何か間違ったことをしているようです:

_int i = 3;
Object o = i;

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

_Java.lang.Integer, false_を出力します。

正しい方法や代替手段はありますか?

103
drill3r

Object[]は決して本当にプリミティブになりません-参照を持っているからです!ここで、iの型はintであるのに対し、oによって参照されるオブジェクトの型は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;
    }
}
158
Jon Skeet

commons-langClassUtils には関連するmethodsがあります。

新しいバージョンには次のものがあります。

_boolean isPrimitiveOrWrapped = 
    ClassUtils.isPrimitiveOrWrapper(object.getClass());
_

古いバージョンにはwrapperToPrimitive(clazz)メソッドがあり、primitiveの対応を返します。

_boolean isPrimitiveOrWrapped = 
    clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
_
73
Bozho

GoogleのGuavaライブラリには、クラスがプリミティブのラッパータイプであるかどうかをチェックするPrimitivesユーティリティがあります。 http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/primitives/ Primitives.html

Primitives.isWrapperType(class)

Class.isPrimitive()はプリミティブに対して機能します

24
Andrejs

簡潔なコードが好きな人向け。

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);
}
16
Peter Lawrey

Java 1.5以降では、オートボクシングと呼ばれる新しい機能があります。コンパイラはこれを実行します。機会があると、プリミティブ型を適切なラッパークラスに変換します。

おそらくここで起こっているのはあなたが宣言するときです

Object o = i;

コンパイラはこのステートメントを次のようにコンパイルします

Object o = Integer.valueOf(i);

これは自動ボクシングです。これは、受け取っている出力を説明します。 Java 1.5仕様のこのページでは、オートボクシングについて詳しく説明しています。

8
Jose Chavez

Integerはプリミティブではなく、Class.isPrimitive()は嘘ではありません。

6
Bombe
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;
}
5
user3395079

これはauto-boxingが原因で起こると思います。

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);
}
5
bruno conde

Javaのオートボクシングに対処する必要があります。
コードを取得しましょう

public class test 
 {
 public static void main(String [] args)
 {
 int i = 3; 
 Object o = i; 
 return; 
} 
}
javap -cテスト
「test.Java」
 public class test extends Java.lang.Object {
 public test(); 
 Code:
 0:aload_0 
 1:特別な#1を呼び出します。 //メソッドJava/lang/Object。 "" :()V 
 4:return 
 

public static void main(Java.lang.String []); Code: 0:iconst_3 1:istore_1 2:iload_1 3:invokestatic#2; //メソッドJava/lang/Integer.valueOf:(I)Ljava/lang/Integer; 6:astore_2 7:return
}
invokestatic#2; //メソッドJava/lang/Integer.valueOf:(I)Ljava/lang/Integer;
その新しいオブジェクト
5
chendral

IsPrimitiveがtrueを返すことが可能であることがわかります(falseである理由を示す十分な回答があるため)。

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

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

これは、メソッドが「整数」ではなく「整数」を受け入れる場合に反映されます。

このコードは機能します:

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)
    {
    }
}
3
TofuBeer

すでに数人が言っているように、これは autoboxing によるものです。

オブジェクトのクラスがIntegerDoubleなどであるかどうかを確認するユーティリティメソッドをcould作成します。ただし、オブジェクトがプリミティブのオートボックス化によって作成されたかどうかを知る方法はありません;ボックス化されると、明示的に作成されたオブジェクトのように見えます。

そのため、オートボクシングなしでは配列にラッパークラスが含まれないことが確実でない限り、実際の解決策はありません。

2
Michael Myers

私はショーに遅れていますが、フィールドをテストしている場合は、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 docs は、8つのプリミティブ型をリストします。

2

Primitveラッパータイプはこの値に応答しません。これはプリミティブをクラスで表現するためのものですが、リフレクションは別として、それをあまりに多く使用することは考えられません。だから、例えば

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

「false」を出力しますが、

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;
}

「true」を出力します

2
Steve B.

SpringからBeanUtilsを入手 http://static.springsource.org/spring/docs/3.0.x/javadoc-api/

おそらく、Apacheのバリエーション(Commons Bean)にも同様の機能があります。

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;        
}
1
Rahul Bobhate

以下のステートメントにより、オブジェクトがラッパータイプかどうかを判断できます。

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

また、isPrimitive()メソッドを使用してプリミティブオブジェクトを決定することもできます

1
airblock

少なくとも私にとって、この質問はまだ10年あります...プリミティブのインスタンスで機能しない場合、「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」などの文字列を返します。8つのプリミティブにはすべて、これらの値を含む「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"));
    }
  }

出力:いいえはいはいはいはいいいえ

0
Carlos Leandro
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
0
Arham