কোনও বস্তু আদিম ধরণের কিনা তা নির্ধারণ করা হচ্ছে


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সর্বোপরি কাজ করে , অবশ্যই আদিম নিজেই। দেখে মনে হচ্ছে আমি পৃথকভাবে প্রতিটি প্রকারের জন্য পরীক্ষা করা এড়াতে পারব না, সুন্দর সমাধানের জন্য ধন্যবাদ।
drill3r

3
আমি অবাক হয়েছি যদি হ্যাশসেট ব্যবহারের ওভারহেডটি স্টেটমেন্টগুলি থাকে তবে কয়েকটির চেয়ে ভাল better
নাটেস

9
@ নাটেস: আমি বিশ্বাস করি এটি আরও বেশি পঠনযোগ্য, সে কারণেই আমি সেটাকে ওভারহেডটি সত্যিকারের বাধা হিসাবে প্রমাণ না করা পর্যন্ত "যদি" বিবৃতি না দিয়ে আমি তা দিয়ে যাই ।
জন স্কিটি

1
@ মার্ক: তারপরে এটি একটি খুব নির্দিষ্ট প্রসঙ্গ এবং এটিকে হিসাবে বিবেচনা করা উচিত। অটোবক্সিং কি এনামগুলিতে প্রযোজ্য? না, তারা ইতিমধ্যে রেফারেন্সের ধরণ। এগুলি কি অযোগ্য? না, কারণ তারা রেফারেন্সের ধরণ ... তালিকাটি চলছে। তাদেরকে আদিম বলা এ শব্দটির অর্থটি বিশালভাবে দুর্বল করে দেয় এবং এতে আমি কোনও লাভ দেখছি না।
জন স্কিটি

2
@ নাটস দ্য HashSetও (1) এ অ্যাক্সেসের অনুমতি দেয় যেখানে এক সারি ifবিবৃতি বা switchবিবৃতি সবচেয়ে খারাপ ক্ষেত্রে ও (# মোড়কের #) প্রয়োজন) অনুশীলনে এটি প্রশ্নবিদ্ধ যদি if9 টি মোড়কের নির্দিষ্ট সংখ্যার বিবৃতিগুলি সর্বোপরি হ্যাশ-ভিত্তিক অ্যাক্সেসের চেয়ে দ্রুত না হয়।
কার্ল রিখটার

83

কমন্স-ল্যাংয়ের ClassUtils প্রাসঙ্গিক পদ্ধতি রয়েছে

নতুন সংস্করণটিতে রয়েছে:

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

পুরানো সংস্করণগুলির wrapperToPrimitive(clazz)পদ্ধতি রয়েছে, যা আদিম চিঠিপত্র ফিরিয়ে দেবে ।

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

1
এটি v3.1 অবধি যুক্ত করা হয়নি , আপনার লিঙ্কটি 2.5 এপিআই প্রতিবিম্বিত করে। আমি এটা সংশোধন করেছি।
javamonkey79

8
স্প্রিংয়ের ক্লাস ইউটিলেস ক্লাসও রয়েছে , সুতরাং আপনি যদি ইতিমধ্যে স্প্রিং ব্যবহার করছেন তবে এটি আরও সুবিধাজনক হতে পারে।
সের্গেই


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
কেন শূন্য? আপনি কীভাবে একটি শূন্যতা আবদ্ধ করবেন?
শেরভিন আসগরী

2
@ শেরভিন void.class.isPrimitive()সত্য প্রত্যাবর্তন করেছেন
অ্যাসিলিয়াস

1
অকার্যকর খালি এবং শুধুমাত্র বৈধ মান Voidহল nullএটি একটি তৈরি করার জন্য দরকারী); Callable<Void>যা Callable যা কিছু ফেরত না।
পিটার লরে

8

