यह निर्धारित करना कि कोई वस्तु आदिम प्रकार की है


114

मेरे पास एक Object[]सरणी है, और मैं उन लोगों को खोजने की कोशिश कर रहा हूं जो आदिम हैं। मैंने उपयोग करने की कोशिश की है Class.isPrimitive(), लेकिन ऐसा लगता है कि मैं कुछ गलत कर रहा हूं:

int i = 3;
Object o = i;

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

प्रिंट java.lang.Integer, false

क्या कोई सही तरीका है या कोई विकल्प है?


12
संक्षेप में: int.class.isPrimitive()पैदावार true; Integer.class.isPrimitive()पैदावार false
पैट्रिक

जवाबों:


165

एक में प्रकार वास्तव में आदिम Object[]नहीं होगा - क्योंकि आपको संदर्भ मिल गए हैं! यहाँ उस प्रकार का है जबकि संदर्भित ऑब्जेक्ट का प्रकार हैiintoInteger (ऑटो-बॉक्सिंग के कारण)।

ऐसा लगता है कि आपको यह पता लगाने की आवश्यकता है कि क्या प्रकार "आदिम के लिए आवरण" है। मुझे नहीं लगता कि इसके लिए मानक पुस्तकालयों में कुछ भी बनाया गया है, लेकिन इसे कोड करना आसान है:

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

मैं इस धारणा के तहत था कि यह आदिम आवरणों के लिए काम करता है, लेकिन यह केवल java.lang.<type>.TYPEआखिरकार काम करता है , जो निश्चित रूप से आदिम है। ऐसा लगता है कि मैं व्यक्तिगत रूप से प्रत्येक प्रकार के लिए जाँच से बचने में सक्षम नहीं होगा, अच्छा समाधान के लिए धन्यवाद।
15 अगस्त को ड्रिल

3
मुझे आश्चर्य है कि अगर बयानों के अनुसार हशसेट का उपयोग करने का ओवरहेड वास्तव में कुछ से बेहतर है।
नैट्स

9
@ नेट्स: मेरा मानना ​​है कि यह अधिक पठनीय है, यही कारण है कि मैं "अगर" बयानों के बजाय इसके साथ जाऊंगा जब तक कि यह साबित नहीं हुआ कि सेट का ओवरहेड एक वास्तविक अड़चन है।
जॉन स्कीट

1
@ चिह्न: तब यह एक बहुत ही विशिष्ट संदर्भ है, और इस तरह से व्यवहार किया जाना चाहिए। क्या ऑटोबॉक्सिंग एनम पर लागू होता है? नहीं, वे पहले से ही संदर्भ प्रकार हैं। क्या वे अशक्त हैं? नहीं, क्योंकि वे संदर्भ प्रकार हैं ... सूची चलती है। उन्हें आदिम कहलाने से इस शब्द का अर्थ बेहद कमज़ोर हो जाता है, और मुझे इसमें कोई लाभ नहीं दिखता है।
जॉन स्कीट

2
@ नेट्स HashSetO (1) में एक्सेस की अनुमति देता है जबकि ifस्टेटमेंट्स या switchस्टेटमेंट्स में सबसे खराब स्थिति में O (# रैपरों की) की आवश्यकता होती है। व्यवहार में यह संदिग्ध है अगर if9 रैपरों की निश्चित संख्या के लिए बयान सब के बाद हैश-आधारित पहुंच से अधिक तेज नहीं है।
कार्ल रिक्टर

83

कॉमन्स-लैंग ClassUtils में प्रासंगिक विधियां हैं

नए संस्करण में है:

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

पुराने संस्करणों में wrapperToPrimitive(clazz)विधि है, जो आदिम पत्राचार लौटाएगा ।

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

1
यह v3.1 तक जोड़ा नहीं गया था , आपके लिंक ने 2.5 API परिलक्षित किया। मैंने इसे सुधारा है।
javamonkey79

8
स्प्रिंग में भी क्लासयूटिल्स क्लास है, इसलिए यदि आप पहले से ही स्प्रिंग का उपयोग कर रहे हैं तो यह अधिक सुविधाजनक हो सकता है।
सर्गेई

25

Google की अमरुद लाइब्रेरी में एक आदिम उपयोगिता है जो यह जाँचती है कि क्या कोई वर्ग किसी आदिम के लिए एक आवरण प्रकार है:Primitives.isWrapperType(class)

प्राइमरी के लिए Class.isPrimitive () काम करता है


4
someObject.getClass () .Primitive ()
कुंभ राशि

17

उन लोगों के लिए जो कोड पसंद करते हैं।

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

1
क्यों Void.class? आप एक शून्य कैसे लपेटते हैं?
शेरविन असगरी 15'11

2
@ शेरविन void.class.isPrimitive()सच है
assylias 22

1
शून्य खाली है और एक के लिए ही मान्य मूल्य Voidहै nullयह एक बनाने के लिए उपयोगी है); Callable<Void>जो एक प्रतिदेय जो कुछ भी वापस नहीं करता है।
पीटर लॉरी

8

जावा 1.5 और उसके बाद से, एक नई सुविधा है, जिसे ऑटो-बॉक्सिंग कहा जाता है। कंपाइलर खुद ऐसा करता है। जब यह एक अवसर देखता है, तो यह एक आदिम प्रकार को अपने उपयुक्त आवरण वर्ग में परिवर्तित करता है।

जब आप घोषणा करते हैं तो यहां क्या हो रहा है

