जावा में विधि पैरामीटर के रूप में एक प्रकार कैसे पास करें


85

जावा में, आप एक पैरामीटर के रूप में एक प्रकार कैसे पारित कर सकते हैं (या एक चर के रूप में घोषित करें)?

मैं टाइप का उदाहरण नहीं देना चाहता , लेकिन खुद टाइप (जैसे। इंट, स्ट्रिंग, आदि)।

C # में, मैं यह कर सकता हूं:

private void foo(Type t)
{
    if (t == typeof(String)) { ... }
    else if (t == typeof(int)) { ... }
}

private void bar()
{
    foo(typeof(String));
}

क्या जावा में टाइप टी के उदाहरण के बिना एक रास्ता है ?
या मुझे अपने स्वयं के इंट कॉन्स्टेंट या एनम का उपयोग करना होगा?
या कोई बेहतर तरीका है?

संपादित करें: यहाँ foo के लिए आवश्यकता है:
प्रकार t के आधार पर, यह एक अलग शॉर्ट, xml स्ट्रिंग उत्पन्न करता है।
If / else में कोड बहुत छोटा (एक या दो लाइनें) होगा और कुछ निजी वर्ग चर का उपयोग करेगा।

java  types 

आप निजी शून्य foo (कक्षा c) की तरह कक्षा पास कर सकते हैं और foo (String.class) की तरह उपयोग कर सकते हैं
माइकल

जवाबों:


109

आप में पास कर सकते हैं Class<T>

private void foo(Class<?> cls) {
    if (cls == String.class) { ... }
    else if (cls == int.class) { ... }
}

private void bar() {
    foo(String.class);
}

अद्यतन : OOP तरीका कार्यात्मक आवश्यकता पर निर्भर करता है। सर्वश्रेष्ठ शर्त एक इंटरफ़ेस परिभाषित करना foo()और दो ठोस कार्यान्वयन को लागू करना foo()और फिर foo()आपके द्वारा लागू किए गए कार्यान्वयन पर कॉल करना होगा। एक और तरीका हो सकता है Map<Class<?>, Action>जिसे आप कॉल कर सकते हैं actions.get(cls)। यह आसानी से एक अंतरफलक और ठोस कार्यान्वयन के साथ जोड़ा जा सकता है actions.get(cls).foo():।


मैं प्रश्न के लिए आवश्यकता का विवरण जोड़ूंगा।

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

Stringजावा में एक आदिम नहीं है;)
BalusC

@ पोडवान - अभी भी पर्याप्त नहीं है। मैप का उपयोग करके BalusC का उत्तर पर्याप्त है। आप इसे स्वीकार करने के लिए सही हैं।
duffymo

साथ ही आप Class<?> clsतुलना के अलावा किसी और चीज में उपयोग कर सकते हैं । जब आप नहीं लिख सकते हैं: cls value = (cls) aCollection.iterator().next();आप cls.cast (aCollection.iterator ()। Next ()) को कॉल कर सकते हैं; क्लास
जैवाडोक

17

मेरे पास एक समान प्रश्न था, इसलिए मैंने नीचे एक पूरी तरह से जवाब देने योग्य काम किया। मुझे जो करने की आवश्यकता है वह एक असंबंधित वर्ग की एक वस्तु (O) के लिए एक वर्ग (C) पास है और उस वस्तु (O) के वर्ग की नई वस्तुएं (C) मेरे पास वापस आती हैं जब मैंने उनके लिए कहा।

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

उत्पादन

You've annoyed the target!
You've holed the target!
You've obliterated the target!
click
click

कोड

import java.util.ArrayList;
import java.util.List;

public class PassAClass {
    public static void main(String[] args) {
        MagicGun gun = new MagicGun();
        gun.loadWith(Pebble.class);
        gun.loadWith(Bullet.class);
        gun.loadWith(NuclearMissle.class);
        //gun.loadWith(Object.class);   // Won't compile -- Object is not a Projectile
        for(int i=0; i<5; i++){
            try {
                String effect = gun.shoot().effectOnTarget();
                System.out.printf("You've %s the target!\n", effect);
            } catch (GunIsEmptyException e) {
                System.err.printf("click\n");
            }
        }
    }
}

