जानबूझकर एक कस्टम जावा कंपाइलर चेतावनी संदेश कैसे पैदा करें?


84

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

[javac] com.foo.Hacky.java:192: warning: FIXME temporary hack to work around library bug, remove me when library is fixed!

क्या कोई तरीका है जिससे मैं अपने चयन के संदेश के साथ जानबूझकर संकलक चेतावनी दे सकता हूं? असफल होना, मौजूदा चेतावनी को फेंकने के लिए कोड में जोड़ने के लिए सबसे आसान बात क्या है, शायद आक्रामक लाइन पर स्ट्रिंग में एक संदेश के साथ ताकि यह चेतावनी संदेश में मुद्रित हो जाए?

संपादित करें: पदावनत टैग मेरे लिए कुछ भी नहीं कर रहे हैं:

/**
 * @deprecated "Temporary hack to work around remote server quirks"
 */
@Deprecated
private void doSomeHackyStuff() { ... }

ग्रहण में या सूर्य जावेद 1.6 (चींटी लिपि से चलने) से कोई संकलक या रनटाइम त्रुटियां नहीं हैं, और यह निश्चित रूप से फ़ंक्शन को निष्पादित कर रहा है।


1
FYI करें: @Deprecated केवल संकलक चेतावनी देता है , संकलक या रनटाइम त्रुटि नहीं। कोड निश्चित रूप से चलना चाहिए
BalusC

सीधे javac के साथ चलने का प्रयास करें। मुझे शक है कि चींटी कुछ आउटपुट छिपा रही है। या अधिक जानकारी के लिए नीचे मेरा अद्यतन उत्तर देखें।
पीटर रेकोर

जवाबों:


42

एक तकनीक है कि मैं प्रयोग किया जाता देखा गया है इकाई परीक्षण (आप में इस टाई करने के लिए है करना इकाई परीक्षण, है ना?)। मूल रूप से आप एक इकाई परीक्षण बनाते हैं जो बाहरी संसाधन तय होने के बाद विफल हो जाता है। फिर आप टिप्पणी करते हैं कि यूनिट टेस्ट दूसरों को यह बताने के लिए कि समस्या के हल होने के बाद कैसे अपने हैक करने के लिए।

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


2
मैंने इसके बारे में नो फ्लफ़ जस्ट स्टफ सम्मेलनों में से एक में सुना (यह याद नहीं कर सकता कि प्रस्तुतकर्ता कौन था)। मैंने सोचा कि यह बहुत चालाक था। मैं निश्चित रूप से उन सम्मेलनों की सिफारिश करता हूं, हालांकि।
केविन डे

3
मैं इस दृष्टिकोण का एक उदाहरण देखना चाहता हूं
बजे

उत्तर 11yrs पुराना है, लेकिन मैं इसे भी एक कदम आगे ले जाऊंगा: इकाई परीक्षणों की टिप्पणी करना खतरनाक है। मैं एक यूनिट टेस्ट बनाऊंगा जो अवांछित व्यवहार को एनकैप्सुलेट करता है, इस तरह जब यह अंततः तय हो जाता है, तो विराम टूट जाता है।
17

86

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

  • एक कस्टम एनोटेशन प्रकार लिखें। यह पृष्ठ बताता है कि एनोटेशन कैसे लिखना है।
  • एक एनोटेशन प्रोसेसर लिखें, जो चेतावनी देने के लिए आपके कस्टम एनोटेशन को प्रोसेस करता है। ऐसे एनोटेशन प्रोसेसर को चलाने वाले टूल को APT कहा जाता है। आप इस पृष्ठ पर एक खोज प्राप्त कर सकते हैं । मुझे लगता है कि एपीटी एपीआई में आपको जो चाहिए वह है एनोटेशनप्रोसेसरऑनवायरमेंट, जो आपको चेतावनी का उत्सर्जन करने देगा।
  • जावा 6 से, APT को javac में एकीकृत किया गया है। यही है, आप javac कमांड लाइन में एनोटेशन प्रोसेसर जोड़ सकते हैं। Javac मैन्युअल का यह भाग आपको बताएगा कि आप अपने कस्टम एनोटेशन प्रोसेसर को कैसे कॉल कर सकते हैं।