Object o = i;

संकलनकर्ता इस कथन को संकलित करेगा

Object o = Integer.valueOf(i);

यह ऑटो-बॉक्सिंग है। यह आपको प्राप्त होने वाले आउटपुट की व्याख्या करेगा। जावा 1.5 कल्पना से यह पृष्ठ ऑटो-बॉक्सिंग को अधिक विस्तार से बताता है।


6
पूरी तरह से सच नहीं है। यह एक Integer नया नहीं है, बल्कि इसे Integer.valueOf (int) कहता है जो इंटेगर के कुछ उदाहरणों को कैशिंग करता है।
स्टीव कूओ

1
@SteveKuo Integer.valueOf(int)केवल तभी कैश्ड वैल्यू देता है जब तर्क "बाइट" होता है (पढ़ें: -128, 127, दोनों समावेशी)। नहीं तो पुकारता है new Integer(int)। देखें: developer.classpath.org/doc/java/lang/… , hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7n7986d/src/share/…
ड्रैगस

6

Integer एक आदिम नहीं है, Class.isPrimitive() झूठ नहीं बोल रहा है।


6

मुझे लगता है कि ऑटो-बॉक्सिंग के कारण ऐसा होता है ।

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
आप सुरक्षित रूप से बदल सकते हैं .equalsकरने के लिए ==। कक्षाएं एकल हैं।
Boann

5

आपको जावा के ऑटो-बॉक्सिंग से निपटना होगा।
कोड लेते हैं

पब्लिक क्लास टेस्ट
{
    सार्वजनिक स्थैतिक शून्य main (String [] args)
    {
        int i = 3;
        वस्तु ओ = मैं;
        वापसी;
    }
}
आप वर्ग परीक्षण प्राप्त करें। क्लब और javap -c परीक्षण करते हैं ताकि आप जेनरेट किए गए का निरीक्षण कर ।
"Test.java" से संकलित
पब्लिक क्लास टेस्ट में फैली java.lang.Object {
सार्वजनिक परीक्षण ();
  कोड:
   0: aload_0
   1: invokespecial # 1; // विधि जावा / लैंग / ऑब्जेक्ट। "" :() वी
   4: वापसी

सार्वजनिक स्थैतिक शून्य मुख्य (java.lang.String []); कोड: 0: iconst_3 1: istore_1 2: iload_1 3: इनवोकैस्टेटिक # 2; // मेथड जावा / लैंग / इंटेगर.वेल्यूऑफ: (I) लाजवा / लैंग / इंटेगर; 6: astore_2 7: वापसी

}

जैसा कि आप जावा कंपाइलर को जोड़कर देख सकते हैं
invokestatic # 2; // मेथड जावा / लैंग / इंटेगर.वेल्यूऑफ: (I) लाजवा / लैंग / इंटेगर;
अपने int से एक नया Integer बनाने के लिए और फिर astore_2 के माध्यम से उस नई ऑब्जेक्ट को स्टोर करता है


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

3

बस इतना है कि आप यह देख सकते हैं कि यह संभव है कि यह सही हो।

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

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

यह उस समय परावर्तन में मायने रखता है जब कोई विधि "इंटगर" के बजाय "int" में ले जाती है।

यह कोड काम करता है:

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

2

जैसा कि कई लोग पहले ही कह चुके हैं, यह ऑटोबॉक्सिंग के कारण होता है ।

आप हो सकता है की जांच करने के लिए एक उपयोगिता विधि निर्माण, वस्तु की क्लास है Integer, Doubleआदि लेकिन वहाँ है कोई रास्ता नहीं जानना चाहता है कि एक वस्तु एक आदिम autoboxing द्वारा बनाया गया था ; एक बार बॉक्सिंग करने के बाद, यह स्पष्ट रूप से बनाई गई वस्तु जैसा दिखता है।

इसलिए जब तक आप यह सुनिश्चित नहीं कर लेते हैं कि आपके सरणी में ऑटोबॉक्सिंग के बिना एक आवरण वर्ग कभी नहीं होगा, कोई वास्तविक समाधान नहीं है।


2

प्राइमिटव रैपर प्रकार इस मान का जवाब नहीं देंगे। यह प्राथमिकताओं के वर्ग प्रतिनिधित्व के लिए है, हालांकि प्रतिबिंब से अलग मैं इसके लिए बहुत सारे उपयोगों के बारे में नहीं सोच सकता। इसलिए, उदाहरण के लिए

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

प्रिंट "सच"


2

मुझे शो के लिए देर हो रही है, लेकिन यदि आप किसी फ़ील्ड का परीक्षण कर रहे हैं, तो आप उपयोग कर सकते हैं 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));
    }
}

ओरेकल डॉक्स 8 आदिम प्रकार की सूची।


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
मैं सहमत हूँ। लेकिन अब तक, यह सबसे सरल तरीका है जिसके बारे में मैं सोच सकता था। :)
राहुल बोबेट


1

आप निर्धारित कर सकते हैं कि क्या वस्तु कथन के अनुसार आवरण प्रकार है:

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

और आप isPrimitive () पद्धति का उपयोग करके एक आदिम वस्तु का निर्धारण भी कर सकते हैं


0
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

Javapoet के उपयोगकर्ताओं के लिए, इस तरह से भी है:

private boolean isBoxedPrimitive(Class<?> type) {
    return TypeName.get(type).isBoxedPrimitive();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.