विधियों के स्थैतिक आयात के लिए एक अच्छा उपयोग मामला क्या है?


137

बस एक समीक्षा टिप्पणी मिली कि मेरी विधि का स्थिर आयात एक अच्छा विचार नहीं था। स्थैतिक आयात डीए वर्ग से एक विधि का था, जिसमें ज्यादातर स्थिर विधियां हैं। तो व्यापार तर्क के बीच में मैं एक दा गतिविधि थी जो जाहिरा तौर पर वर्तमान वर्ग से संबंधित थी:

import static some.package.DA.*;
class BusinessObject {
  void someMethod() {
    ....
    save(this);
  }
} 

समीक्षक इस बात के लिए उत्सुक नहीं था कि मैं कोड बदल दूं और मैंने नहीं किया लेकिन मैं उससे सहमत हूं। स्थैतिक-आयात न करने का एक कारण यह था कि यह भ्रमित था कि विधि को कहां परिभाषित किया गया था, यह वर्तमान वर्ग में नहीं था और किसी भी सुपरक्लास में नहीं था, इसलिए इसकी परिभाषा (वेब ​​आधारित समीक्षा प्रणाली की पहचान के लिए क्लिक करने योग्य नहीं है) आईडीई :-) जैसे लिंक मैं वास्तव में इस मामले को नहीं समझता हूं, स्थैतिक-आयात अभी भी काफी नए हैं और जल्द ही हम सभी को उनका पता लगाने की आदत हो जाएगी।

लेकिन दूसरा कारण, जिस पर मैं सहमत हूं, वह यह है कि एक अयोग्य पद्धति कॉल वर्तमान वस्तु से संबंधित है और इसमें छलांग नहीं लगानी चाहिए। लेकिन अगर यह वास्तव में होता है, तो यह उस सुपर क्लास का विस्तार करने के लिए समझ में आता है।

तो, जब करता है यह स्थिर आयात तरीकों को समझ बनाने? आपने कब किया है क्या जिस तरह से अयोग्य कॉल दिखते हैं, क्या आपको पसंद है?

संपादित करें: लोकप्रिय राय यह प्रतीत होती है कि स्थैतिक-आयात विधियाँ यदि कोई उन्हें वर्तमान वर्ग के तरीकों के रूप में भ्रमित करने वाला नहीं है। उदाहरण के लिए java.lang.Math और java.awt.Color से विधियाँ। लेकिन अगर abs और getAlpha अस्पष्ट नहीं हैं, तो मैं नहीं देखता कि readEmployee क्यों है। प्रोग्रामिंग विकल्पों में से अधिकांश के रूप में, मुझे लगता है कि यह भी एक व्यक्तिगत प्राथमिकता है।

आपकी प्रतिक्रिया के लिए धन्यवाद दोस्तों, मैं सवाल बंद कर रहा हूं।


2
यहाँ स्थैतिक आयात का बहुत अच्छा उपयोग है: ibm.com/developerworks/library/j-ft18
intrepidis

1
@ mr5 का सिंटैक्स है import static, फीचर हैstatic import
Miserable Variable

जवाबों:


150

यह सन के गाइड से है जब उन्होंने फीचर (मूल में जोर) जारी किया:

तो आपको स्थैतिक आयात का उपयोग कब करना चाहिए? बहुत विरल! केवल तब ही इसका उपयोग करें जब आपको अन्यथा स्थिरांक की स्थानीय प्रतियाँ घोषित करने, या वंशानुक्रम (कॉन्स्टेंट इंटरफ़ेस एंटीट्रोनफ़ॉर्म) का दुरुपयोग करने के लिए लुभाया जाएगा। ... यदि आप स्थैतिक आयात सुविधा का उपयोग करते हैं, तो यह आपके प्रोग्राम को अपठनीय और अस्वीकार्य बना सकता है, आपके द्वारा आयात किए जाने वाले सभी स्थैतिक सदस्यों के साथ इसके नामस्थान को प्रदूषित करता है। आपके कोड के पाठक (आपके सहित, आपके लिखे जाने के कुछ महीने बाद) को यह पता नहीं होगा कि एक स्थिर सदस्य किस वर्ग से आता है। सभी स्थिर सदस्यों को एक वर्ग से आयात करना विशेष रूप से पठनीयता के लिए हानिकारक हो सकता है; यदि आपको केवल एक या दो सदस्यों की आवश्यकता है, तो उन्हें व्यक्तिगत रूप से आयात करें।

