জাভাতে কীভাবে কোনও পদ্ধতি প্যারামিটার হিসাবে পাস করতে হয়


85

জাভাতে, আপনি কীভাবে কোনও প্যারামিটার হিসাবে কোনও প্রকার পাস করতে পারেন (বা ভেরিয়েবল হিসাবে ঘোষণা)?

আমি টাইপের কোনও উদাহরণটি পাস করতে চাই না তবে টাইপটি নিজেই (যেমন। Int, স্ট্রিং ইত্যাদি)।

সি # তে, আমি এটি করতে পারি:

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

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

টাইপের টি উদাহরণ না দিয়ে জাভাতে কোনও উপায় আছে ?
অথবা আমার নিজের ইন্ট কনস্ট্যান্ট বা এনাম ব্যবহার করতে হবে?
নাকি এর চেয়ে ভাল উপায় আছে?

সম্পাদনা: এখানে foo এর প্রয়োজনীয়তা রয়েছে:
টাইপ টি এর উপর ভিত্তি করে, এটি একটি পৃথক শর্ট, এক্সএমএল স্ট্রিং উত্পন্ন করে।
যদি / অন্যটির কোডটি খুব ছোট হবে (এক বা দুটি লাইন) এবং কিছু ব্যক্তিগত শ্রেণীর ভেরিয়েবল ব্যবহার করবে।

java  types 

আপনি প্রাইভেট ভয়েড ফু (ক্লাস সি) এর মতো ক্লাসের ধরণটি পাস করতে পারেন এবং ফু (স্ট্রিং.ক্লাস) এর মতো ব্যবহার করতে পারেন
মাইকেল বাভিন

উত্তর:


109

আপনি একটি পাস করতে পারে Class<T>

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

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

আপডেট : ওওপি উপায় কার্যকরী প্রয়োজনের উপর নির্ভর করে। সেরা বাজি হ'ল ইন্টারফেস সংজ্ঞায়িত করা foo()এবং দুটি কংক্রিট বাস্তবায়ন বাস্তবায়ন করা foo()এবং তারপরে কেবল foo()আপনি যে বাস্তবায়নটি হাতে নিয়ে এসেছেন তা কল করুন। আর একটি উপায় হতে পারে Map<Class<?>, Action>যা আপনি কল করতে পারেন actions.get(cls)। এই সহজে একটি ইন্টারফেস এবং জমাটবদ্ধ বাস্তবায়নের সঙ্গে মিলিত হবে: actions.get(cls).foo()


আমি প্রশ্নের প্রয়োজনীয়তার বিবরণ যুক্ত করব।

আমি আপাতত সহজ সংস্করণটি নিয়ে যাওয়ার সিদ্ধান্ত নিয়েছি যেহেতু প্রশ্নের ধরণগুলি সর্বদা আদিম হবে (int, স্ট্রিং ইত্যাদি)। যাইহোক, আমি স্পষ্টভাবে মনে রাখবেন ওপ উপায়। ধন্যবাদ

Stringজাভাতে কোনও আদিম নয়;)
বালাসসি

@ পাদওয়ান - এখনও চালানোর পক্ষে পর্যাপ্ত নয়। BalusC থেকে মানচিত্র ব্যবহার করা উত্তর যথেষ্ট। আপনি এটি গ্রহণ করা ঠিক আছে।
duffymo

এছাড়াও আপনি Class<?> clsতুলনা ব্যতীত অন্য কিছুতে ব্যবহার করতে পারেন । আপনি লিখতে না cls value = (cls) aCollection.iterator().next();পারার সময় : আপনি cls.cast (aColલેક્.iterator ()। পরবর্তী ()) কল করতে পারেন; বর্গ javadoc
dlamblin

17

আমারও অনুরূপ প্রশ্ন ছিল, তাই আমি নীচে একটি সম্পূর্ণ চালনার যোগ্য উত্তর নিয়ে কাজ করেছি। আমার যা করার দরকার তা হ'ল একটি সম্পর্কহীন শ্রেণীর একটি বস্তুর (ও) ক্লাস (সি) পাশ করা এবং সেই বস্তু (ও) ক্লাসের নতুন বস্তু (সি) আমার কাছে ফেরত দেওয়ার জন্য যখন আমি তাদের জিজ্ঞাসা করি।