मुझे नहीं पता कि यह समाधान वास्तव में व्यावहारिक है या नहीं। कुछ समय मिलने पर मैं इसे स्वयं लागू करने का प्रयास करूंगा।

संपादित करें

मैंने अपने समाधान को सफलतापूर्वक लागू किया। और एक बोनस के रूप में, मैंने इसके उपयोग को आसान बनाने के लिए जावा की सेवा प्रदाता सुविधा का उपयोग किया। दरअसल, मेरा समाधान एक जार है जिसमें 2 वर्ग हैं: कस्टम एनोटेशन और एनोटेशन प्रोसेसर। इसका उपयोग करने के लिए, बस अपने प्रोजेक्ट के क्लासपाथ में इस जार को जोड़ें, और जो भी आप चाहते हैं, एनोटेट करें! यह मेरी आईडीई (नेटबीन्स) के अंदर ठीक काम कर रहा है।

एनोटेशन का कोड:

package fr.barjak.hack;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE})
public @interface Hack {

}

प्रोसेसर का कोड:

package fr.barjak.hack_processor;

import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;

@SupportedAnnotationTypes("fr.barjak.hack.Hack")
public class Processor extends AbstractProcessor {

    private ProcessingEnvironment env;

    @Override
    public synchronized void init(ProcessingEnvironment pe) {
        this.env = pe;
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (!roundEnv.processingOver()) {
            for (TypeElement te : annotations) {
                final Set< ? extends Element> elts = roundEnv.getElementsAnnotatedWith(te);
                for (Element elt : elts) {
                    env.getMessager().printMessage(Kind.WARNING,
                            String.format("%s : thou shalt not hack %s", roundEnv.getRootElements(), elt),
                            elt);
                }
            }
        }
        return true;
    }

}

सेवा प्रदाता के रूप में परिणामी जार को सक्षम करने के लिए, फ़ाइल META-INF/services/javax.annotation.processing.Processorको जार में जोड़ें । यह फ़ाइल एक acsii फ़ाइल है जिसमें निम्नलिखित पाठ होना चाहिए:

fr.barjak.hack_processor.Processor

3
+1, महान शोध! यह निश्चित रूप से इसे करने का "सही तरीका" है (यदि एक इकाई परीक्षण व्यावहारिक नहीं है), और इसे नियमित चेतावनियों के ऊपर और बाहर खड़े होने का फायदा है।
यिशैई

1
javac एक चेतावनी का उत्सर्जन करता है, लेकिन ग्रहण (?) में कुछ भी नहीं होता है
fwonce

8
छोटे नोट: फ़ील्ड को ओवरराइड initऔर सेट करने की कोई आवश्यकता नहीं है env- आप इसे तब ProcessingEnvironmentसे प्राप्त कर सकते हैं । this.processingEnvprotected
पॉल बेलोरा

क्या यह चेतावनी संदेश IDE चेतावनियों पर दिखाई देगा?
uylmz

4
ग्रहण में डिफ़ॉल्ट रूप से एनोटेशन प्रोसेसिंग बंद है। इसे चालू करने के लिए, प्रोजेक्ट गुण -> जावा कंपाइलर -> एनोटेशन प्रोसेसिंग -> एनोटेशन प्रोसेसिंग सक्षम करें। फिर उस पृष्ठ के नीचे "फ़ैक्ट्री पाथ" नामक एक पृष्ठ होता है, जहाँ आपको उन जारों को कॉन्फ़िगर करने की आवश्यकता होती है जिनमें वे प्रोसेसर होते हैं जिनका आप उपयोग करना चाहते हैं।
कोन्स्टेंटिन कोमिसार्सिक

