Je n'utilise essentiellement pas final dans mes propres fonctions. Je pense que la raison est simplement "Je l'ai écrit pour que vous puissiez le voir". Par exemple, il a la forme suivante.
public static int f(int x) {
int y = g(x);
int z = h(y);
return z;
}
Quand vous regardez cela, il va de soi que y et z (et x) ne sont pas réaffectés. Et comme la fonction que je définis est généralement de quelques lignes comme celle-ci, je pense que l'ajout de final au moment de la déclaration est redondant, alors j'essaye de ne pas l'ajouter.
Cependant, je pense que c'est normal d'en avoir un autre. Par exemple, si les paramètres IDE sont définis pour ajouter automatiquement la finale, au moins cela n'affectera pas le nombre de types, et je pense qu'il s'habituera bientôt à l'apparence. Bref, dans les cas ci-dessus, nous ne sommes pas si particuliers à ce sujet.
Eh bien, si vous n'utilisez pas du tout final, ce n'est pas le cas, et dans certains cas, il peut être utilisé. Ci-dessous, je présenterai un cas où j'utilise personnellement final.
Puisque la fonction ci-dessus a été définie par moi-même, cela n'a pris que quelques lignes, mais lors de sa modification dans les affaires réelles, il est possible de déclarer des variables dans une fonction très longue (centaines de lignes, mille lignes, etc.). Dans de telles fonctions, il n'est pas rare qu'il y ait des dizaines ou des centaines de lignes entre la déclaration de variable et l'endroit où la variable est utilisée. À ce moment-là, si final n'est pas joint au moment de la déclaration, il est nécessaire de lire toutes les lignes intermédiaires et de saisir la dernière valeur.
numéro de ligne
100 public static int longLongFunc() {
101 String foo = "foo";
~~ Omis ~~
//Vous devez lire les 400 lignes entre les deux pour connaître la valeur de foo à ce stade.
500 String bar = hoge(foo);
・ ・ ・
Sinon, la portée continuera après l'utilisation de la variable, de sorte que la valeur ne peut plus changer dans les lignes en dessous.
//Il peut être réutilisé comme ça(Qu'est-ce que l'initialisation ...)¡
700 foo = null; //Initialisation
701 foo = fuga();
・ ・ ・
Bien sûr, cela peut être une histoire qui peut être évitée par la révision du code, mais dans le monde réel, il n'est pas rare que les entreprises n'aient pas une telle culture.
Les cas ci-dessus peuvent être traités en ajoutant final lors de la déclaration.
numéro de ligne
100 public static int longLongFunc() {
101 final String foo = "foo";
~~ Omis ~~
//La valeur de foo n'a pas changé depuis sa déclaration("foo"Tel quel)Par conséquent, il n'est pas nécessaire de saisir le traitement intermédiaire.
500 String bar = hoge(foo);
~~ Omis ~~
//Ne peut pas être réutilisé dans la ligne ci-dessous car cela entraînera une erreur de compilation
700 foo = null; //Erreur de compilation
・ ・ ・
(Post-scriptum du 19/10/1 / correction) @Kilisame l'a souligné dans les commentaires, et j'ai découvert mon gros malentendu, alors je fais une correction majeure. Les variables locales Java, indépendamment de la présence ou de l'absence de final, provoqueront une erreur de compilation si la valeur initiale n'est pas affectée uniquement par la déclaration, mais dans le cas de la déclaration uniquement, la valeur initiale implicite est affectée comme le champ. Je l'ai mal compris. Merci d'avoir souligné, @Kilisame.
String hoge = "";
if (isFoo) {
hoge = "foo";
} else if (isBar) {
hoge = "bar";
}
Si vous ne voulez tout simplement pas réattribuer, vous pouvez également utiliser l'opérateur conditionnel (opérateur ternaire) pour écrire:
String hoge = isFoo ? "foo" : isBar ? "bar" : "";
Ce n'est pas impossible d'écrire, mais il est certainement difficile de voir si else if est mélangé, pas seulement if-else. Fondamentalement, il vaut mieux éviter l'imbrication d'opérateurs conditionnels. Dans un tel cas, vous pouvez également écrire comme suit.
// 19/10/1 commentaire pour correction(Voir les notes supplémentaires)
// final String hoge; //Déclaration uniquement
String hoge; //Déclaration uniquement
//Remplacez une valeur en fonction de la condition
if (isFoo) {
hoge = "foo";
} else if (isBar) {
hoge = "bar";
} else {
hoge = "";
}
Puisque ~~ final est "une valeur qui ne peut être attribuée qu'une seule fois", le moment de la déclaration et de l'affectation lui-même peut être différent. Au lieu de cela, vous obtiendrez une erreur de compilation si vous ne définissez pas de valeur quelque part avant qu'elle ne soit hors de portée. L'avantage de l'écriture ci-dessus est que vous pouvez empêcher la surveillance des cas où aucune valeur n'est définie. Par exemple, l'exemple suivant entraînera une erreur de compilation. ~~
(Post-scriptum du 19/10/1 / correction) Même s'il n'y a pas de final, une erreur de compilation se produira si la valeur initiale n'est pas affectée uniquement dans la déclaration.
// 19/10/1 commentaire pour correction
// final String hoge;
String hoge;
if (isFoo) {
hoge = "foo";
} else if (isBar) {
String fuga = getFuga();
if (!fuga.isEmpty()) {
hoge = fuga;
} //Si c'est faux, la valeur ne sera pas définie, ce qui entraînera une erreur de compilation.
} else {
hoge = "";
}
Afin de réussir la compilation, il est nécessaire de couvrir tous les cas comme suit.
// 19/10/1 commentaire pour correction
// final String hoge;
String hoge;
if (isFoo) {
hoge = "foo";
} else if (isBar) {
String fuga = getFuga();
if (!fuga.isEmpty()) {
hoge = fuga;
} else {
hoge = "bar";
}
} else {
hoge = "";
}
~~ Pour compléter un peu plus, supprimez la finale de l'exemple ci-dessus qui provoque une erreur de compilation et remplacez-la par la valeur initiale. ~~
(Post-scriptum du 19/10/1 / correction) Puisque final est supprimé, seule la valeur initiale est remplacée.
String hoge = "";
if (isFoo) {
hoge = "foo";
} else if (isBar) {
String fuga = getFuga();
if (!fuga.isEmpty()) {
hoge = fuga;
} //Quand c'est faux, hoge est""tel quel.
}
Dans ce cas, la compilation elle-même passera.
Cependant, cela peut être dû au fait que vous avez oublié d'écrire le cas où fuga.isEmpty ()
est true
(bien sûr, cela peut être comme prévu).
String hoge = "";
if (isFoo) {
hoge = "foo";
} else if (isBar) {
String fuga = getFuga();
if (!fuga.isEmpty()) {
hoge = fuga;
} else {
hoge = "bar"; //Peut-être que j'avais l'intention d'écrire comme ça
}
}
Ce type de bogue est également un bogue courant dans la pratique. Les gens sont des créatures qui font des erreurs. Donc, de cette façon, il est plus sûr et plus sûr d'écrire de telle manière qu'une erreur de compilation se produise si vous faites une erreur, plutôt que d'écrire de telle manière que la compilation passera dans les deux cas d'erreurs et non. ~~ Si vous oubliez d'écrire l'exemple ci-dessus, vous pouvez éviter les bogues inattendus en ajoutant final. ~~
(Post-scriptum du 19/10/1 / correction)
La directive elle-même, "Si vous faites une erreur, vous devriez obtenir une erreur de compilation" ne change pas, mais l'exemple ci-dessus est inapproprié car il ne concerne pas la présence ou l'absence de final.
En ce qui concerne les mérites de l'ajout final dans de tels cas, @Kilisame a souligné, illustré et expliqué dans la section des commentaires, veuillez donc vous y référer.
En plus de l'exemple ci-dessus, il est également bon de créer la fonction suivante et de l'appeler.
//Ring hoge si transformé en fonction= getHoge();Peut être écrit
public static String getHoge() {
if (isFoo) {
return "foo";
}
if (isBar) {
String fuga = getFuga();
if (!fuga.isEmpty()) {
return fuga;
} else {
return "bar";
}
}
return "";
}
J'aimerais que vous réfléchissiez à l'opportunité d'en faire une fonction au cas par cas.
Actuellement, je n'ajoute pas final à toutes les variables locales, mais j'ai l'intention d'écrire avec l'intention que "final puisse être ajouté à toutes les variables locales". Plutôt que d'ajouter ou non final, si vous êtes bien conscient de l'arrière-plan et du but de l'ajout de final, tels que «éviter les bogues inattendus» et «réparer facilement», il ne peut pas tourner dans la mauvaise direction. Je suis en train de penser.
Ou s'il s'agit de développement d'équipe, je pense que la stratégie de forcer le final dans la norme de codage et de n'assurer que la qualité minimale sans que le programmeur s'en rende compte est aussi une fourmi.
Dans cet article, je voulais simplement présenter le cas selon lequel "il est plus pratique d'utiliser final dans de tels cas" au lieu de "utiliser ou non final", afin que vous ou votre équipe décidez quoi faire. J'espère que vous pouvez y réfléchir.
Merci d'avoir lu pour moi jusqu'à la fin. Si vous avez des questions ou des lacunes, veuillez nous contacter dans la section commentaires ou Twitter.
Recommended Posts