এটি কীভাবে করা হয়েছে তা নীচের উদাহরণে দেখায়। একটি ম্যাজিকগান ক্লাস রয়েছে যা আপনি প্রজেক্টাইল ক্লাসের কোনও উপ-টাইপ (পেবল, বুলেট বা নিউক্লিয়ারমিসল) দিয়ে লোড করেন। মজার বিষয় হ'ল আপনি এটিকে প্রজেক্টাইলের সাব টাইপ দিয়ে লোড করেছেন তবে সেই ধরণের প্রকৃত অবজেক্ট নয়। ম্যাজিকগান শুটিং করার সময় আসল অবজেক্ট তৈরি করে।

আউটপুট

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;
}

4
আমি বুঝতে পেরেছি যে আপনি কোনও পদ্ধতিতে কোনও প্রকারটি পাস করার ডেমো চেষ্টা করছেন এবং আমি উদাহরণটি সাধারণত পছন্দ করি তবে এই সাধারণ প্রশ্নটি উত্থাপন করে তবে আপনি কেবল জাজি বন্দুকটি প্রজেক্টিকেলের নতুন উদাহরণ সহ লোড করবেন না কেন তার মতো বিষয়গুলিকে জটিল করার চেয়ে? এই? সতর্কতাগুলি সেগুলি সংশোধন করে দমন করবেন না List<Class<? extends Projectile>> projectiles = new ArrayList<Class<? extends Projectile>>()। প্রজেক্টাইল ক্লাসটি একটি ইন্টারফেস হওয়া উচিত এবং আপনার উদাহরণের জন্য সিরিয়ালটি প্রয়োজনীয় নয়
dlamblin

4
কেবলমাত্র কারণটি আমি সামনে আসতে পেরেছি তা হল ক্লাসের নাম পড়া কার্যকর হতে পারে। পেস্টবিন.com/ ভি 9 ইউপিটিডব্লিউটি তবে আপনি এনাম ব্যবহার করতে পারেন। পেস্টবিন.
com

10

ওহ, তবে এটি কুৎসিত, অ-অবজেক্ট-ওরিয়েন্টেড কোড। যে মুহুর্তে আপনি "যদি / অন্য" এবং "টাইপফ" দেখেন, আপনার পলিমারফিজম চিন্তা করা উচিত। এটি যেতে ভুল উপায়। আমি মনে করি জেনারিকগুলি এখানে আপনার বন্ধু।

আপনি কত প্রকারের সাথে ডিল করার পরিকল্পনা করছেন?

হালনাগাদ:

আপনি যদি কেবল স্ট্রিং এবং ইন্টের কথা বলছেন তবে এখানে এটির একটি উপায় রয়েছে। ইন্টারফেস এক্সএমএল জেনারেটর দিয়ে শুরু করুন ("ফু" দিয়ে যথেষ্ট):

package generics;

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

এবং কংক্রিট বাস্তবায়ন এক্সএমএল জেনারেটর আইএমপিএল:

    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>

আপনার মনে মনে এটি ছিল কিনা তা আমি জানি না।


এই মুহূর্তে শুধুমাত্র ইনট এবং স্ট্রিং। এটি করার ওওপ কী হবে?

4
"যে কোনও সময় আপনি নিজেকে ফর্মের কোড লেখার সন্ধান করতে পারেন" যদি অবজেক্ট টি 1 টাইপ হয়, তবে কিছু করুন, তবে এটি টি 2 টাইপের হয়, তবে অন্য কিছু করুন, "নিজেকে চড় মার"। javapractices.com/topic/TopicAction.do?Id=31
পুল

@ দাওয়াত: লিঙ্কটির জন্য ধন্যবাদ। আমি মনে করি আমি যা বলছি তা বুঝতে পেরেছি তবে এখানে আমার কোনও বস্তুর উদাহরণ নেই। আমি চাই foo একটি ইন্ট বনাম স্ট্রিংয়ের জন্য আলাদা স্ট্রিং তৈরি করতে। এটিকে ওপও করতে আমাকে কি অন্য কোনও বস্তু থেকে প্রাপ্ত দুটি পদার্থের তৈরি করতে হবে? এই ক্ষেত্রে এটি overkill হতে পারে?

আমি আপাতত সহজ সংস্করণটি নিয়ে যাওয়ার সিদ্ধান্ত নিয়েছি যেহেতু প্রশ্নের ধরণগুলি সর্বদা আদিম হবে (int, স্ট্রিং ইত্যাদি)। যাইহোক, আমি স্পষ্টভাবে মনে রাখবেন উওপ উপায়। ধন্যবাদ

4
@ পাদওয়ান, দুঃখিত, আমি বোঝাতে চাইনি - ডফাইমোর মন্তব্য আমাকে সেই উক্তিটির কথা মনে করিয়ে দিয়েছে!
পুল

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