জাভা স্যুইচ স্টেটমেন্ট: ধ্রুব এক্সপ্রেশন প্রয়োজন, তবে এটি ধ্রুবক


175

সুতরাং, আমি এই ক্লাসে কাজ করছি যেখানে কয়েকটি স্থির ধ্রুবক রয়েছে:

public abstract class Foo {
    ...
    public static final int BAR;
    public static final int BAZ;
    public static final int BAM;
    ...
}

তারপরে, আমি ধ্রুবকের উপর ভিত্তি করে প্রাসঙ্গিক স্ট্রিংয়ের একটি উপায় চাই:

public static String lookup(int constant) {
    switch (constant) {
        case Foo.BAR: return "bar";
        case Foo.BAZ: return "baz";
        case Foo.BAM: return "bam";
        default: return "unknown";
    }
}

যাইহোক, আমি যখন সংকলন করি তখন আমি constant expression required3 টি কেস লেবেলের প্রত্যেকটিতে ত্রুটি পাই ।

আমি বুঝতে পারি যে সংকলকটির একটি স্যুইচ সংকলন করার জন্য সংকলন সময়ে অভিব্যক্তিটি জানা দরকার, তবে কেন Foo.BA_ধ্রুব নয় ?


1
এই ক্ষেত্রে এনাম ব্যবহার না করার কোনও কারণ?
ব্যারোক

1
আমি ভাবিনি জাভার এনাম রয়েছে ums public static final intগুলি সমস্ত জেডিকে দিয়ে ছড়িয়ে ছিটিয়ে রয়েছে, তাই আমি যা করেছি।
অস্টিন হাইড


4
এবং কার্যকর জাভা ( java.sun.com / ডকস / বই / কার্যকর ) পড়ুন, আইটেম 30: ইনট কনস্ট্যান্টের পরিবর্তে এনাম ব্যবহার করুন
সান প্যাট্রিক ফ্লয়েড

টিপস বলার জন্য ধন্যবাদ, আমি এগুলি পরীক্ষা করে দেখব।
অস্টিন হাইড

উত্তর:


150

আমি বুঝতে পারি যে সংকলকটির একটি স্যুইচ সংকলন করার জন্য সংকলন সময়ে এক্সপ্রেশনটি জানা দরকার, তবে কেন Foo.BA_ ধ্রুবক নয়?

ক্ষেত্রগুলির সূচনা হওয়ার পরে কার্যকর হওয়া কোনও কোডের দৃষ্টিকোণ থেকে তারা স্থির থাকলেও , জেএলএস দ্বারা প্রয়োজনীয় অর্থে তারা সংকলনের সময় নয় ; দেখতে §15.28 স্থায়ী প্রকাশ একটি স্পেসিফিকেশন জন্য ধ্রুবক অভিব্যক্তি 1 । এটি §4.12.4 কে চূড়ান্ত ভেরিয়েবলগুলি বোঝায় যা নীচে "ধ্রুবক পরিবর্তনশীল" সংজ্ঞায়িত করে:

আমরা আদিম প্রকারের বা স্ট্রিং প্রকারের একটি পরিবর্তনশীল বলি, এটি চূড়ান্ত এবং একটি সংকলন-সময় ধ্রুবক অভিব্যক্তি (§15.28) একটি ধ্রুবক ভেরিয়েবলের সাথে আরম্ভ হয়। কোনও চলক একটি ধ্রুবক পরিবর্তনশীল কিনা বা শ্রেণীর সূচনা (§12.4.1), বাইনারি সামঞ্জস্যতা (§13.1, §13.4.9) এবং নির্দিষ্ট অ্যাসাইনমেন্ট (assign16) এর সাথে জড়িত থাকতে পারে।

আপনার উদাহরণে, Foo.BA * ভেরিয়েবলগুলির আরম্ভকারী নেই এবং তাই "ধ্রুবক ভেরিয়েবল" হিসাবে যোগ্যতা অর্জন করবেন না। ফিক্স সহজ; Foo.BA * পরিবর্তনশীল ঘোষণাগুলি সংকলন-সময় ধ্রুবক এক্সপ্রেশনর ইনিশিয়ালাইজারগুলি রাখতে পরিবর্তন করুন।

অন্যান্য উদাহরণগুলিতে (যেখানে ইনিশিয়ালাররা ইতিমধ্যে সংকলন-সময় ধ্রুবক এক্সপ্রেশন থাকে) ভেরিয়েবলটি finalযা প্রয়োজন তা হতে পারে তা ঘোষণা করে ।

