-->

Variable cannot be resolved

2019-01-02 22:01发布

问题:

I am trying to create an item list, diffrent for each i and j variable. My code is:

if (i == 0) { 
            if (j == 0) { 
                final CharSequence[] items = {"4:45", "5:00"}
            } else if (j == 1) { 
                final CharSequence[] items = {"4:43", "4:58"}
            } else if (j == 2) { 
                final CharSequence[] items = {"4:41", "4:56"}
            } else { 
                final CharSequence[] items = {"4:38", "4:53"}
}

...

new AlertDialog.Builder(this)
               .setTitle("Hours")
               .setItems(items,
                new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialoginterface, int i) {
                      // getStation(i);
                   }
                })
               .show();
       }

I get an error in the line .setItems(items,:

items cannot be resolved

I think that the compiler thinks that the CharSequence[] items may not be initialised or something... How can I make this programme run?

回答1:

The problem is variable scoping.

if (someCondition) {
   final int i = 666;
} else {
   final int i = 42;
}
int j = i + 1; // compile-time error

Here we have two local variables i who goes out of scope immediately after they're declared and initialized. If j needs the value of i, then i would have to be declared in a larger scope.

final int i;
if (someCondition) {
   i = 666;
} else {
   i = 42;
}
int j = i + 1; // compiles fine!

(It should be mentioned that this is exactly the kind of scenarios where the ternary operator excels, i.e.)

final int i = (someCondition) ? 666 : 42;

In your specific case, unfortunately the array initializer shorthand can only be used to initialize upon declaration. That is:

int[] arr1 = { 1, 2, 3 }; // compiles fine!
int[] arr2;
arr2 = { 4, 5, 6 }; // doesn't compile!

You can pull out the declaration of items outside the if and write the verbose code for each case (see Joachim Sauer's answer), but a more concise code is to use array-of-arrays instead.

final CharSequence[][] allItems = {
   { "4:45", "5:00" },
   { "4:43", "4:58" },
   { "4:41", "4:56" },
   { "4:38", "4:53" }
};
final CharSequence[] items = allItems[j];

This technique works well in this case, but in the more general case you want to use a Map or something similar.

Note: It's not explicit in the original code, but this works if j can either be 0, 1, 2, or 3. If you want the last option to apply when j is any value other than 0, 1, 2, then you have to check for that and set it to 3 before this code.



回答2:

You actually have 4 items variables in your code, each one with a very limited scope (only the code-block of the respective if).

Instead you'll want to create one variable with a bigger scope:

if (i == 0) { 
            final CharSequence[] items;
            if (j == 0) { 
                items = new CharSequence[] {"4:45", "5:00"};
            } else if (j == 1) { 
                items = new CharSequence[] {"4:43", "4:58"};
            } else if (j == 2) { 
                items = new CharSequence[] {"4:41", "4:56"};
            } else { 
                items = new CharSequence[] {"4:38", "4:53"};
            }
            // you can use items here
}

Edit: I forgot that the new CharSequence[] is necessary here. You can leave it out if you initialize the variable during declaration, but here you moved the declaration out and use a simple assignment to set a value. For some reason the short syntax of defining an array is only valid in an initializaton statement (i.e. in an assignment that is in the same statement as the declaration).



回答3:

In Java you have strict block-level scope, so for example:

if (blah) { int foo = 1; }
// foo is no longer visible here

So once you reach that closing curly brace } your items variable is no longer visible. This is different from JavaScript for example where you have function-level scope.

Hope this helps.



回答4:

Because you define (as well as give a value to) items within a block, it is only visible within that block. Pull the definition out of the block to somewhere visible to both the snippets you have given us, and just assign a value within the if else construct.



回答5:

Declare items before the

if (i == 0) {

The way you are doing it now, items is only in scope inside you inner ifs.



回答6:

You are only declaring items in local scope. You need to move the

final CharSequence[] items

outside the if clauses and the instantiate it inside the if clause.



标签: