Java में a.getClass () और A.class में क्या अंतर है?


101

जावा में क्या पेशेवरों / विपक्ष उपयोग करने के लिए विकल्प आसपास मौजूद a.getClass()या A.class? जहाँ कहीं भी Class<?>उम्मीद की जाती है, वहाँ या तो उपयोग किया जा सकता है, लेकिन मुझे लगता है कि दोनों अलग-अलग परिस्थितियों में उपयोग करने के लिए प्रदर्शन या अन्य सूक्ष्म लाभ होंगे (जैसे कि वहाँ हैं Class.forName()और साथ ही ClassLoader.loadClass()

जवाबों:


163

मैं उनके पक्ष / विपक्ष के संदर्भ में उनकी तुलना नहीं करूंगा क्योंकि उनके अलग-अलग उद्देश्य हैं और दोनों के बीच बनाने के लिए शायद ही कोई "पसंद" हो।

  • a.getClass()का रनटाइम प्रकार लौटाता है a। यानी, अगर आपके पास है A a = new B();तो क्लास a.getClass()वापस कर देंगे B

  • A.classAकक्षा के लिए सांख्यिकीय रूप से मूल्यांकन करता है , और इसका उपयोग अक्सर प्रतिबिंब से संबंधित अन्य उद्देश्यों के लिए किया जाता है।

प्रदर्शन के संदर्भ में, एक औसत दर्जे का अंतर हो सकता है, लेकिन मैं इसके बारे में कुछ नहीं कहूंगा क्योंकि अंत में यह जेवीएम और / या कंपाइलर पर निर्भर है।


इस पोस्ट को यहाँ एक लेख के रूप में फिर से लिखा गया है


2
कैसे के बारे में A.class.getClass()?
user1870400

5
यह आपको उस Classवस्तु का प्रतिनिधित्व करने वाले वर्ग की A.classवस्तु देगा जो फिर से एक उदाहरण है java.lang.Class
एयरोब

कैसे के बारे में A.getClass().class?
शिखर मैनाले

@ ShikharMainalee, अगर वास्तव Aमें कोई वर्ग है तो इसका कोई मतलब नहीं है। getClassकक्षाओं पर कोई स्थिर विधि नहीं है ।
एयरोबे

यह यहाँ कैसे सुझाव से संबंधित है कि वे अलग-अलग वर्ग लोडर को भी इंगित करते हैं। यह भी दोनों के बीच एक महत्वपूर्ण अंतर हो सकता है?
जिम

32

वे वास्तव में भिन्न हैं जहां आप उन्हें उपयोग कर सकते हैं। A.classसंकलित समय पर काम करता है जबकि a.getClass()एक प्रकार की आवृत्ति की आवश्यकता होती है Aऔर रनटाइम पर काम करता है।

प्रदर्शन में अंतर भी हो सकता है। जबकि A.classसंकलक द्वारा हल किया जा सकता है क्योंकि यह वास्तविक प्रकार जानता है A, a.getClass()रनटाइम पर हो रही एक आभासी विधि कॉल है।

संदर्भ के लिए, बायकटोड पर एक संकलक लक्ष्यीकरण आम तौर पर निम्नलिखित निर्देश देता है Integer.getClass():

aload_1
invokevirtual   #3; //Method java/lang/Object.getClass:()Ljava/lang/Class;

और निम्नलिखित के लिए Integer.class:

//const #3 = class  #16;    //  java/lang/Integer

ldc_w   #3; //class java/lang/Integer

पूर्व में आमतौर पर एक आभासी विधि प्रेषण शामिल होता है और इसलिए संभवतः निष्पादित होने में अधिक समय लगता है। हालांकि अंत में जेवीएम पर निर्भर है।


1
[१] तकनीकी रूप से जावा लैंग्वेज स्पेसिफिकेशन में किसी भी निरंतर पूल का उल्लेख नहीं है ...
aioobe

@ आईओओबी: मुझे लगता है कि आप सही हैं, इसीलिए मैंने सन जेडडीके द्वारा उत्पन्न बाईटेकोड की जाँच की।
टॉमाज़ नर्कविक्ज़

1
... जो तकनीकी रूप से बोलना एक आधिकारिक उत्तर प्रदान नहीं करता है, क्योंकि जावा लैंग्वेज स्पेसिफिकेशंस शब्दश: जब यह शब्दशः की बात करता है, तब तक यह बायटेकोड का उल्लेख नहीं करता है।
aioobe

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

1
यदि आप इसे पसंद नहीं करते हैं तो वापस ;-)
aioobe

8

नीचे दिए गए उदाहरणों पर एक नज़र डालें

a.getClass()!= A.class, यानी ए का उदाहरण नहीं है, बल्कि ए के एक अनाम उप वर्ग का है

a.getClass() प्रकार ए की एक उदाहरण की आवश्यकता है


4