স্থির enumচেয়ে বরং আপনার কোডটি ব্যবহার করতে আপনি পরিবর্তন করতে পারেন int, তবে এটি আরও কয়েকবার বিভিন্ন বিধিনিষেধ নিয়ে আসে:


1 - ধ্রুবক অভিব্যক্তি বিধিনিষেধগুলি নিম্নলিখিত হিসাবে সংক্ষিপ্ত করা যেতে পারে। স্থায়ী এক্সপ্রেশন ক) আদিম ধরনের ব্যবহার করতে পারেন এবং Stringশুধুমাত্র খ) প্রাইমারিতে যে লিটারেল (পৃথক্ থেকে এসেছ অনুমতি null) এবং ধ্রুব ভেরিয়েবল শুধুমাত্র গ) অনুমতি ধ্রুব এক্সপ্রেশন সম্ভবত subexpressions যেমন parenthesised ঘ) নিয়োগ অপারেটার ছাড়া অপারেটার অনুমতি ++, --বা instanceof, এবং e) প্রকারভেদগুলিকে আদিম ধরণের বা Stringকেবলমাত্র মঞ্জুরি দিন ।

মনে রাখবেন যে এটিতে কোনও পদ্ধতি বা ল্যাম্বডা কল new,, .class.lengthবা অ্যারে সাবস্ক্রিপশন। তবুও, অ্যারের মান, enumমান, আদিম মোড়ক প্রকারের মান, বক্সিং এবং আনবক্সিং এর কোনও ব্যবহারই ক এর কারণে বাদ দেওয়া হয়)।


79

আপনি কনস্ট্যান্ট এক্সপ্রেশনটি প্রয়োজনীয় কারণ আপনি আপনার ধ্রুবকগুলি থেকে মানগুলি ছেড়ে গেছেন। চেষ্টা করুন:

public abstract class Foo {
    ...
    public static final int BAR=0;
    public static final int BAZ=1;
    public static final int BAM=2;
    ...
}

48

আমি এই ত্রুটিটি Android এ পেয়েছি, এবং আমার সমাধানটি কেবল ব্যবহারের জন্য ছিল:

public static final int TAKE_PICTURE = 1;

পরিবর্তে

public static int TAKE_PICTURE = 1;

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

4
আমি জানি এটি একটি ভিন্ন সমস্যা, তবে যেহেতু আমি এখানে আমার সাথে এসেছি এটি একই পরিস্থিতিতে অন্য কাউকে সাহায্য করতে পারে।
টিও ইনকে

বোঝায় যে তাদের চূড়ান্ত হতে হবে কারণ জিনিসগুলি ভুল হতে পারে যদি এই মানগুলি রানটাইম পরিবর্তন করতে পারে।
স্লট

31

কারণ এগুলি সময় সংকীর্ণ নয়। নিম্নলিখিত বৈধ কোড বিবেচনা করুন:

public static final int BAR = new Random().nextInt();

আপনি কেবল BARরানটাইমের মান জানতে পারবেন ।


1
মজাদার. চান public static final int BAR = new Random().nextInt()কাজ করে?
থিলো

4
থিলোর বক্তব্য সংকলন করে তবে সুইচ স্টেটমেন্টটি ধ্রুবক অভিব্যক্তির প্রয়োজনীয়তার অভিযোগ করে । তদ্ব্যতীত, পরপর দু'জন new Random().nextInt()কি একই মান ফিরে আসতে পারে না ?
টনি এনিস

2
@ টনি: কোনটি ভাল জিনিস। এটি সংকলন করে না কারণ এটি একটি সংকলন-সময় ধ্রুবক দিয়ে আরম্ভ করা হয়নি। স্টিফেনের গৃহীত উত্তর দেখুন। যদি এটি সংকলন করে, একটি এলোমেলো পূর্ণসংখ্যার ক্লাসে হার্ড-কোডড হবে, বেশ অনাকাঙ্ক্ষিত ফলাফল সহ।
Thilo

আমি অবাক হয়েছি যে স্যুইচটির ধ্রুবকটি প্রত্যাখ্যান করা হয়েছে, এবং 'ধ্রুবক' নিজেও তা নয়। আমি কখনও ভাবিনি যে এটি এইভাবেই হবে। অবশ্যই, আমি মনে করি এটি সত্যই ধ্রুব নয়।
টনি এনিস

