2010-04-06 4 views
1

J'essaie de créer une liste d'articles, différente pour chaque variable i et j. Mon code est:La variable ne peut pas être résolue

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

je reçois une erreur dans la ligne .setItems(items,:

items cannot be resolved 

Je pense que le compilateur pense que le CharSequence[] items ne peut pas être initialisés ou quelque chose ... Comment puis-je faire fonctionner ce programme?

+1

Indice: lorsque le compilateur pense qu'il n'est pas initialisé, il vous dira qu'il n'est pas initialisé. S'il est dit "impossible à résoudre", cela signifie qu'il ne peut trouver la variable dans aucune portée applicable. –

Répondre

3

Le problème est la portée variable.

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

Nous avons ici deux variables locales i qui est hors de portée immédiatement après leur déclarés et initialisés. Si j a besoin de la valeur i, alors i devra être déclaré dans une plus grande portée.

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

(Il convient de mentionner que c'est exactement le genre de scénarios où l'opérateur ternaire excelle, à savoir)

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

Dans votre cas, malheureusement, le raccourci tableau initialiseur ne peut être utilisé pour initialiser lors de la déclaration. C'est:

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

Vous pouvez retirer la déclaration de items en dehors du if et écrire le code verbeux pour chaque cas (voir la réponse de Joachim Sauer), mais un code plus concis consiste à utiliser le tableau-de-tableaux à la place .

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

Cette technique fonctionne bien dans ce cas, mais dans le cas plus général que vous souhaitez utiliser un Map ou quelque chose de similaire.

Note: Il est pas explicite dans le code d'origine, mais cela fonctionne si j peut être soit 0, 1, 2 ou 3. Si vous voulez que la dernière option s'applique lorsque j est une valeur autre que 0, 1, 2, alors vous devez vérifier cela et le régler à 3 avant ce code.

6

Vous avez en réalité 4 variables items dans votre code, chacune avec une portée très limitée (seulement le code-bloc du if respectif). Au lieu de cela

vous voulez créer une variable avec une portée plus grande:

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: Je oublié que le new CharSequence[] est nécessaire ici. Vous pouvez l'ignorer si vous initialisez la variable lors de la déclaration, mais ici vous avez déplacé la déclaration et utilisé une affectation simple pour définir une valeur. Pour une raison quelconque, la syntaxe courte de définition d'un tableau est seulement valide dans une instruction initializaton (c'est-à-dire dans une affectation qui est dans la même instruction que la déclaration).

+1

Cela ne compilera pas, n'est-ce pas? –

+0

@Tom: oui, j'étais occupé à corriger cela maintenant ;-) –

+0

C'est correct maintenant, mais voyez ma réponse pour une solution alternative beaucoup plus concise qui fonctionne bien dans ce cas particulier. – polygenelubricants

0

Vous déclarez uniquement des éléments dans la portée locale. Vous devez déplacer le

final CharSequence[] items 

en dehors des clauses if et de l'instancier dans la clause if.

+0

mais que se passe-t-il si la variable peut avoir des types différents, qui sont définis dans la clause 'if'? –

1

Parce que définir (ainsi que donner une valeur à) items dans un bloc, il est uniquement visible dans ce bloc. Tirez la définition hors du bloc à un endroit visible à la fois les extraits que vous nous avez donnés, et attribuer une valeur dans la construction ifelse.

1

Declare items avant la

if (i == 0) { 

La façon dont vous faites maintenant, items est seulement portée à l'intérieur vous if intérieur s.

+0

ne fonctionne pas pour chaque situation, et si le type de la variable doit être défini dans le 'if'? –

+0

Vous pouvez toujours définir la variable en dehors de l'if, puis à l'intérieur changer/définir la valeur –

2

En Java vous avez portée au niveau du bloc strict, donc par exemple:

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

donc une fois que vous atteignez cette accolade fermante} votre variable d'articles ne soit plus visible. Ceci est différent de JavaScript par exemple lorsque vous avez une portée au niveau de la fonction.

Espérons que cela aide.

+0

ok, mais quelle est la solution?, Comment puis-je obtenir une variable à l'extérieur? De quoi ai-je besoin pour créer? –

+0

Vous devez déclarer la variable dans la portée que vous avez l'intention de l'utiliser. 'int foo = 0; si (bla) {foo = 1; } faire quelque chose avec (foo); ' – greim

Questions connexes