জাভা ১.৫ এবং তার থেকে শুরু করে অটো-বক্সিং নামে একটি নতুন বৈশিষ্ট্য রয়েছে। সংকলক নিজেই এটি করে। যখন এটি কোনও সুযোগ দেখে, এটি একটি আদিম প্রকারটিকে তার উপযুক্ত মোড়কের ক্লাসে রূপান্তর করে।

সম্ভবত এখানে যা ঘটছে তা আপনি যখন ঘোষণা করেন is

Object o = i;

সংকলক এই বিবৃতিটি বলার মতো সংকলন করবে

Object o = Integer.valueOf(i);

এটি অটো-বক্সিং। এটি আপনার প্রাপ্ত আউটপুটটি ব্যাখ্যা করবে। জাভা ০.৫ স্পেসের এই পৃষ্ঠাটি অটো-বক্সিং সম্পর্কে আরও বিশদ ব্যাখ্যা করে।


6
সম্পূর্ণ সত্য নয়। এটি কোনও পূর্ণসংখ্যার সাথে নতুন নয়, বরং এটি পূর্ণসংখ্যা বলে।
স্টিভ কুও

1
@ স্টিভকুও Integer.valueOf(int)কেবল তখনই ক্যাশেড মান প্রদান করে যখন যুক্তিটি "বাইট" হয় (পড়ুন: -128, 127 এর মধ্যে উভয়ই অন্তর্ভুক্ত)। অন্যথায় এটি কল new Integer(int)। দেখুন: developer.classpath.org/doc/java/lang/... , hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/...
Dragas

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করতে পারেন ==। ক্লাসগুলি সিঙ্গেলন।
বোয়ান

5

আপনি জাভা অটো-বক্সিং মোকাবেলা করতে হবে।
কোডটি নেওয়া যাক

পাবলিক ক্লাস পরীক্ষা
{
    পাবলিক স্ট্যাটিক শূন্য মূল (স্ট্রিং [] আরগস)
    {
        int i = 3;
        অবজেক্ট o = i;
        আসতে;
    }
}
আপনি ক্লাসের টেস্ট.ক্লাস এবং জাভ্যাপ-সি পরীক্ষাটি আসুন আপনাকে উত্পন্ন বাইকোডটি পরীক্ষা করতে দিন।
"Test.java" থেকে সংকলিত
পাবলিক ক্লাস পরীক্ষা java.lang.Object extend প্রসারিত
পাবলিক পরীক্ষা ();
  কোড:
   0: aload_0
   1: ইনভোকেসপেশিয়াল # 1; // পদ্ধতি জাভা / ল্যাং / অবজেক্ট। "" :() ভি
   4: ফিরে

পাবলিক স্ট্যাটিক শূন্য মূল (java.lang.String []); কোড: 0: আইকনস্ট_3 1: istore_1 2: ইলোয়াড_1 3: ইনভোকাস্ট্যাটিক # 2; // পদ্ধতি জাভা / ল্যাং / পূর্ণসংখ্যা.ভালিউ অফ: (আই) লাজাভা / ল্যাং / পূর্ণসংখ্যা; 6: অ্যাস্টোর_2 7: ফিরে

}

আপনি দেখতে পারেন জাভা সংকলক যুক্ত করা
ইনভোকাস্ট্যাটিক # 2; // পদ্ধতি জাভা / ল্যাং / পূর্ণসংখ্যা.ভালিউ অফ: (আই) লাজাভা / ল্যাং / পূর্ণসংখ্যা;
আপনার int থেকে একটি নতুন পূর্ণসংখ্যা তৈরি করতে এবং তারপরে সেই নতুন অবজেক্টটি অ্যাস্টোর_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());
    }
}

যখন কোনও পদ্ধতি "পূর্ণসংখ্যার" পরিবর্তে "ইনট" গ্রহণ করে তখন এটি প্রতিবিম্বিত হয়।

এই কোডটি কাজ করে:

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। কোনও ক্লাস র্যাপার ক্লাস কিনা তা পরীক্ষা করতে আপনি এটি ব্যবহার করতে পারেন।

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.