@ টনিএন্নিস - এটি সত্যিকারের ধ্রুবক দ্বারা আপনি কী বোঝাতে চান তার উপর নির্ভর করে। এটি সত্যিকার অর্থেই স্থির যে প্রোগ্রামটি কার্যকর করার সময় এটি পরিবর্তিত হবে না (একধরনের দু'বাগল)। তবে সকল ফাঁসি কার্যকর করার ক্ষেত্রে এটি এক নয়।
স্টিফেন সি

17

আপনি এই উদাহরণে একটি এনাম ব্যবহার করতে পারেন:

public class MainClass {
enum Choice { Choice1, Choice2, Choice3 }
public static void main(String[] args) {
Choice ch = Choice.Choice1;

switch(ch) {
  case Choice1:
    System.out.println("Choice1 selected");
    break;
 case Choice2:
   System.out.println("Choice2 selected");
   break;
 case Choice3:
   System.out.println("Choice3 selected");
   break;
    }
  }
}

উত্স: এনামের সাথে বিবৃতি স্যুইচ করুন


হাই, আমি এখনও এনামটি এইভাবে ব্যবহার করতে সমস্যা করছি: <br/> enum Codes { CODE_A(1), CODE_B(2); private mCode; Codes(int i) { mCode = i; } public int code() { return mCode; } }<br/> আমি যখন সুইচটিতে এনাম ব্যবহার করার চেষ্টা করি তখন আমিও ত্রুটি পাই ... <br/> switch(field) { case Codes.CODE_A.code() : // do stuffs.. ; } <br/> সমস্যার সমাধান সম্ভব?
শাওলিন

1
@ স্টিগা - আপনি কেবল এনাম উদাহরণগুলি নিজেরাই স্যুইচ করতে পারেন। এনাম উদাহরণগুলিতে কোনও পদ্ধতিতে কল করে কিছুটা মূল্য দেওয়া হয়নি।
স্টিফেন সি

3

যুগে যুগে এটির উত্তর দেওয়া হয়েছিল এবং সম্ভবত প্রাসঙ্গিক নয়, তবে কেবল ক্ষেত্রে। যখন আমি এই সমস্যার মুখোমুখি হয়েছিলাম তখন আমি কেবল ifপরিবর্তে একটি বিবৃতি ব্যবহার করেছি switch, এটি ত্রুটিটি সমাধান করেছে। এটি অবশ্যই একটি কর্মচঞ্চল এবং সম্ভবত "সঠিক" সমাধান নয়, তবে আমার ক্ষেত্রে এটি যথেষ্ট ছিল।


4
এটি কার্যতালিকা নয় এবং প্রশ্নের উত্তর নয়
জে ডঃ

আমি কেন এখানে ভোট নামাচ্ছি? এটি একটি বৈধ কাজ
সমীর মুরাদ

2
সম্ভবত এটি আইএফ-এর বক্তব্য যা আমরা বিশেষভাবে একটি স্যুইচ দিয়ে এড়াতে চাইছি
ডিন ওয়াইল্ড

1
আমি নীচে ভোট দিয়েছি কারণ এখানে প্রশ্নটি "কীভাবে" সমস্যা সমাধানের নয়, তবে "কেন" সমস্যা দেখা দিয়েছে। আমি মনে করি আপনার উত্তরটি প্রসঙ্গের বাইরে। এছাড়াও আপনি যদি নিখুঁতবাদী হন তবে আপনার বুঝতে হবে যে switchসাধারণত দীর্ঘের চেয়ে দ্রুত হয় if-else, কারণ switchকেবল একবার শর্তটি পরীক্ষা করে দেখুন , যখন আপনার সাথে if-elseসঠিক অবস্থার সন্ধানের আগে সমস্ত শর্ত পরীক্ষা করতে হবে।
খ্রিস্টান লিম

0

কখনও কখনও স্যুইচ পরিবর্তনশীল উদাহরণস্বরূপ ত্রুটি করতে পারে:

switch(view.getTag()) {//which is an Object type

   case 0://will give compiler error that says Constant expression required

   //...
}

সমাধানের জন্য আপনাকে ভেরিয়েবলটি ইনট (এই ক্ষেত্রে) করা উচিত। তাই:

switch((int)view.getTag()) {//will be int

   case 0: //No Error

   //...
}

0

এই জাতীয় কিছু করার সময় অ্যান্ড্রয়েডে এই ত্রুটিটি পেয়েছেন:

 roleSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            switch (parent.getItemAtPosition(position)) {
                case ADMIN_CONSTANT: //Threw the error

            }

স্থির ঘোষণা করেও:

public static final String ADMIN_CONSTANT= "Admin";

আমি আমার কোডটি এতে পরিবর্তন করে সমস্যার সমাধান করেছি:

roleSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            String selectedItem = String.valueOf(parent.getItemAtPosition(position));
            switch (selectedItem) {
                case ADMIN_CONSTANT:

            }

0

আমার ক্ষেত্রে, আমি এই ব্যতিক্রম পাচ্ছিলাম কারণ

switch (tipoWebServ) {
                            case VariablesKmDialog.OBTENER_KM:
                                resultObtenerKm(result);
                                break;
                            case var.MODIFICAR_KM:
                                resultModificarKm(result);
                                break;
                        }

দ্বিতীয় ক্ষেত্রে আমি উদাহরণ থেকে ধ্রুবক কল ছিল var.MODIFICAR_KM:কিন্তু আমার VariablesKmDialog.OBTENER_KMসরাসরি ক্লাস থেকে ব্যবহার করা উচিত ।


0

আপনি যদি এটি একটি স্যুইচ ক্ষেত্রে ব্যবহার করছেন তবে আপনার স্যুইচটিতে এই মানটি প্লাগ করার আগেই আপনাকে এনামের ধরণটি পেতে হবে। এই ক্ষেত্রে :

SomeEnum someEnum = SomeEnum.values ​​() [1];

switch (someEnum) {
            case GRAPES:
            case BANANA: ...

এবং এনাম এর মতো:

public enum SomeEnum {

    GRAPES("Grapes", 0),
    BANANA("Banana", 1),

    private String typeName;
    private int typeId;

    SomeEnum(String typeName, int typeId){
        this.typeName = typeName;
        this.typeId = typeId;
    }
}

0

কোডের নীচে স্ব-বর্ণনামূলক, আমরা একটি সুইচ কেস সহ একটি এনাম ব্যবহার করতে পারি:

/**
 *
 */
enum ClassNames {
    STRING(String.class, String.class.getSimpleName()),
    BOOLEAN(Boolean.class, Boolean.class.getSimpleName()),
    INTEGER(Integer.class, Integer.class.getSimpleName()),
    LONG(Long.class, Long.class.getSimpleName());
    private Class typeName;
    private String simpleName;
    ClassNames(Class typeName, String simpleName){
        this.typeName = typeName;
        this.simpleName = simpleName;
    }
}

এনাম থেকে শ্রেণিক মানের উপর ভিত্তি করে ম্যাপ করা যায়:

 switch (ClassNames.valueOf(clazz.getSimpleName())) {
        case STRING:
            String castValue = (String) keyValue;
            break;
        case BOOLEAN:
            break;
        case Integer:
            break;
        case LONG:
            break;
        default:
            isValid = false;

    }

আশা করি এটা সাহায্য করবে :)


0

আমি নিম্নলিখিত উপায় ব্যবহার করার পরামর্শ দিচ্ছি:

public enum Animal {
    DOG("dog"), TIGER("tiger"), LION("lion");
    private final String name;

    @Override
    public String toString() {
        return this.name;
    }
}


public class DemoSwitchUsage {

     private String getAnimal(String name) {
         Animal animalName = Animal.valueOf(name);
         switch(animalName) {
         case DOG:
             // write the code required.
             break;
         case LION:
             // Write the code required.
             break;
         default:
             break;
         }
     }
}

আমি মনে করি private Animal(String name) { this.name = name; }
এনামের

-1

আমি আপনাকে enums ব্যবহার করার পরামর্শ দিচ্ছি :)

এটা দেখ:

public enum Foo 
{
    BAR("bar"),
    BAZ("baz"),
    BAM("bam");

    private final String description;

    private Foo(String description)
    {
        this.description = description;
    }

    public String getDescription()
    {
        return description;
    }
}

তারপরে আপনি এটি ব্যবহার করতে পারেন:

System.out.println(Foo.BAR.getDescription());

@ জাজানফান আপনি কোন কোডটি জেডিকে চালু করছেন?
এভারটন

আমি জেডিকে 1.7.0_74 ব্যবহার করেছি ইন্টেলিজ-আইডিইএ 14
জাঙ্গোফান

1
আমি এভারটন অ্যাগনার প্রস্তাবিত একই ক্লাসটি ব্যবহার করছি তবে এটির ধ্রুবক প্রকাশ প্রয়োজন showing
অমিত কুমার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.