14

कुछ त्वरित और इतने गंदे दृष्टिकोण, @SuppressWarningsजानबूझकर गलत Stringतर्क के साथ एनोटेशन का उपयोग करने के लिए हो सकते हैं :

@SuppressWarnings("FIXME: this is a hack and should be fixed.")

यह एक चेतावनी उत्पन्न करेगा क्योंकि इसे संकलक द्वारा दबाने के लिए विशिष्ट चेतावनी के रूप में मान्यता प्राप्त नहीं है:

असमर्थित @SuppressWarnings ("FIXME: यह एक हैक है और इसे ठीक किया जाना चाहिए।"


4
यह फ़ील्ड दृश्यता चेतावनी या एक प्रकार की त्रुटियों को दबाने में काम नहीं करता है।
इगोरगानापल्स्की

2
विडंबना विचलित करने वाली है।
शानदार

12

एक अच्छा हैक एक और योग्य है ... मैं आमतौर पर हैकी विधि में अप्रयुक्त चर को पेश करके वर्णित उद्देश्य के लिए संकलक चेतावनी उत्पन्न करता हूं, इस प्रकार:

/**
 * @deprecated "Temporary hack to work around remote server quirks"
 */
@Deprecated
private void doSomeHackyStuff() {
    int FIXMEtemporaryHackToWorkAroundLibraryBugRemoveMeWhenLibraryIsFixed;
    ...
}

यह अप्रयुक्त चर एक चेतावनी उत्पन्न करेगा जो (आपके कंपाइलर के आधार पर) कुछ इस तरह दिखाई देगा:

चेतावनी: स्थानीय चर FIXMEtemporaryHackToWorkAroundLibraryBugRemoveMeWhenLibraryIsFixed को कभी नहीं पढ़ा जाता है।

यह समाधान कस्टम एनोटेशन के रूप में अच्छा नहीं है, लेकिन इसका यह लाभ है कि इसके लिए कोई अग्रिम तैयारी की आवश्यकता नहीं है (मान लें कि संकलक पहले से ही अप्रयुक्त चर के लिए चेतावनी जारी करने के लिए कॉन्फ़िगर किया गया है)। मेरा सुझाव है कि यह दृष्टिकोण केवल अल्पकालिक हैक के लिए उपयुक्त है। लंबे समय तक रहने वाले हैक्स के लिए, मैं तर्क दूंगा कि एक कस्टम एनोटेशन बनाने का प्रयास उचित होगा।


क्या आप जानते हैं कि अप्रयुक्त चर चेतावनियों को कैसे सक्षम किया जाए? मैं कमांड लाइन से ग्रैडल के साथ एंड्रॉइड के लिए निर्माण कर रहा हूं और मुझे अप्रयुक्त चर के लिए कोई चेतावनी नहीं मिलती है। क्या आप जानते हैं कि इसे कैसे सक्षम किया जा सकता है build.gradle?
एंड्रियास

@Andreas क्षमा करें, मुझे उस वातावरण / टूलचिन के बारे में कुछ नहीं पता है। यदि इस विषय पर पहले से ही कोई एसओ प्रश्न नहीं है, तो आप एक पूछने पर विचार कर सकते हैं।
पहुंचें

10

मैंने एक लाइब्रेरी लिखी है जो एनोटेशन के साथ ऐसा करती है: लाइटवेट जेवाक @Warning एनोटेशन

उपयोग बहुत सरल है:

// some code...

@Warning("This method should be refactored")
public void someCodeWhichYouNeedAtTheMomentButYouWantToRefactorItLater() {
    // bad stuff going on here...
}

और संकलक आपके पाठ के साथ चेतावनी संदेश फेंक देगा


कृपया डिस्क्लेमर जोड़ें कि आप अनुशंसित पुस्तकालय के लेखक हैं।
पॉल बेलोरा

@PaulBellora नहीं जानता कि यह आपकी मदद कैसे करेगा, लेकिन ठीक है
आर्टेम ज़िनातुल्लीन


5

कैसे विधि या वर्ग को @Deprecated के रूप में चिह्नित किया जाए? यहाँ डॉक्स । ध्यान दें कि @Deprecated और @deprecated दोनों है - कैपिटल डी संस्करण एनोटेशन है और लोअरकेस डी javadoc संस्करण है। Javadoc संस्करण आपको एक मनमाना स्ट्रिंग निर्दिष्ट करने की अनुमति देता है जो यह बताता है कि क्या चल रहा है। लेकिन इसे देखते समय एक चेतावनी का उत्सर्जन करने के लिए संकलक की आवश्यकता नहीं होती है (हालांकि कई करते हैं)। एनोटेशन हमेशा एक चेतावनी का कारण होना चाहिए, हालांकि मुझे नहीं लगता कि आप इसमें स्पष्टीकरण जोड़ सकते हैं।

अद्यतन यहाँ कोड है जिसे मैंने अभी-अभी परीक्षण किया है: Sample.java में शामिल हैं:

public class Sample {
    @Deprecated
    public static void foo() {
         System.out.println("I am a hack");
    }
}

SampleCaller.java शामिल हैं:

public class SampleCaller{
     public static void main(String [] args) {
         Sample.foo();
     }
}

जब मैं "javac Sample.java नमूनाCaller.java" चलाता हूं तो मुझे निम्नलिखित आउटपुट मिलते हैं:

Note: SampleCaller.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

मैं सूरज की जावा 1.6 का उपयोग कर रहा हूं। यदि आप केवल एक नोट के बजाय एक अच्छाई की चेतावनी के लिए एक ईमानदार चाहते हैं, तो -Xlint विकल्प का उपयोग करें। हो सकता है कि चींटी के माध्यम से ठीक से फैल जाएगा।


मुझे @Deprecate के साथ कंपाइलर से कोई त्रुटि नहीं मिलती है; उदाहरण कोड के साथ मेरा q संपादित करें।
pimlottc

1
हम्म। आपका उदाहरण केवल पदावनत विधि दिखाता है। आप विधि का उपयोग कहाँ करते हैं? यहीं से चेतावनी दिखाई देगी।
पीटर रेकोर ने

3
रिकॉर्ड के लिए, @Deprecatedकेवल कक्षाओं में काम करता है (इसलिए यह निजी तरीकों के लिए बेकार है)।
npostavs

4

हम एनोटेशन के साथ ऐसा कर सकते हैं!

त्रुटि बढ़ाने के लिए, Messagerसंदेश भेजने के लिए उपयोग करें Diagnostic.Kind.ERROR। संक्षिप्त उदाहरण:

processingEnv.getMessager().printMessage(
    Diagnostic.Kind.ERROR, "Something happened!", element);

यहाँ एक काफी सरल एनोटेशन है जो मैंने इसे लिखने के लिए लिखा था।

यह @Markerएनोटेशन बताता है कि लक्ष्य एक मार्कर इंटरफ़ेस है:

package marker;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Marker {
}

और एनोटेशन प्रोसेसर एक त्रुटि का कारण बनता है यदि यह नहीं है:

package marker;

import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import javax.tools.Diagnostic;
import java.util.Set;

@SupportedAnnotationTypes("marker.Marker")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public final class MarkerProcessor extends AbstractProcessor {

    private void causeError(String message, Element e) {
        processingEnv.getMessager()
            .printMessage(Diagnostic.Kind.ERROR, message, e);
    }

    private void causeError(
            Element subtype, Element supertype, Element method) {
        String message;
        if (subtype == supertype) {
            message = String.format(
                "@Marker target %s declares a method %s",
                subtype, method);
        } else {
            message = String.format(
                "@Marker target %s has a superinterface " +
                "%s which declares a method %s",
                subtype, supertype, method);
        }

        causeError(message, subtype);
    }

    @Override
    public boolean process(
            Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {

        Elements elementUtils = processingEnv.getElementUtils();
        boolean processMarker = annotations.contains(
            elementUtils.getTypeElement(Marker.class.getName()));
        if (!processMarker)
            return false;

        for (Element e : roundEnv.getElementsAnnotatedWith(Marker.class)) {
            ElementKind kind = e.getKind();

            if (kind != ElementKind.INTERFACE) {
                causeError(String.format(
                    "target of @Marker %s is not an interface", e), e);
                continue;
            }

            if (kind == ElementKind.ANNOTATION_TYPE) {
                causeError(String.format(
                    "target of @Marker %s is an annotation", e), e);
                continue;
            }

            ensureNoMethodsDeclared(e, e);
        }

        return true;
    }

    private void ensureNoMethodsDeclared(
            Element subtype, Element supertype) {
        TypeElement type = (TypeElement) supertype;

        for (Element member : type.getEnclosedElements()) {
            if (member.getKind() != ElementKind.METHOD)
                continue;
            if (member.getModifiers().contains(Modifier.STATIC))
                continue;
            causeError(subtype, supertype, member);
        }

        Types typeUtils = processingEnv.getTypeUtils();
        for (TypeMirror face : type.getInterfaces()) {
            ensureNoMethodsDeclared(subtype, typeUtils.asElement(face));
        }
    }
}

उदाहरण के लिए, ये सही उपयोग हैं @Marker:

  • @Marker
    interface Example {}
    
  • @Marker
    interface Example extends Serializable {}
    

लेकिन इन उपयोगों के @Markerकारण संकलक त्रुटि होगी:

  • @Marker
    class Example {}
    
  • @Marker
    interface Example {
        void method();
    }
    

    मार्कर त्रुटि

यहाँ एक ब्लॉग पोस्ट है जो मुझे इस विषय पर शुरू करने में बहुत सहायक लगी:


छोटे नोट: नीचे टिप्पणी करने वाला व्यक्ति जो इंगित कर रहा है , वह यह है कि MarkerProcessorसंदर्भों के कारण Marker.class, उस पर एक संकलन-समय निर्भरता है। मैंने उपरोक्त उदाहरण इस धारणा के साथ लिखा है कि दोनों वर्ग एक ही JAR फ़ाइल (कहते हैं marker.jar) में जाएंगे , लेकिन यह हमेशा संभव नहीं है।

उदाहरण के लिए, मान लें कि निम्न वर्गों के साथ एक आवेदन JAR है:

com.acme.app.Main
com.acme.app.@Ann
com.acme.app.AnnotatedTypeA (uses @Ann)
com.acme.app.AnnotatedTypeB (uses @Ann)

तब प्रोसेसर के लिए @Annएक अलग जार में मौजूद होता है, जिसका उपयोग एप्लिकेशन जार को संकलित करते समय किया जाता है:

com.acme.proc.AnnProcessor (processes @Ann)

उस मामले में, सीधे AnnProcessorप्रकार को संदर्भित करने में सक्षम नहीं होगा @Ann, क्योंकि यह एक परिपत्र JAR निर्भरता पैदा करेगा। यह केवल नाम या / के @Annद्वारा संदर्भित करने में सक्षम होगा ।StringTypeElementTypeMirror


एनोटेशन प्रोसेसर लिखने का यह सबसे अच्छा तरीका नहीं है। आप आमतौर पर एनोटेशन प्रकार Set<? extends TypeElement>पैरामीटर से प्राप्त करते हैं और फिर दिए गए राउंड का उपयोग करने के लिए एनोटेट तत्व प्राप्त करते हैं getElementsAnnotatedWith(TypeElement annotation)। मुझे यह भी समझ नहीं आ रहा है कि आपने printMessageपद्धति को क्यों लपेटा है ।
thePyroEagle

@ ThePyroEagle सुनिश्चित करें कि दो अधिभार के बीच कोडिंग शैली में एक बहुत छोटा अंतर है।
रेडियोडेफ

यह आदर्श है, लेकिन क्या आप प्रोसेसर JAR में केवल एनोटेशन प्रोसेसर नहीं रखना चाहेंगे? पहले बताए गए तरीकों का उपयोग करने से अलगाव के उस स्तर की अनुमति मिलती है क्योंकि आपको क्लासपैथ में संसाधित एनोटेशन की आवश्यकता नहीं है।
thePyroEagle

2

यहां एनोटेशन पर एक ट्यूटोरियल दिखाया गया है और सबसे नीचे यह आपके एनोटेशन को परिभाषित करने का एक उदाहरण देता है। दुर्भाग्य से ट्यूटोरियल के एक त्वरित स्किमिंग ने कहा कि वे केवल javadoc में उपलब्ध हैं ...

कंपाइलर द्वारा उपयोग किए गए एनोटेशन तीन एनोटेशन प्रकार हैं जो भाषा विनिर्देश द्वारा पूर्वनिर्धारित हैं: @Deprecated, @Override, और @SuppressWarnings।

तो ऐसा प्रतीत होता है कि आप वास्तव में कर सकते हैं एक @Deprecated टैग में फेंक दिया गया है कि कंपाइलर प्रिंट के बारे में बताने वाले javadocs में एक कस्टम टैग लगाएगा या प्रिंट करेगा।


कंपाइलर एक चेतावनी का यह कहते हुए भी अनुकरण करेगा कि आप @Deprecated के साथ जिस विधि को चिह्नित करते हैं वह ऐसा है ... यह उपयोगकर्ता को बताएगा कि यह कौन सा है।
मैट फिलिप्स

1

यदि आप IntelliJ का उपयोग कर रहे हैं। आप यहां जा सकते हैं: प्राथमिकताएँ> संपादक> TODO और "\ bhack.b *" या कोई अन्य पैटर्न जोड़ें।

अगर आप कमेंट करते है तो लाइक करे // HACK: temporary fix to work around server issues

फिर TODO टूल विंडो में, यह संपादन करते समय आपके सभी अन्य परिभाषित पैटर्न के साथ अच्छी तरह से दिखाई देगा।


0

आपको संकलन करने के लिए एक उपकरण का उपयोग करना चाहिए, जैसे चींटी मावेन। इसके साथ, आपको संकलन समय पर कुछ कार्यों को परिभाषित करना चाहिए जो आपके FIXME टैग के बारे में कुछ लॉग (जैसे संदेश या चेतावनी) उत्पन्न कर सकते हैं, उदाहरण के लिए।

और यदि आप कुछ त्रुटियां चाहते हैं, तो यह भी संभव है। जब आप अपने कोड में कुछ TODO छोड़ दिया है (क्यों नहीं?)


हैक यह ASAP काम कर पाने के लिए है, मेरे पास अभी बिल्ड सिस्टम को बदलने का समय नहीं है :) लेकिन भविष्य के बारे में सोचने के लिए अच्छा है ...
pimlottc

0

प्रकट होने के लिए कोई भी चेतावनी पाने के लिए, मैंने पाया कि अप्रयुक्त चर और कस्टम @SuppressWarnings ने मेरे लिए काम नहीं किया, लेकिन एक अनावश्यक कलाकार ने किया:

public class Example {
    public void warn() {
        String fixmePlease = (String)"Hello";
    }
}

अब जब मैं संकलन करता हूं:

$ javac -Xlint:all Example.java
ExampleTest.java:12: warning: [cast] redundant cast to String
        String s = (String) "Hello!";
                   ^
1 warning
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.