class MagicGun {
    /**
     * projectiles holds a list of classes that extend Projectile. Because of erasure, it
     * can't hold be a List<? extends Projectile> so we need the SuppressWarning. However
     * the only way to add to it is the "loadWith" method which makes it typesafe. 
     */
    private @SuppressWarnings("rawtypes") List<Class> projectiles = new ArrayList<Class>();
    /**
     * Load the MagicGun with a new Projectile class.
     * @param projectileClass The class of the Projectile to create when it's time to shoot.
     */
    public void loadWith(Class<? extends Projectile> projectileClass){
        projectiles.add(projectileClass);
    }
    /**
     * Shoot the MagicGun with the next Projectile. Projectiles are shot First In First Out.
     * @return A newly created Projectile object.
     * @throws GunIsEmptyException
     */
    public Projectile shoot() throws GunIsEmptyException{
        if (projectiles.isEmpty())
            throw new GunIsEmptyException();
        Projectile projectile = null;
        // We know it must be a Projectile, so the SuppressWarnings is OK
        @SuppressWarnings("unchecked") Class<? extends Projectile> projectileClass = projectiles.get(0);
        projectiles.remove(0);
        try{
            // http://www.java2s.com/Code/Java/Language-Basics/ObjectReflectioncreatenewinstance.htm
            projectile = projectileClass.newInstance();
        } catch (InstantiationException e) {
            System.err.println(e);
        } catch (IllegalAccessException e) {
            System.err.println(e);
        }
        return projectile;
    }
}

abstract class Projectile {
    public abstract String effectOnTarget();
}

class Pebble extends Projectile {
    @Override public String effectOnTarget() {
        return "annoyed";
    }
}

class Bullet extends Projectile {
    @Override public String effectOnTarget() {
        return "holed";
    }
}

class NuclearMissle extends Projectile {
    @Override public String effectOnTarget() {
        return "obliterated";
    }
}

class GunIsEmptyException extends Exception {
    private static final long serialVersionUID = 4574971294051632635L;
}

2
मैं समझता हूं कि आप एक प्रकार से किसी विधि को पारित करने के लिए डेमो करने की कोशिश कर रहे हैं, और मुझे आम तौर पर उदाहरण पसंद है, लेकिन यह आसान सवाल यह है कि आप सिर्फ मामलों को जटिल करने के बजाय प्रोजेक्टाइल के नए उदाहरणों के साथ जादू बंदूक को लोड क्यों नहीं करेंगे यह? इसके अलावा चेतावनियों को दबाकर उन्हें ठीक न करें List<Class<? extends Projectile>> projectiles = new ArrayList<Class<? extends Projectile>>()। प्रक्षेप्य वर्ग एक इंटरफ़ेस होना चाहिए, और धारावाहिक आपके उदाहरण के लिए आवश्यक नहीं है,
dlamblin

1
केवल यही कारण हो सकता है कि मैं कक्षा के नाम को पढ़ना उपयोगी हो सकता है। pastebin.com/v9UyPtWT लेकिन फिर, आप एक एनम का उपयोग कर सकते हैं। pastebin.com/Nw939Js1
dlamblin

10

ओह, लेकिन यह बदसूरत, गैर-वस्तु-उन्मुख कोड है। जिस क्षण आप "यदि / और" और "टाइपोफ" देखते हैं, तो आपको बहुरूपता के बारे में सोचना चाहिए। यह जाने का गलत तरीका है। मुझे लगता है कि जेनरिक यहां आपका दोस्त है।

आप कितने प्रकार से निपटने की योजना बनाते हैं?

अपडेट करें:

यदि आप केवल स्ट्रिंग और इंट के बारे में बात कर रहे हैं, तो यहां एक तरीका यह है कि आप इसे कर सकते हैं। इंटरफ़ेस के साथ शुरू करें XmlGenerator ("फू" के साथ पर्याप्त):

package generics;

public interface XmlGenerator<T>
{
   String getXml(T value);
}

और ठोस कार्यान्वयन XmlGeneratorImpl:

    package generics;

public class XmlGeneratorImpl<T> implements XmlGenerator<T>
{
    private Class<T> valueType;
    private static final int DEFAULT_CAPACITY = 1024;

