[{"data":1,"prerenderedAt":940},["ShallowReactive",2],{"page-\u002Fkotlin\u002Fsecurite-du-null":3,"pieces-kotlin":897,"autour-\u002Fkotlin\u002Fsecurite-du-null":922,"prerequis-\u002Fkotlin\u002Fsecurite-du-null":927,"plan-kotlin":929},{"id":4,"title":5,"body":6,"description":870,"extension":871,"ligne":77,"meta":872,"motsCles":873,"navigation":120,"niveau":876,"path":877,"prerequis":878,"ressources":880,"seo":889,"sources":890,"stem":895,"__hash__":896},"docs\u002Fkotlin\u002F03.securite-du-null.md","La sécurité du null",{"type":7,"value":8,"toc":857},"minimark",[9,14,48,52,59,65,68,72,156,165,181,185,230,246,257,260,277,285,289,331,343,353,386,395,399,402,459,479,483,530,546,550,617,626,630,668,680,705,709,801,805,853],[10,11,13],"h2",{"id":12},"ce-que-tu-vas-apprendre","Ce que tu vas apprendre",[15,16,17,26,41],"ul",{},[18,19,20,21,25],"li",{},"Pourquoi ",[22,23,24],"code",{},"null"," est dangereux et comment Kotlin t'en protège.",[18,27,28,29,32,33,36,37,40],{},"Utiliser ",[22,30,31],{},"?",", ",[22,34,35],{},"?."," et ",[22,38,39],{},"?:"," pour gérer l'absence de valeur.",[18,42,43,44,47],{},"Savoir pourquoi éviter ",[22,45,46],{},"!!",".",[10,49,51],{"id":50},"le-problème-de-null","Le problème de null",[53,54,55,58],"p",{},[56,57,24],"strong",{}," signifie « aucune valeur ». Une recette peut ne pas avoir de photo, un ingrédient peut ne pas avoir de note.",[53,60,61,62,47],{},"Si ton code utilise une valeur absente comme si elle existait, le programme plante. Dans de nombreux langages, cela donne l'erreur ",[22,63,64],{},"NullPointerException",[53,66,67],{},"Kotlin traite ce problème dès la compilation : il te force à dire si une valeur peut être absente.",[10,69,71],{"id":70},"types-nullables","Types nullables",[73,74,79],"pre",{"className":75,"code":76,"language":77,"meta":78,"style":78},"language-kotlin shiki shiki-themes github-light-default github-dark-default github-dark-default","var titre: String = \"Tarte\"\n\u002F\u002F titre = null          \u002F\u002F erreur de compilation\n\nvar photo: String? = \"tarte.jpg\"\nphoto = null             \u002F\u002F accepté\n","kotlin","",[22,80,81,105,115,122,141],{"__ignoreMap":78},[82,83,86,90,94,98,101],"span",{"class":84,"line":85},"line",1,[82,87,89],{"class":88},"sOnC1","var",[82,91,93],{"class":92},"scfrF"," titre: ",[82,95,97],{"class":96},"sIXEE","String",[82,99,100],{"class":88}," =",[82,102,104],{"class":103},"shWOn"," \"Tarte\"\n",[82,106,108,112],{"class":84,"line":107},2,[82,109,111],{"class":110},"sd6ml","\u002F\u002F titre = null",[82,113,114],{"class":110},"          \u002F\u002F erreur de compilation\n",[82,116,118],{"class":84,"line":117},3,[82,119,121],{"emptyLinePlaceholder":120},true,"\n",[82,123,125,127,130,132,135,138],{"class":84,"line":124},4,[82,126,89],{"class":88},[82,128,129],{"class":92}," photo: ",[82,131,97],{"class":96},[82,133,134],{"class":92},"? ",[82,136,137],{"class":88},"=",[82,139,140],{"class":103}," \"tarte.jpg\"\n",[82,142,144,147,149,153],{"class":84,"line":143},5,[82,145,146],{"class":92},"photo ",[82,148,137],{"class":88},[82,150,152],{"class":151},"s5iOY"," null",[82,154,155],{"class":110},"             \u002F\u002F accepté\n",[53,157,158,159,161,162,164],{},"Un type normal, comme ",[22,160,97],{},", ne peut jamais contenir ",[22,163,24],{},". Le compilateur refuse l'affectation.",[53,166,167,168,171,172,174,175,178,179,47],{},"Un ",[56,169,170],{},"type nullable"," s'écrit avec un ",[22,173,31],{}," après le nom du type : ",[22,176,177],{},"String?",". Il accepte une chaîne ou ",[22,180,24],{},[10,182,184],{"id":183},"le-safe-call","Le safe call ?.",[73,186,188],{"className":75,"code":187,"language":77,"meta":78,"style":78},"val photo: String? = null\nval longueur = photo?.length\nprintln(longueur)   \u002F\u002F null\n",[22,189,190,206,218],{"__ignoreMap":78},[82,191,192,195,197,199,201,203],{"class":84,"line":85},[82,193,194],{"class":88},"val",[82,196,129],{"class":92},[82,198,97],{"class":96},[82,200,134],{"class":92},[82,202,137],{"class":88},[82,204,205],{"class":151}," null\n",[82,207,208,210,213,215],{"class":84,"line":107},[82,209,194],{"class":88},[82,211,212],{"class":92}," longueur ",[82,214,137],{"class":88},[82,216,217],{"class":92}," photo?.length\n",[82,219,220,224,227],{"class":84,"line":117},[82,221,223],{"class":222},"syCW7","println",[82,225,226],{"class":92},"(longueur)   ",[82,228,229],{"class":110},"\u002F\u002F null\n",[53,231,232,233,236,237,239,240,242,243,245],{},"Le ",[56,234,235],{},"safe call"," ",[22,238,35],{}," appelle une propriété ou une fonction seulement si la valeur n'est pas ",[22,241,24],{},". Sinon, toute l'expression vaut ",[22,244,24],{},", sans plantage.",[53,247,248,249,252,253,256],{},"Le type de ",[22,250,251],{},"longueur"," est ici ",[22,254,255],{},"Int?",", puisque le résultat peut être absent.",[53,258,259],{},"On peut chaîner plusieurs appels :",[73,261,263],{"className":75,"code":262,"language":77,"meta":78,"style":78},"val pays = recette.auteur?.adresse?.pays\n",[22,264,265],{"__ignoreMap":78},[82,266,267,269,272,274],{"class":84,"line":85},[82,268,194],{"class":88},[82,270,271],{"class":92}," pays ",[82,273,137],{"class":88},[82,275,276],{"class":92}," recette.auteur?.adresse?.pays\n",[53,278,279,280,282,283,47],{},"Dès qu'un maillon vaut ",[22,281,24],{},", le résultat entier vaut ",[22,284,24],{},[10,286,288],{"id":287},"lopérateur-elvis","L'opérateur Elvis ?:",[73,290,292],{"className":75,"code":291,"language":77,"meta":78,"style":78},"val photo: String? = null\nval longueur = photo?.length ?: 0\nprintln(longueur)   \u002F\u002F 0\n",[22,293,294,308,322],{"__ignoreMap":78},[82,295,296,298,300,302,304,306],{"class":84,"line":85},[82,297,194],{"class":88},[82,299,129],{"class":92},[82,301,97],{"class":96},[82,303,134],{"class":92},[82,305,137],{"class":88},[82,307,205],{"class":151},[82,309,310,312,314,316,319],{"class":84,"line":107},[82,311,194],{"class":88},[82,313,212],{"class":92},[82,315,137],{"class":88},[82,317,318],{"class":92}," photo?.length ?: ",[82,320,321],{"class":151},"0\n",[82,323,324,326,328],{"class":84,"line":117},[82,325,223],{"class":222},[82,327,226],{"class":92},[82,329,330],{"class":110},"\u002F\u002F 0\n",[53,332,333,334,236,337,339,340,342],{},"L'",[56,335,336],{},"opérateur Elvis",[22,338,39],{}," donne une valeur de secours. Si la partie gauche n'est pas ",[22,341,24],{},", il la renvoie. Sinon, il renvoie la partie droite.",[53,344,345,346,349,350,352],{},"Le résultat est maintenant un ",[22,347,348],{},"Int"," simple, plus un ",[22,351,255],{},". Tu peux t'en servir sans autre précaution.",[73,354,356],{"className":75,"code":355,"language":77,"meta":78,"style":78},"fun noteMoyenne(id: Int): Int = recetteParId(id)?.note ?: 0\n",[22,357,358],{"__ignoreMap":78},[82,359,360,363,366,369,371,374,376,378,381,384],{"class":84,"line":85},[82,361,362],{"class":88},"fun",[82,364,365],{"class":222}," noteMoyenne",[82,367,368],{"class":92},"(id: ",[82,370,348],{"class":96},[82,372,373],{"class":92},"): ",[82,375,348],{"class":96},[82,377,100],{"class":88},[82,379,380],{"class":222}," recetteParId",[82,382,383],{"class":92},"(id)?.note ?: ",[82,385,321],{"class":151},[53,387,388,389,391,392,394],{},"Ce mélange de ",[22,390,35],{}," et de ",[22,393,39],{}," est le réflexe à prendre.",[10,396,398],{"id":397},"tester-avec-if","Tester avec if",[53,400,401],{},"Le compilateur suit tes vérifications.",[73,403,405],{"className":75,"code":404,"language":77,"meta":78,"style":78},"fun afficher(photo: String?) {\n    if (photo != null) {\n        println(photo.length)   \u002F\u002F photo est traité comme String\n    }\n}\n",[22,406,407,422,438,449,454],{"__ignoreMap":78},[82,408,409,411,414,417,419],{"class":84,"line":85},[82,410,362],{"class":88},[82,412,413],{"class":222}," afficher",[82,415,416],{"class":92},"(photo: ",[82,418,97],{"class":96},[82,420,421],{"class":92},"?) {\n",[82,423,424,427,430,433,435],{"class":84,"line":107},[82,425,426],{"class":88},"    if",[82,428,429],{"class":92}," (photo ",[82,431,432],{"class":88},"!=",[82,434,152],{"class":151},[82,436,437],{"class":92},") {\n",[82,439,440,443,446],{"class":84,"line":117},[82,441,442],{"class":222},"        println",[82,444,445],{"class":92},"(photo.length)   ",[82,447,448],{"class":110},"\u002F\u002F photo est traité comme String\n",[82,450,451],{"class":84,"line":124},[82,452,453],{"class":92},"    }\n",[82,455,456],{"class":84,"line":143},[82,457,458],{"class":92},"}\n",[53,460,461,462,465,466,469,470,472,473,475,476,47],{},"Dans le bloc du ",[22,463,464],{},"if",", Kotlin sait que ",[22,467,468],{},"photo"," n'est pas ",[22,471,24],{},". Tu n'as pas besoin de ",[22,474,35],{},". On appelle cela un ",[56,477,478],{},"cast automatique",[10,480,482],{"id":481},"let-agir-seulement-si-présent","let : agir seulement si présent",[73,484,486],{"className":75,"code":485,"language":77,"meta":78,"style":78},"val photo: String? = \"tarte.jpg\"\nphoto?.let { println(\"Photo : $it\") }\n",[22,487,488,502],{"__ignoreMap":78},[82,489,490,492,494,496,498,500],{"class":84,"line":85},[82,491,194],{"class":88},[82,493,129],{"class":92},[82,495,97],{"class":96},[82,497,134],{"class":92},[82,499,137],{"class":88},[82,501,140],{"class":103},[82,503,504,507,510,513,515,518,521,524,527],{"class":84,"line":107},[82,505,506],{"class":92},"photo?.",[82,508,509],{"class":222},"let",[82,511,512],{"class":92}," { ",[82,514,223],{"class":222},[82,516,517],{"class":92},"(",[82,519,520],{"class":103},"\"Photo : ",[82,522,523],{"class":151},"$it",[82,525,526],{"class":103},"\"",[82,528,529],{"class":92},") }\n",[53,531,532,535,536,539,540,542,543,545],{},[22,533,534],{},"?.let { ... }"," exécute le bloc uniquement si la valeur existe. À l'intérieur, ",[22,537,538],{},"it"," désigne cette valeur, désormais non nulle. Si ",[22,541,468],{}," vaut ",[22,544,24],{},", rien ne se passe.",[10,547,549],{"id":548},"le-cast-sûr-as","Le cast sûr as?",[73,551,553],{"className":75,"code":552,"language":77,"meta":78,"style":78},"val valeur: Any = \"Gratin\"\nval nombre: Int? = valeur as? Int       \u002F\u002F null\nval texte: String? = valeur as? String  \u002F\u002F \"Gratin\"\n",[22,554,555,570,594],{"__ignoreMap":78},[82,556,557,559,562,565,567],{"class":84,"line":85},[82,558,194],{"class":88},[82,560,561],{"class":92}," valeur: ",[82,563,564],{"class":96},"Any",[82,566,100],{"class":88},[82,568,569],{"class":103}," \"Gratin\"\n",[82,571,572,574,577,579,581,583,586,589,592],{"class":84,"line":107},[82,573,194],{"class":88},[82,575,576],{"class":92}," nombre: ",[82,578,348],{"class":96},[82,580,134],{"class":92},[82,582,137],{"class":88},[82,584,585],{"class":92}," valeur ",[82,587,588],{"class":88},"as",[82,590,591],{"class":92},"? Int       ",[82,593,229],{"class":110},[82,595,596,598,601,603,605,607,609,611,614],{"class":84,"line":117},[82,597,194],{"class":88},[82,599,600],{"class":92}," texte: ",[82,602,97],{"class":96},[82,604,134],{"class":92},[82,606,137],{"class":88},[82,608,585],{"class":92},[82,610,588],{"class":88},[82,612,613],{"class":92},"? String  ",[82,615,616],{"class":110},"\u002F\u002F \"Gratin\"\n",[53,618,619,622,623,625],{},[22,620,621],{},"as?"," convertit une valeur vers un type. Si la conversion est impossible, il renvoie ",[22,624,24],{}," au lieu de lever une erreur.",[10,627,629],{"id":628},"à-éviter","!! : à éviter",[73,631,633],{"className":75,"code":632,"language":77,"meta":78,"style":78},"val photo: String? = null\nval longueur = photo!!.length   \u002F\u002F NullPointerException\n",[22,634,635,649],{"__ignoreMap":78},[82,636,637,639,641,643,645,647],{"class":84,"line":85},[82,638,194],{"class":88},[82,640,129],{"class":92},[82,642,97],{"class":96},[82,644,134],{"class":92},[82,646,137],{"class":88},[82,648,205],{"class":151},[82,650,651,653,655,657,660,662,665],{"class":84,"line":107},[82,652,194],{"class":88},[82,654,212],{"class":92},[82,656,137],{"class":88},[82,658,659],{"class":92}," photo",[82,661,46],{"class":88},[82,663,664],{"class":92},".length   ",[82,666,667],{"class":110},"\u002F\u002F NullPointerException\n",[53,669,670,671,673,674,676,677,679],{},"L'opérateur ",[22,672,46],{}," affirme « cette valeur n'est pas ",[22,675,24],{}," ». Si elle l'est, le programme plante avec une ",[22,678,64],{},". Tu retrouves alors le problème que Kotlin voulait éviter.",[681,682,683],"warning",{},[53,684,685,686,688,689,691,692,694,695,697,698,701,702,704],{},"Évite ",[22,687,46],{}," dans ton code. Préfère ",[22,690,35],{}," avec ",[22,693,39],{},", un ",[22,696,464],{},", ou ",[22,699,700],{},"?.let",". Réserve ",[22,703,46],{}," aux rares cas où tu es certain que la valeur existe, et où un plantage serait préférable à une valeur par défaut.",[10,706,708],{"id":707},"quel-outil-choisir","Quel outil choisir ?",[710,711,712,728],"table",{},[713,714,715],"thead",{},[716,717,718,722,725],"tr",{},[719,720,721],"th",{},"Besoin",[719,723,724],{},"Outil",[719,726,727],{},"Exemple",[729,730,731,745,759,773,787],"tbody",{},[716,732,733,737,741],{},[734,735,736],"td",{},"Autoriser l'absence",[734,738,739],{},[22,740,31],{},[734,742,743],{},[22,744,177],{},[716,746,747,750,754],{},[734,748,749],{},"Lire sans planter",[734,751,752],{},[22,753,35],{},[734,755,756],{},[22,757,758],{},"photo?.length",[716,760,761,764,768],{},[734,762,763],{},"Une valeur de secours",[734,765,766],{},[22,767,39],{},[734,769,770],{},[22,771,772],{},"photo?.length ?: 0",[716,774,775,778,782],{},[734,776,777],{},"Agir si présent",[734,779,780],{},[22,781,700],{},[734,783,784],{},[22,785,786],{},"photo?.let { ... }",[716,788,789,792,796],{},[734,790,791],{},"Convertir sans erreur",[734,793,794],{},[22,795,621],{},[734,797,798],{},[22,799,800],{},"valeur as? Int",[10,802,804],{"id":803},"à-retenir","À retenir",[15,806,807,816,823,830,837,842],{},[18,808,809,810,812,813,815],{},"Un type normal comme ",[22,811,97],{}," n'accepte jamais ",[22,814,24],{},", c'est vérifié à la compilation.",[18,817,818,820,821,47],{},[22,819,177],{}," est un type nullable : il accepte une chaîne ou ",[22,822,24],{},[18,824,825,827,828,47],{},[22,826,35],{}," appelle seulement si la valeur existe, sinon renvoie ",[22,829,24],{},[18,831,832,834,835,47],{},[22,833,39],{}," fournit une valeur de secours quand la partie gauche est ",[22,836,24],{},[18,838,839,841],{},[22,840,534],{}," exécute un bloc seulement si la valeur est présente.",[18,843,844,846,847,849,850,852],{},[22,845,46],{}," provoque une ",[22,848,64],{}," si la valeur est ",[22,851,24],{}," : à éviter.",[854,855,856],"style",{},"html pre.shiki code .sOnC1, html code.shiki .sOnC1{--shiki-light:#CF222E;--shiki-default:#FF7B72;--shiki-dark:#FF7B72}html pre.shiki code .scfrF, html code.shiki .scfrF{--shiki-light:#1F2328;--shiki-default:#E6EDF3;--shiki-dark:#E6EDF3}html pre.shiki code .sIXEE, html code.shiki .sIXEE{--shiki-light:#953800;--shiki-default:#FFA657;--shiki-dark:#FFA657}html pre.shiki code .shWOn, html code.shiki .shWOn{--shiki-light:#0A3069;--shiki-default:#A5D6FF;--shiki-dark:#A5D6FF}html pre.shiki code .sd6ml, html code.shiki .sd6ml{--shiki-light:#6E7781;--shiki-default:#8B949E;--shiki-dark:#8B949E}html pre.shiki code .s5iOY, html code.shiki .s5iOY{--shiki-light:#0550AE;--shiki-default:#79C0FF;--shiki-dark:#79C0FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .syCW7, html code.shiki .syCW7{--shiki-light:#8250DF;--shiki-default:#D2A8FF;--shiki-dark:#D2A8FF}",{"title":78,"searchDepth":107,"depth":117,"links":858},[859,860,861,862,863,864,865,866,867,868,869],{"id":12,"depth":107,"text":13},{"id":50,"depth":107,"text":51},{"id":70,"depth":107,"text":71},{"id":183,"depth":107,"text":184},{"id":287,"depth":107,"text":288},{"id":397,"depth":107,"text":398},{"id":481,"depth":107,"text":482},{"id":548,"depth":107,"text":549},{"id":628,"depth":107,"text":629},{"id":707,"depth":107,"text":708},{"id":803,"depth":107,"text":804},"Comment Kotlin évite les plantages liés à l'absence de valeur, avec les types nullables, le safe call, l'opérateur Elvis et le cast sûr.","md",{},[874,170,235,875,46,64,621,509],null,"Elvis","debutant","\u002Fkotlin\u002Fsecurite-du-null",[879],"\u002Fkotlin\u002Fconditions-boucles-fonctions",[881,885],{"nom":882,"url":883,"type":884},"Sécurité du null, cours Principes de base d'Android avec Compose","https:\u002F\u002Fdeveloper.android.com\u002Fcourses\u002Fandroid-basics-compose\u002Fcourse?hl=fr","cours",{"nom":886,"url":887,"type":888,"anglais":120},"Null safety (en anglais)","https:\u002F\u002Fkotlinlang.org\u002Fdocs\u002Fnull-safety.html","doc",{"title":5,"description":870},[891,892],{"nom":886,"url":887},{"nom":893,"url":894},"Null safety, visite guidée de Kotlin (en anglais)","https:\u002F\u002Fkotlinlang.org\u002Fdocs\u002Fkotlin-tour-null-safety.html","kotlin\u002F03.securite-du-null","XYrA6_JXg1JOCP9GwKlQXSz4oICQcodMtrPCfeXZoM0",[898,902,905,906,910,914,918],{"path":899,"title":900,"stem":901},"\u002Fkotlin\u002Fdecouvrir-kotlin","Découvrir Kotlin","kotlin\u002F01.decouvrir-kotlin",{"path":879,"title":903,"stem":904},"Conditions, boucles et fonctions","kotlin\u002F02.conditions-boucles-fonctions",{"path":877,"title":5,"stem":895},{"path":907,"title":908,"stem":909},"\u002Fkotlin\u002Fclasses-et-objets","Classes, data classes et objets","kotlin\u002F04.classes-et-objets",{"path":911,"title":912,"stem":913},"\u002Fkotlin\u002Fcollections-et-lambdas","Collections et lambdas","kotlin\u002F05.collections-et-lambdas",{"path":915,"title":916,"stem":917},"\u002Fkotlin\u002Fcoroutines-et-compose","Coroutines et Jetpack Compose","kotlin\u002F06.coroutines-et-compose",{"path":919,"title":920,"stem":921},"\u002Fkotlin","Kotlin","kotlin\u002Findex",[923,925],{"title":903,"path":879,"stem":904,"description":924,"children":-1},"Prendre des décisions avec if et when, répéter avec for, et regrouper du code dans des fonctions avec valeurs par défaut et arguments nommés.",{"title":908,"path":907,"stem":909,"description":926,"children":-1},"Modéliser tes données avec class et data class, puis utiliser object et companion object pour un singleton ou des fonctions de fabrique.",[928],{"path":879,"title":903,"ligne":77},[930,931,932,933,935,936,938],{"path":899,"title":900,"niveau":876,"stem":901},{"path":879,"title":903,"niveau":876,"stem":904},{"path":877,"title":5,"niveau":876,"stem":895},{"path":907,"title":908,"niveau":934,"stem":909},"intermediaire",{"path":911,"title":912,"niveau":934,"stem":913},{"path":915,"title":916,"niveau":937,"stem":917},"avance",{"path":919,"title":920,"niveau":939,"stem":921},"memo",1794583461684]