का प्रयोग करें a.getClassआप वर्ग / प्रकार का एक उदाहरण है और आप इसे का सही प्रकार प्राप्त करने के लिए चाहते हैं। जबकि a.classजब आप प्रयोग किया जाता है typeउपलब्ध है और आप इसे का उदाहरण बनाना चाहते हैं। संकलन समय पर मूल्यांकन किए जाने के दौरान रनटाइम प्रकार का रिटर्न
भी । के प्रदर्शन को ध्यान में रखते हुए और , की तुलना में बेहतर प्रदर्शन किया है । उदाहरण :getClass().class
getClass().class.classgetClass()

public class PerfomanceClass {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        long time=System.nanoTime();
        Class class1="String".getClass();
        class1="String".getClass();
        class1="String".getClass();
        class1="String".getClass();

        System.out.println("time (getClass()) :"+(System.nanoTime()-time)+" ns");     


        long time2=System.nanoTime();
        Class class2=String.class;
        class2=String.class;
        class2=String.class;
        class2=String.class;

        System.out.println("time (.class):"+(System.nanoTime()-time2)+" ns");
    }

}

आउटपुट:

time (getClass()) : 79410 ns
time (.class)     : 8032 ns

1

एक अंतर है जिसे मैं जोड़ना चाहूंगा। मान लीजिए कि आपके पास एक क्लास एक कंस्ट्रक्टर है जैसा कि नीचे एक सुपर क्लास के साथ दिखाया गया है जो क्लास ऑब्जेक्ट लेता है। आप चाहते हैं कि जब भी उपवर्ग ऑब्जेक्ट बनाया जाए तो उपक्लास की क्लास ऑब्जेक्ट सुपर क्लास में जाए। नीचे कोड संकलित नहीं करेगा क्योंकि आप एक कंस्ट्रक्टर में एक इंस्टेंस विधि नहीं कह सकते। उस मामले में यदि आप के myObject.getClass()साथ प्रतिस्थापित करते हैं MyClass.class। यह पूरी तरह से चलेगा।

Class MyClass
{
    private MyClass myObject = new MyClass();
    public MyClass()
    {
        super(myObject.getClass()); //error line compile time error
    }
}

2
एक ही कक्षा के उदाहरण चर के रूप में एक ही वर्ग के उदाहरण होने से .... आप पुनरावर्ती रूप से ऑब्जेक्ट बनाते हुए ढेर स्थान से बाहर निकल जाएंगे।
अनिकेत ठाकुर

1

दिलचस्प है कि प्रदर्शन में अंतर ऊपर के उदाहरण में उल्लिखित है, अन्य कारणों से संबंधित प्रतीत होता है। 3 विभिन्न वर्गों का उपयोग करना, औसत में प्रदर्शन लगभग समान होगा:

import java.util.LinkedHashMap;
public class PerfomanceClass {

public static void main(String[] args) {

    long time = System.nanoTime();
    Class class1 = "String".getClass();
    Class class11 = "Integer".getClass();
    Class class111 = "LinkedHashMap".getClass();

    System.out.println("time (getClass()) :" + (System.nanoTime() - time) + " ns");

    long time2 = System.nanoTime();
    Class class2 = String.class;
    Class class22 = Integer.class;
    Class class222 = LinkedHashMap.class;

    System.out.println("time (.class):" + (System.nanoTime() - time2) + " ns");
} }

आउटपुट कुछ इस तरह होगा:

time (getClass()) :23506 ns 
time (.class):23838 ns

और कॉल के क्रम को बदलने से परिणाम और भी getClass()तेज़ होंगे।

import java.util.LinkedHashMap;

public class PerfomanceClass {

public static void main(String[] args) {
    long time2 = System.nanoTime();
    Class class2 = LinkedHashMap.class;

    System.out.println("time (.class):" + (System.nanoTime() - time2) + " ns");

    long time = System.nanoTime();
    Class class1 = "LinkedHashMap".getClass();

    System.out.println("time (getClass()) :" + (System.nanoTime() - time) + " ns");
}}

आउटपुट:

time (.class):33108 ns
time (getClass()) :6622 ns

"3 अलग-अलग वर्गों का उपयोग करना"। लेकिन getClass () अनुभाग में आप 3 विभिन्न वर्गों का उपयोग नहीं कर रहे हैं। ये सभी स्ट्रिंग हैं और इसलिए getClass सभी उदाहरणों के लिए java.lang.String वापस आ जाएगी।
किलन

1

p.getClass(), जहां pएक वस्तु का एक उदाहरण है, इस ऑब्जेक्ट के रनटाइम वर्ग को वापस करता है ppएक प्रकार नहीं हो सकता है जो एक संकलन-समय त्रुटि का कारण होगा, यह एक वस्तु का एक उदाहरण होना चाहिए।

// B extends A
A a = new B();
System.out.println(a.getClass());
//output: class B

p.classअभिव्यक्ति है। .classवर्ग वाक्यविन्यास कहा जाता है। pएक प्रकार है। यह एक वर्ग, इंटरफ़ेस या सरणी और यहां तक ​​कि एक आदिम प्रकार का नाम हो सकता है। a.getClass() == B.class

यदि एक प्रकार उपलब्ध है और एक उदाहरण है तो getClassटाइप का नाम प्राप्त करने के लिए विधि का उपयोग करना संभव है । अन्यथा, .classसिंटैक्स का उपयोग करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.