    public static void main(String [] args)
    {
        Integer x = 42;
        String y = "foobar";

        XmlGenerator<Integer> intXmlGenerator = new XmlGeneratorImpl<Integer>(Integer.class);
        XmlGenerator<String> stringXmlGenerator = new XmlGeneratorImpl<String>(String.class);

        System.out.println("integer: " + intXmlGenerator.getXml(x));
        System.out.println("string : " + stringXmlGenerator.getXml(y));
    }

    public XmlGeneratorImpl(Class<T> clazz)
    {
        this.valueType = clazz;
    }

    public String getXml(T value)
    {
        StringBuilder builder = new StringBuilder(DEFAULT_CAPACITY);

        appendTag(builder);
        builder.append(value);
        appendTag(builder, false);

        return builder.toString();
    }

    private void appendTag(StringBuilder builder) { this.appendTag(builder, false); }

    private void appendTag(StringBuilder builder, boolean isClosing)
    {
        String valueTypeName = valueType.getName();
        builder.append("<").append(valueTypeName);
        if (isClosing)
        {
            builder.append("/");
        }
        builder.append(">");
    }
}

यदि मैं इसे चलाता हूं, तो मुझे निम्नलिखित परिणाम मिलते हैं:

integer: <java.lang.Integer>42<java.lang.Integer>
string : <java.lang.String>foobar<java.lang.String>

मुझे नहीं पता कि क्या यह आपके दिमाग में था।


अभी केवल int और string है। ऐसा करने का ऊप तरीका क्या होगा?

4
"कभी भी आप अपने आप को फ़ॉर्म का कोड लिखते हुए पाते हैं" यदि ऑब्जेक्ट टाइप T1 का है, तो कुछ करें, लेकिन यदि यह टाइप T2 का है, तो कुछ और करें, "खुद को थप्पड़ मारें।" javapractices.com/topic/TopicAction.do?Id=31
पूल

@ दावत: लिंक के लिए धन्यवाद। मुझे लगता है कि मैं समझता हूं कि क्या कहा जा रहा है, लेकिन यहां मेरे पास किसी वस्तु का उदाहरण नहीं है। मैं एक बनाम बनाम एक स्ट्रिंग के लिए एक अलग स्ट्रिंग उत्पन्न करने के लिए फू चाहता हूं। क्या मुझे किसी अन्य वस्तु से प्राप्त वस्तुओं के दो उदाहरणों को बनाना होगा ताकि इसे ऊप तरीके से किया जा सके? यह इस मामले के लिए overkill हो सकता है?

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

1
@ IPadawan, माफ करना, मेरा मतलब कृपालु होना नहीं था - duffymo की टिप्पणी ने मुझे यह याद दिलाया कि यह सब है!
पूल

9

आपको पास होना चाहिए Class...

private void foo(Class<?> t){
    if(t == String.class){ ... }
    else if(t == int.class){ ... }
}

private void bar()
{
   foo(String.class);
}

आपको क्लास क्यों पास करनी चाहिए और टाइप नहीं? क्या कोई कारण है कि हस्ताक्षर की method_foo(Type fooableType)तुलना में कम उपयोगी हैं method_foo(Class<?> fooableClass)?
रोबर्टो टामस

5

यदि आप प्रकार पास करना चाहते हैं, तो जावा में समकक्ष होगा

java.lang.Class

यदि आप एक कमजोर टाइप विधि का उपयोग करना चाहते हैं, तो आप बस उपयोग करेंगे

java.lang.Object

और संबंधित ऑपरेटर

instanceof

जैसे

private void foo(Object o) {

  if(o instanceof String) {

  }

}//foo

हालांकि, जावा में आदिम प्रकार हैं, जो कक्षाएं नहीं हैं (यानी आपके उदाहरण से इंट), इसलिए आपको सावधान रहने की आवश्यकता है।

असली सवाल यह है कि आप वास्तव में यहां क्या हासिल करना चाहते हैं, अन्यथा इसका जवाब देना मुश्किल है:

या कोई बेहतर तरीका है?


0

आप java.lang.Class का एक उदाहरण दे सकते हैं जो कि प्रकार का प्रतिनिधित्व करता है, अर्थात

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