( https://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html )

दो भाग हैं जिन्हें मैं विशेष रूप से कॉल करना चाहता हूं:

  • स्थैतिक आयात का उपयोग केवल तब करें जब आपको "दुरुपयोग विरासत" का प्रलोभन दिया गया था। इस मामले में, क्या आपके पास BusinessObject होने का लालच होगा extend some.package.DA? यदि हां, तो स्थिर आयात इसे संभालने का एक साफ तरीका हो सकता है। यदि आपने कभी इसका विस्तार करने का सपना नहीं देखा होगा some.package.DA, तो यह संभवतः स्थैतिक आयात का एक खराब उपयोग है। टाइप करते समय कुछ वर्णों को सहेजने के लिए इसका उपयोग न करें।
  • व्यक्तिगत सदस्यों को आयात करें। के import static some.package.DA.saveबजाय कहें DA.*। इससे यह पता लगाना बहुत आसान हो जाएगा कि यह आयातित विधि कहां से आ रही है।

व्यक्तिगत रूप से, मैंने इस भाषा सुविधा का उपयोग बहुत कम ही किया है, और लगभग हमेशा केवल स्थिरांक या एनम के साथ, कभी तरीकों के साथ नहीं। मेरे लिए व्यापार-बंद, लगभग कभी भी इसके लायक नहीं है।


9
माना। मैंने कभी-कभार स्थैतिक आयात वाली वेईरी का उपयोग किया है, जहां उन्होंने वास्तव में कोड का पालन करना काफी आसान बना दिया है।
नील कॉफ़ी

65

स्थिर आयात के लिए एक और उचित उपयोग JUnit 4 के साथ है। JUnit विधियों के पुराने संस्करणों में जैसे assertEqualsऔर failटेस्ट क्लास विस्तारित होने के बाद विरासत में मिला junit.framework.TestCase

// old way
import junit.framework.TestCase;

public class MyTestClass extends TestCase {
    public void myMethodTest() {
        assertEquals("foo", "bar");
    }
}

JUnit 4 में, परीक्षण कक्षाओं को अब विस्तार करने की आवश्यकता नहीं है TestCaseऔर इसके बजाय एनोटेशन का उपयोग कर सकते हैं। इसके बाद आप एस्ट्रल विधियों को सांख्यिकीय रूप से आयात कर सकते हैं org.junit.Assert:

// new way
import static org.junit.Assert.assertEquals;

public class MyTestClass {
    @Test public void myMethodTest() {
        assertEquals("foo", "bar");
        // instead of
        Assert.assertEquals("foo", "bar");
    }
}

JUnit दस्तावेजों का उपयोग इस तरह से।


4
मैं मान जाऊंगा। परीक्षण के मामलों को सरल बनाना एक ऐसा स्थान है जहां इरादे को गलत समझा जाना संभव नहीं है।
बिल माइकेल

6
हमने अपनी परियोजना पर यह किया है और वास्तव में मुखर () का उपयोग करने वाले लोगों के साथ समस्या थी और गलत तरीके से सोच रहे थे कि यह मुखर पैकेज के स्थैतिक आयात से आता है। एक बार जब हमें यह समस्या मिली, तो हमारे कोड-बेस के एक त्वरित स्कैन ने हमारे परीक्षणों में इसके लगभग 30 उदाहरण पाए, जिसका अर्थ है कि परीक्षण रूपरेखा निष्पादित होने पर 30 दावे नहीं चलाए जा रहे थे क्योंकि जब हम परीक्षण चलाते हैं तो DEBUG ध्वज सेट नहीं होता है।
क्रिस विलियम्स

27

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

import static com.example.UtilityClassWithFrequentlyUsedMethods.myMethod;

public class MyClass {
    public void doSomething() {
        int foo= UtilityClassWithFrequentlyUsedMethods.myMethod();
        // can be written less verbosely as
        int bar = myMethod();
    }
}

इसके फायदे और नुकसान हैं। यह विधि को परिभाषित करने के बारे में कुछ तत्काल जानकारी खोने की कीमत पर कोड को थोड़ा अधिक पठनीय बनाता है। हालाँकि, एक अच्छी IDE आपको परिभाषा में जाने देगी, इसलिए यह अधिक समस्या नहीं है।

आपको अभी भी इस संयम का उपयोग करना चाहिए, और केवल तभी जब आप खुद को आयातित फ़ाइल से चीजों का उपयोग करते हुए कई बार पाएं।

संपादित करें: अद्यतनों को विधियों के लिए और अधिक विशिष्ट होना चाहिए, क्योंकि यह प्रश्न किसका उल्लेख कर रहा है। यह सिद्धांत लागू होता है कि क्या आयात किया जा रहा है (स्थिरांक या तरीके)।


1
मेरा सवाल स्टैटिक-इम्पोर्ट करने के तरीकों के बारे में है , न कि फील्ड्स पर।
दु: खद परिवर्तनशील

7
शायद UtilityClassWithFrequentlyUsedMethodsछोटा करने की जरूरत है।
स्टीव कू

5
@SteveKuo निश्चित रूप से InternalFrameTitlePaneMaximizeButtonWindowNotFocusedState से कम : P
अनिर्बान नाग 'tintinmj'

@ रोब- Hruska मैं एक नई विधि या क्षेत्र में सिर्फ एक स्थिर आयात विधि या क्षेत्र लपेट नहीं सकता, अगर मैं उन्हें अक्सर उपयोग करने की योजना बना रहा हूं? क्या यह मुझे सांख्यिकीय रूप से आयात नहीं करने देगा? जैसे: double myPI = Math.PI;और फिर क्या मैं myPIइसके बजाय सिर्फ जिक्र कर सकता हूं Math.PI
अब्दुल

@ अब्दुल - हाँ, आप ऐसा कर सकते हैं।
रोब Hruska

14

मैं इस बात से सहमत हूं कि वे पठनीयता के दृष्टिकोण से समस्याग्रस्त हो सकते हैं और उन्हें संयम से इस्तेमाल किया जाना चाहिए। लेकिन एक सामान्य स्थैतिक विधि का उपयोग करते समय वे वास्तव में पठनीयता बढ़ा सकते हैं। उदाहरण के लिए, JUnit परीक्षण वर्ग में, तरीके ऐसे assertEqualsहैं जो स्पष्ट हैं कि वे कहाँ से आते हैं। इसी तरह से तरीकों के लिए java.lang.Math


5
और क्या बहुत बुरा है Math.round (d) बनाम राउंड (d) देखने के बारे में?
स्टीव कू

5
@SteveKuo - एक ही कारण के लिए कि गणितज्ञ सूत्र में हेरफेर करते समय एक-अक्षर चर नामों का उपयोग करते हैं: ऐसे समय होते हैं जब लंबे नाम समग्र कथन की पठनीयता में हस्तक्षेप करते हैं। कई त्रिकोणमितीय कार्यों को शामिल करने वाले सूत्र पर विचार करें। आसानी से समझ में आने वाला गणित फार्मूला sin x cos y + cos x sin y:। में जावा हो जाता है: Math.sin(x) * Math.cos(y) + Math.cos(x) * Math.sin(y)। पढ़ने में भयानक।
ToolmakerSteve

@ कूलमेकरसेव, इसीलिए मैंने usingसी ++ में निर्देशन को बहुत याद किया : वे स्थानीय हो सकते हैं ।
फ्रैंकलिन यू

11

मुझे लगता है कि स्टैटिक इम्पोर्ट वास्तव में उपयोगी है जब निरर्थक वर्ग के नाम को हटाने के लिए उपयोग किया जाता है जैसे कि बर्तनों की कक्षाएं Arraysऔर Assertions

निश्चित रूप से क्यों नहीं, लेकिन रॉस ने अंतिम वाक्य को छोड़ दिया जो इस संदर्भ में उल्लेख करता है कि वह दस्तावेज है

उचित रूप से प्रयुक्त, स्थैतिक आयात आपके प्रोग्राम को अधिक पठनीय बना सकता है, वर्ग नामों की पुनरावृत्ति के बॉयलरप्लेट को हटाकर।

मूल रूप से इस ब्लॉग से कॉपी किया गया: https://medium.com/alphadev- हालांकिts/static-imports-are-great-but-underused- e805ba9b279f

उदाहरण के लिए:

परीक्षणों में जोर

यह सबसे स्पष्ट मामला है जो मुझे लगता है कि हम सभी पर सहमत हैं

Assertions.assertThat(1).isEqualTo(2);

// Use static import instead
assertThat(1).isEqualTo(2);

उत्पल वर्ग और एनम

कोड को पढ़ने में आसान बनाने वाले बर्तनों की कक्षाओं का उपयोग करते समय वर्ग का नाम कई मामलों में हटाया जा सकता है

List<Integer> numbers = Arrays.asList(1, 2, 3);

// asList method name is enough information
List<Integer> numbers = asList(1, 2, 3);

java.time पैकेज में कुछ मामले हैं जहां इसका उपयोग किया जाना चाहिए

// Get next Friday from now, quite annoying to read
LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

// More concise and easier to read
LocalDate.now().with(next(FRIDAY));

उपयोग न करने का उदाहरण

// Ok this is an Optional
Optional.of("hello world");

// I have no idea what this is 
of("hello world");

10

मैं इसका इस्तेमाल कलर के लिए बहुत करता हूं।

static import java.awt.Color.*;

यह बहुत कम संभावना है कि रंगों को कुछ और के साथ भ्रमित किया जाएगा।


1
यह सबसे अच्छा उपयोग मामलों में से एक है जो मैंने देखा है कि पुराने JUnit / Hamcrest / TestNG से अलग है।
केविनरपे

3

मैं जावा के साथ ओपनजीएल का उपयोग करते समय स्थैतिक आयात के उपयोग की सलाह देता हूं , जो कि "यूटिलिटी क्लास से स्थिरांक के भारी उपयोग" श्रेणी में आने वाला एक उपयोग-मामला है।

उस पर विचार करे

import static android.opengl.GLES20.*;

आपको मूल C कोड को पोर्ट करने और कुछ पठनीय लिखने की अनुमति देता है जैसे:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(samplerUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, vtxBuffer);
glVertexAttribPointer(vtxAttrib, 3, GL_FLOAT, false, 0, 0);

इसके बजाय आम व्यापक कुरूपता:

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
GLES20.glUniform1i(samplerUniform, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vtxBuffer);
GLES20.glVertexAttribPointer(vtxAttrib, 3, GLES20.GL_FLOAT, false, 0, 0);

2

स्थैतिक आयात जावा की एकमात्र "नई" विशेषता है जिसका मैंने कभी उपयोग नहीं किया है और कभी भी उपयोग करने का इरादा नहीं है, जो आपके द्वारा बताई गई समस्याओं के कारण है।


धन्यवाद बॉम्बे। खैर, मेरा मानना ​​है कि वे बेहतर समझ रखते हैं कि विस्तार करने और इंटरफ़ेस करने के लिए जिसमें स्थिर फाइनल का एक गुच्छा होता है।
दु: खद परिवर्तनशील

2

C / C ++ से java में गणित भारी कोड पोर्ट करते समय मैं 'import static java.lang.Math। *' का उपयोग करता हूं। गणित के तरीके 1 से 1 नक्शा बनाते हैं और वर्ग नाम योग्यता के बिना पोर्ट किए गए कोड को अलग करना आसान बनाते हैं।


2

उपयोगिता कक्षाओं का उपयोग करते समय मुझे यह बहुत सुविधाजनक लगा।

उदाहरण के लिए, उपयोग करने के बजाय: if(CollectionUtils.isNotEmpty(col))

मैं इसके बजाय कर सकता हूं:

import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
if(isNotEmpty(col))

जब मैं अपने कोड में इस उपयोगिता का कई बार उपयोग करता हूं तो IMO कोड पठनीयता बढ़ाता है।


2

यूनिट परीक्षणों के बारे में बात करना: अधिकांश लोग विभिन्न स्थिर तरीकों के लिए स्थैतिक आयात का उपयोग करते हैं जो मॉकिंग फ्रेमवर्क प्रदान करते हैं, जैसे कि when()या verify()

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

और निश्चित रूप से, जब आप केवल एक का उपयोग कर रहे हैं और इसका उपयोग करना चाहिए, तो assertThat()यह आवश्यक रूप से आवश्यक हैमरेस्ट मैचर्स को सांख्यिकीय रूप से आयात करने के काम आता है, जैसे कि:

import static org.hamcrest.Matchers.*;

1

वे वर्बेज को कम करने के लिए उपयोगी हैं, विशेष रूप से ऐसे मामलों में जहां बहुत सारे आयातित तरीके कहे जा रहे हैं, और स्थानीय और आयातित तरीकों के बीच अंतर स्पष्ट है।

एक उदाहरण: कोड जिसमें java.lang.Math के कई संदर्भ शामिल हैं

एक और: एक XML बिल्डर वर्ग जहां प्रत्येक संदर्भ के लिए classname प्रस्तुत करते हुए बनाया जा रहा संरचना छिपा होगा


1

मुझे लगता है कि गेटटेक्स्ट-स्टाइल में एनएलएस के लिए स्थैतिक आयात साफ हैं।

import static mypackage.TranslatorUtil._;

//...
System.out.println(_("Hello world."));

यह दोनों स्ट्रिंग को एक स्ट्रिंग के रूप में चिह्नित करता है जिसे निकाला जाना है और स्ट्रिंग को इसके अनुवाद के साथ बदलने के लिए एक आसान और साफ तरीका प्रदान करता है।


1

IMO स्टैटिक इम्पोर्ट काफी अच्छा फीचर है। यह बिलकुल सच है कि स्थैतिक आयात पर भारी निर्भरता कोड को अपठनीय और समझने में कठिन बनाता है कि कौन सी स्थैतिक विधि या विशेषता किस वर्ग की है। हालाँकि, मेरे अनुभव में यह एक प्रयोग करने योग्य विशेषता बन जाती है, विशेष रूप से Utilकक्षाओं को डिजाइन करते समय जो कुछ स्थिर तरीके और विशेषताएँ प्रदान करते हैं। जब भी स्थैतिक आयात प्रदान करते हैं तब उत्पन्न होने वाली अस्पष्टता को कोड मानकों को स्थापित करके रोका जा सकता है। एक कंपनी के भीतर मेरे अनुभव में यह दृष्टिकोण स्वीकार्य है और कोड को क्लीनर और समझने में आसान बनाता है। अधिमानतः मैं _चरित्र को सामने स्थिर तरीकों और स्थिर विशेषताओं में सम्मिलित करता हूं (किसी तरह सी से अपनाया गया)। जाहिरा तौर पर यह दृष्टिकोण जावा के नामकरण मानकों का उल्लंघन करता है लेकिन यह कोड को स्पष्टता प्रदान करता है। उदाहरण के लिए, यदि हमारे पास एक एंगलउल्टिल्स वर्ग है:

public class AngleUtils {

    public static final float _ZERO = 0.0f;
    public static final float _PI   = 3.14f;

    public static float _angleDiff(float angle1, float angle2){

    }

    public static float _addAngle(float target, float dest){

    }
}

इस मामले में स्थैतिक आयात स्पष्टता प्रदान करता है और कोड संरचना मुझे अधिक सुरुचिपूर्ण लगती है:

import static AngleUtils.*;

public class TestClass{

    public void testAngles(){

        float initialAngle = _ZERO;
        float angle1, angle2;
        _addAngle(angle1, angle2);
    }
}

कोई व्यक्ति यह बता सकता है कि कौन सी विधि या विशेषता स्थैतिक आयात से आती है और यह उस वर्ग की जानकारी को छिपाती है जो वह है। मैं उन कक्षाओं के लिए स्थैतिक आयात का उपयोग करने का सुझाव नहीं देता जो एक मॉड्यूल का अभिन्न अंग हैं और स्थिर और गैर-स्थिर तरीके प्रदान करते हैं क्योंकि इन मामलों में यह जानना महत्वपूर्ण है कि कौन सी कक्षा निश्चित स्थैतिक कार्यक्षमता प्रदान करती है।


सुझाव के लिए फिर से नामकरण धन्यवाद। बीटीडब्ल्यू, सामने एक अंडरस्कोर पारंपरिक रूप से कुछ वातावरण में निजी तरीकों / क्षेत्रों के नाम के लिए उपयोग किया जाता है। मैं इस तरह के रूप में एक संशोधित सम्मेलन, पर विचार कर रहा हूँ H_एक से आयात के लिए Helperउपयोगिता वर्ग मैं, या C_के लिए Common, या U_के लिए Utility। वैकल्पिक रूप से, मैंने इन व्यापक रूप से उपयोग की जाने वाली कक्षाओं के लिए एक या दो चरित्र वर्ग नामों का उपयोग करने पर विचार किया है, लेकिन चिंतित था कि कभी-कभी स्थानीय नामों के साथ संघर्ष हो सकता है - अपरकेस विधि नामों के साथ कुछ विरासत कोड हैं।
टूलमेकरसेव

-1

आपको उनका उपयोग करने की आवश्यकता है जब:

  • आप switchएनम मूल्यों के साथ एक बयान का उपयोग करना चाहते हैं
  • आप अपने कोड को समझना मुश्किल बना सकते हैं

9
यह सच नहीं है। (1) आप उनमें से एक स्थिर आयात के बिना पूरी तरह से अच्छी तरह से एनम स्थिरांक का उपयोग कर सकते हैं। (2) स्टेटिक आयात, कहते हैं, JUnit Assert वर्ग के तरीके एक घंटी के रूप में स्पष्ट हैं। "assertTrue (...)" केवल "Assert.assertTrue (...)" के रूप में पठनीय है, शायद मोर्सो।
एलन क्रूगर 19

5
यदि आपके पास 500 लाइन क्लास में 5 स्थैतिक आयात हैं, तो यह बताना बहुत कठिन है कि विधियाँ कहाँ से आती हैं।
davetron5000

4
+1 के लिए जब आप अपने कोड को समझना मुश्किल बनाना चाहते हैं :)
दुखी चर

-5

जब मैं कर सकता हूं तो मैं उनका उपयोग करता हूं। अगर मुझे भूल गए तो मुझे याद दिलाने के लिए मेरे पास IntelliJ सेटअप है। मुझे लगता है कि यह पूरी तरह से योग्य पैकेज नाम की तुलना में बहुत साफ दिखता है।


13
आप नियमित आयात के बारे में सोच रहे हैं। स्थैतिक आयात आपको एक वर्ग के सदस्यों के साथ संदर्भित करते हैं, उन्हें एक classname के साथ योग्य किए बिना, जैसे स्थैतिक आयात java.lang.system.out; out.println ( "foo"); // के बजाय System.out.println ("foo");
स्के।

अब यह स्थैतिक आयात की बहुत अच्छी व्याख्या है ... बहुत बुरा मैं +1 टिप्पणी नहीं कर सकता
एल्डेलशेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.