{
  "assessmentTests": {
    "java_test": {
      "name": "Java-test",
      "desc": "30 scenariospørsmål om kjernyntaks, OOP-mekanikk, collections, generics, exceptions og concurrency — finn ut om din Java matcher det som jobbutlysninger mener med Java-kompetanse.",
      "recommendation": "Din Java-ferdighetsprofil",
      "results": {
        "beginner": {
          "name": "Nybegynner",
          "desc": "Du kan skrive fungerende klasser og metoder, men spørsmålene du bommet på handler først og fremst om identitet og standardverdier snarere enn syntaks — String == vs .equals, hvorfor new String(\"x\") aldri gjenbruker strengpoolen, hva et numerisk felt standardiseres til versus et wrapper-felt. Ingen av dette handler om å være dårlig med Java; disse er de spesifikke reglene som forvirrer folk som lærte språket gjennom prøving og feiling snarere enn fra hvordan referanser og primitiver faktisk fungerer under hetten. De betyr noe på jobben fordi hver regel er der kode kompileres, kjøres, og gjør stille det gale.",
          "recommendation": "Start med tre ting, i denne rekkefølgen: hvorfor == på to String-objekter sammenligner referanser, ikke tegn (og .equals er det du nesten alltid vil), hvordan int overflow surrer stille i stedet for å kaste, og hvorfor et uinitialisert Integer-felt standardiseres til null mens et int-felt standardiseres til 0. Oracles offisielle Java-veiledninger og Baeldung dekker begge alle tre med kjørbare eksempler."
        },
        "intermediate": {
          "name": "Intermediær",
          "desc": "Du håndterer hverdagslig applikasjonskode komfortabelt — klasser, collections, rett frem kontrollflykt — og ville ikke blitt forsinket av rutinefunksjonsarbeid. Gapet mellom her og Avansert handler først og fremst om hva som skjer når Javas regler samhandler med concurrency og generics: en statisk metode oppløst av deklarert type i stedet for objektet du forventet, en HashMap-iterasjonsrekkefølge du stille stolte på, en ConcurrentModificationException fra å fjerne et element mid-løkke. Det er den slags feil som passerer en rask visuell sjekk og bare dukker opp under en spesifikk kjøretilstand.",
          "recommendation": "Fokuser på hvordan kompilatorens statiske syn på koden din skiller seg fra hva som kjører: oppløsning av overloading og statisk metodeskjuling etter deklarert type i stedet for kjøringstype, hvorfor HashMap gir ingen iterasjonsrekkefølgeegaranti, og hvorfor modifisering av en liste direkte mens iterasjon kaster ConcurrentModificationException. Deretter generics-erasure, siden det forvirrer folk som allerede kjenner collections enkeltvis."
        },
        "advanced": {
          "name": "Avansert",
          "desc": "Dette er nivået de fleste jobbutlysninger mener med \"sterk Java.\" Du leser en klasse med statiske blokker, instansblokker og flere konstruktører og kan forutsi nøyaktig hvilken rekkefølge de kjøres i, du vet hvorfor en finally-blokk stille kan kassere en try-blocks returverdi, og du griper til try-with-resources i stedet for en manuell finally-close fordi du vet rekkefølgegarantien den gir deg. Det som skiller dette bandet fra toppen er den samfulle og grensesnitt-nivå siden av arbeidet: hva synchronized faktisk låser, hva volatile gjør og ikke gjør garantert, og hvordan standard-metodekonflikter løses.",
          "recommendation": "Skyv inn i delene som beskytter kode andre tråder og andre grensesnitt også berører: forskjellen mellom hva en synchronized instansmetode låser versus en synchronized statisk metode, hvorfor volatile gir synlighet men ikke atomisitet for counter++, og hvordan Java tvinger deg til å løse en standard-metodediamant manuelt. Baeldungs og Java Concurrency in Practices materiale om Java Memory Model er naturlig neste stoppested for begge."
        },
        "expert": {
          "name": "Ekspert",
          "desc": "Du scoret på toppen av hver seksjon — kjernyntaks og typer, OOP-mekanikk og omfang, collections og generics, og exceptions, concurrency og idiomer. Praktisk sett betyr det at du kan få en fremmed klasse overlevert og forklare hvorfor en kompileringsfeil, en kjøretidsunntakelse, eller en stille feil verdi skjer, ikke bare hva syntaksen sier den burde gjøre, som er den vanskeligere og mer verdifulle ferdigheten. På dette nivået er språket sjelden en begrensningsfaktor; grensen er vanligvis concurrency-design eller formen på dataene under det.",
          "recommendation": "Avkastningen er nå i design og diagnose: lesing av en thread dump før du antar at en hengende prosess er en deadlock, valg mellom synchronized, java.util.concurrent locks og atomics som en avveining i stedet for en standard, og stream-pipeline-design som forblir lazy med vilje i stedet for ved et uhell. Hvis du blir screenet for en rolle, beskriv en concurrency-feil som en savnet happens-before edge eller en ConcurrentModificationException du fant i produksjon i stedet for å nevne Java-funksjoner — det demonstrerer resonnementet, ikke bare ordforrådet."
        }
      },
      "questions": [
        {
          "question": "Du lager to String-objekter: String a = new String(\"cat\"); String b = new String(\"cat\"); Hva evaluerer a == b til?",
          "options": [
            {
              "icon": "",
              "label": "true — strengliteraler med de samme tegnene er alltid samme objekt"
            },
            {
              "icon": "",
              "label": "true — new String(...) gjenbruker strengpoolen, så identisk tekst deler alltid ett objekt"
            },
            {
              "icon": "",
              "label": "En kompileringsfeil — == kan ikke brukes til å sammenligne String-objekter"
            },
            {
              "icon": "",
              "label": "false — new String(...) allokerer alltid et nytt objekt på heapen, så == sammenligner to forskjellige referanser selv om .equals(b) ville returnert true"
            }
          ]
        },
        {
          "question": "Integer x = 100; Integer y = 100; System.out.println(x == y); deretter Integer x2 = 200; Integer y2 = 200; System.out.println(x2 == y2); Hva skriver de to linjene?",
          "options": [
            {
              "icon": "",
              "label": "true deretter true — autoboxede Integer-objekter er alltid cachede uavhengig av verdi"
            },
            {
              "icon": "",
              "label": "false deretter false — == på Integer-objekter er alltid en referansesammenligning, så like verdier matcher aldri"
            },
            {
              "icon": "",
              "label": "true deretter false, men bare fordi 200 overløper en byte — cachekvoten er uavhengig av -128..127"
            },
            {
              "icon": "",
              "label": "true derefter false — autoboxede Integer-verdier fra -128 til 127 er cachede og delt, så 100 gjenbruker ett objekt, men 200 faller utenfor cachen og autoboxes til to separate objekter"
            }
          ]
        },
        {
          "question": "int max = Integer.MAX_VALUE; System.out.println(max + 1); Hva skjer?",
          "options": [
            {
              "icon": "",
              "label": "Det kaster en ArithmeticException for heltallsoverflow"
            },
            {
              "icon": "",
              "label": "Det skriver Integer.MAX_VALUE igjen, fordi Java klemmer ved typens maksimum"
            },
            {
              "icon": "",
              "label": "Det skriver Integer.MIN_VALUE — int-aritmetikk surrer stille rundt på overflow i stedet for å kaste"
            },
            {
              "icon": "",
              "label": "Det er en kompileringsfeil — kompilatoren oppdager overløpet på forhånd"
            }
          ]
        },
        {
          "question": "System.out.println(0.1 + 0.2 == 0.3); Hva skriver dette, og hvorfor?",
          "options": [
            {
              "icon": "",
              "label": "false — 0.1, 0.2 og 0.3 kan ikke representeres nøyaktig i binær flytende komma, så summen bærer avrundingsfeil som gjør den ikke bit-for-bit lik 0.3"
            },
            {
              "icon": "",
              "label": "true — Java-kompilatoren optimaliserer flytende-kommauttrykk til nøyaktige verdier"
            },
            {
              "icon": "",
              "label": "false — == kan ikke brukes med flytende-kommaverdier"
            },
            {
              "icon": "",
              "label": "true — 0.1 + 0.2 summerer alltid nøyaktig til 0.3 i Java"
            }
          ]
        },
        {
          "question": "En klasse deklarerer to instansfelt uten initialiserer: int count; og Integer total; Før konstruktøren kjøres, hva er deres standardverdier?",
          "options": [
            {
              "icon": "",
              "label": "Begge standardiseres til 0, fordi Integer autoboxes til int ved feltinitialisering"
            },
            {
              "icon": "",
              "label": "count er 0 og total er 0, automatisk bokset første gang det leses"
            },
            {
              "icon": "",
              "label": "count er 0 og total er null — primitive numeriske felt standardiseres til null, men et uinitialisert wrapper-referansefelt standardiseres til null som enhver annen objektreferanse"
            },
            {
              "icon": "",
              "label": "Begge standardiseres til null til de eksplisitt tilordnes, fordi Java ikke har implisitte numeriske standardverdier"
            }
          ]
        },
        {
          "question": "En løkke kjører 1000 ganger, hver gang gjør result += \"x\"; på en String result. Hva skjer faktisk under hetten hver iterasjon?",
          "options": [
            {
              "icon": "",
              "label": "Det eksisterende String-objektets interne tegnmatrise utvides på stedet"
            },
            {
              "icon": "",
              "label": "Java batch-prosesserer automatisk sammenkatningene og allokerer bare ett endelig String-objekt"
            },
            {
              "icon": "",
              "label": "Det kompileres til ett enkelt StringBuilder.append()-kall delt på tvers av alle 1000 iterasjoner, uten ekstra objekt allokert per iterasjon"
            },
            {
              "icon": "",
              "label": "Et helt nytt String-objekt opprettes og result omtildeles til å peke på det — det forrige String-objektet kastes, fordi String er immutable og += kan ikke modifisere det på stedet"
            }
          ]
        },
        {
          "question": "final List<String> names = new ArrayList<>(); Hvilken av disse er sann?",
          "options": [
            {
              "icon": "",
              "label": "names.add(\"Ana\") kompileres og fungerer fint — final forhindrer bare omtildeling av names-referansen selv, ikke mutasjon av objektet den peker på"
            },
            {
              "icon": "",
              "label": "names.add(\"Ana\") er en kompileringsfeil, fordi final gjør listen selv uforanderlig"
            },
            {
              "icon": "",
              "label": "Listen er thread-safe for samtidige skrivinger fordi den ble deklarert final"
            },
            {
              "icon": "",
              "label": "final på en lokal variabel har ingen effekt med mindre typen også erklæres immutable"
            }
          ]
        },
        {
          "question": "int[] a = {1, 2, 3}; int[] b = {1, 2, 3}; System.out.println(a == b); System.out.println(Arrays.equals(a, b)); Hva skriver de to linjene?",
          "options": [
            {
              "icon": "",
              "label": "false deretter true — == sammenligner array-referanser (to forskjellige array-objekter), mens Arrays.equals sammenligner elementene"
            },
            {
              "icon": "",
              "label": "true deretter true — arrays med identisk innhold er samme objekt i Java"
            },
            {
              "icon": "",
              "label": "false derefter false — Arrays.equals fungerer bare for objektarrays, ikke primitive int-arrays"
            },
            {
              "icon": "",
              "label": "true derefter false — == på arrays sammenligner innhold, og Arrays.equals er redundant"
            }
          ]
        },
        {
          "question": "void show(Object o) { print(\"Object\"); } void show(String s) { print(\"String\"); } Object ref = \"hello\"; show(ref); Hvilken overloading kjøres, og hvorfor?",
          "options": [
            {
              "icon": "",
              "label": "show(String) kjøres, fordi Java inspiserer den faktiske kjøringsklassen til objektet før valg av overloading"
            },
            {
              "icon": "",
              "label": "show(Object) kjøres — overloading-oppløsning avgjøres på kompileringstidspunktet ved hjelp av variabelens deklarerte type, ikke den faktiske kjøringstypen til objektet den refererer til"
            },
            {
              "icon": "",
              "label": "Det er en kompileringsfeil — Object kan ikke sendes hvor en mer spesifikk overloading finnes"
            },
            {
              "icon": "",
              "label": "Begge metoder kjøres, en hver, fordi Java oppløser overloadinger ved å prøve hvert match"
            }
          ]
        },
        {
          "question": "Klasse Base har static void greet() { print(\"Base\"); }. Klasse Derived extends Base og deklarerer også static void greet() { print(\"Derived\"); }. Du skriver: Base ref = new Derived(); ref.greet(); Hva skriver det?",
          "options": [
            {
              "icon": "",
              "label": "Derived — statiske metoder overstyres akkurat som instansmetoder, og følger den faktiske objektets kjøringstype"
            },
            {
              "icon": "",
              "label": "Det er en kompileringsfeil — statiske metoder kan ikke kalles gjennom en instansreferanse"
            },
            {
              "icon": "",
              "label": "Base — statiske metoder er ikke polymorf; kalling gjennom en referanse oppløses av referansens deklarerte type på kompileringstidspunktet, ikke objektets faktiske type"
            },
            {
              "icon": "",
              "label": "Både Base og Derived skriver, fordi kallene oppløses til både den skjulte og skjulende versjonen"
            }
          ]
        },
        {
          "question": "Inne i en metode, du skriver int count = 0; deretter prøver du å referere til count fra inni en lambda som sendes til en annen metode. Hva må være sant om count for at dette kompileres?",
          "options": [
            {
              "icon": "",
              "label": "count må være effektivt final — aldri omtildelt etter sin initialverdi — fordi en lambda fanger et snapshot, ikke en live referanse til en mutable lokal variabel"
            },
            {
              "icon": "",
              "label": "Ingenting — enhver lokal variabel kan fritt leses og omtildeles fra inni en lambda"
            },
            {
              "icon": "",
              "label": "count må erklæres volatile så lambdaen alltid ser sin siste verdi"
            },
            {
              "icon": "",
              "label": "count må være et felt, ikke en lokal variabel — lambdaer kan ikke fange locals i det hele tatt"
            }
          ]
        },
        {
          "question": "void rename(StringBuilder sb) { sb = new StringBuilder(\"new\"); } kalles som StringBuilder original = new StringBuilder(\"old\"); rename(original); Hva er original etter kallene?",
          "options": [
            {
              "icon": "",
              "label": "Blir \"new\" — objekter sendes ved referanse i Java, så omtildeling av parameteren endrer også anropersens variabel"
            },
            {
              "icon": "",
              "label": "Blir \"new\" bare for mutable typer som StringBuilder, men ikke for immutable typer"
            },
            {
              "icon": "",
              "label": "Fortsatt \"old\" — Java sender selv referansen ved verdi, så omtildeling av parameteren inni metoden bare retviser den lokale kopien av referansen, og etterlater anropersens original uberørt"
            },
            {
              "icon": "",
              "label": "Kaster en kjøretidsunntakelse, fordi sb ble omtildelt inni metoden"
            }
          ]
        },
        {
          "question": "En klasse har en statisk initialiseringsblokk, en instansinitialiserings-blokk, og en konstruktør, i den kildeordren. Du lager to objekter av denne klassen etter hverandre. I hvilken rekkefølge kjøres disse?",
          "options": [
            {
              "icon": "",
              "label": "Den statiske blokken kjøres nøyaktig en gang, første gang klassen lastes; derefter for hvert objekt, kjøres instansblokken og derefter konstruktørkroppen"
            },
            {
              "icon": "",
              "label": "Alle tre kjøres ferskt, i kildeordren, for hvert enkelt objekt som opprettes"
            },
            {
              "icon": "",
              "label": "Konstruktøren kjøres først for hvert objekt, derefter instansblokken, derefter den statiske blokken en gang helt på slutten"
            },
            {
              "icon": "",
              "label": "Den statiske blokken kjøres en gang per objekt, rett før instansblokken"
            }
          ]
        },
        {
          "question": "En klasse har void log(String s) og void log(String... args). Du kaller log(\"hi\"). Hvilken kjøres?",
          "options": [
            {
              "icon": "",
              "label": "log(String... args) — varargs-overloadinger velges alltid når begge er gjeldende"
            },
            {
              "icon": "",
              "label": "Det er en kompileringsfeil — kallene er tvetydige mellom de to overloadingene"
            },
            {
              "icon": "",
              "label": "log(String s) — når en fast-arity-overloading matcher nøyaktig, foretrekker Java den fremfor en varargs-overloading, som bare brukes som siste utveg"
            },
            {
              "icon": "",
              "label": "Hvilken som helst deklarert først i kildefilen kjøres"
            }
          ]
        },
        {
          "question": "En konstruktørs første linje kaller this(0); til delegaten til en annen konstruktør i samme klasse. Hvor er dette tillatt å vises?",
          "options": [
            {
              "icon": "",
              "label": "Hvor som helst i konstruktørkroppen, så lenge den kjøres før objektet returneres"
            },
            {
              "icon": "",
              "label": "Bare som allerede første setning i konstruktøren — this() (eller super()) må være første linje, og en konstruktør kan ikke kalle både this() og super()"
            },
            {
              "icon": "",
              "label": "Bare som siste setning, etter all feltinitialisering er fullført"
            },
            {
              "icon": "",
              "label": "Bare i konstruktører markert eksplisitt som delegerende, ved hjelp av delegate-nøkkelord"
            }
          ]
        },
        {
          "question": "Du trenger en liste som vil ha elementer satt inn på fronten ekstremt ofte, og random-access-lesing er sjelden. Hvilken er det bedre strukturelle valget, og hvorfor?",
          "options": [
            {
              "icon": "",
              "label": "ArrayList — dens sammenhengende bakingstabel gjør hver operasjon, inkludert front-innsetning, raskere enn en lenket struktur"
            },
            {
              "icon": "",
              "label": "De ytelser identisk, fordi begge implementerer List-grensesnittet med de samme tidsgarantiene"
            },
            {
              "icon": "",
              "label": "LinkedList — innsetning på fronten er O(1) fordi den bare relener en node, mens ArrayList må skifte hvert eksisterende element opp med en, noe som gjør front-innsetning O(n)"
            },
            {
              "icon": "",
              "label": "LinkedList, fordi det støtter random access i O(1) mens ArrayList ikke gjør det"
            }
          ]
        },
        {
          "question": "Du setter fem oppføringer inn i en vanlig java.util.HashMap i en spesifikk rekkefølge, deretter itererer du over den med en for-each-løkke. Hva rekkefølge kommer oppføringene ut i?",
          "options": [
            {
              "icon": "",
              "label": "Den samme rekkefølgen som oppføringene ble satt inn i, siden Java maps alltid bevarer innsettingsrekkefølgen"
            },
            {
              "icon": "",
              "label": "Ingen garantert rekkefølge i det hele tatt — HashMaps iterasjonsrekkefølge avhenger av hash-bucket-plassering, ikke innsettingsrekkefølge, og kan til og med endre seg mellom kjøringer; LinkedHashMap er det som bevarer innsettingsrekkefølge"
            },
            {
              "icon": "",
              "label": "Sortert etter nøkkel automatisk, på samme måte som en TreeMap oppfører seg"
            },
            {
              "icon": "",
              "label": "Omvendt innsettingsrekkefølge, fordi HashMap bruker en stack internt"
            }
          ]
        },
        {
          "question": "Hvor mange null-nøkler kan en vanlig java.util.HashMap holde på en gang, og hvor mange null-verdier?",
          "options": [
            {
              "icon": "",
              "label": "Ingen null-nøkler og ingen null-verdier er noensinne tillatt i noen Map-implementering"
            },
            {
              "icon": "",
              "label": "En null-nøkkel maksimalt, og hvilket som helst antall null-verdier — HashMap tillater en eneste null-nøkkel, i motsetning til Hashtable som ikke tillater noen av deler"
            },
            {
              "icon": "",
              "label": "Ubegrenset null-nøkler og ubegrensede null-verdier, siden null behandles som hvilken som helst annen nøkkel"
            },
            {
              "icon": "",
              "label": "En null-nøkkel og en null-verdi maksimalt, begge begrenset til en"
            }
          ]
        },
        {
          "question": "Du itererer en List med en for-each-løkke og kaller list.remove(item) direkte på listen fra inni løkkekroppen, på noen men ikke alle elementer. Hva skjer?",
          "options": [
            {
              "icon": "",
              "label": "Det fungerer korrekt og fjerner nøyaktig de tiltenkte elementene"
            },
            {
              "icon": "",
              "label": "Det hopper stille over elementet etter det som ble fjernet, men ellers fullføres uten feil"
            },
            {
              "icon": "",
              "label": "Det kaster IndexOutOfBoundsException når løkken når den gamle størrelsen på listen"
            },
            {
              "icon": "",
              "label": "Det kaster ConcurrentModificationException — modifisering av listens struktur direkte mens en implisitt iterator går den, blir oppdaget og avvist; Iterator.remove() må brukes i stedet"
            }
          ]
        },
        {
          "question": "Ved kjøretid, gitt en List<String> list, hva kan du faktisk bestemme om dens generiske typeparameter via refleksjon eller instanceof?",
          "options": [
            {
              "icon": "",
              "label": "Du kan kalle list.getElementType() for å hente String.class ved kjøretiden"
            },
            {
              "icon": "",
              "label": "instanceof List<String> kompileres og sjekker korrekt elementtypen"
            },
            {
              "icon": "",
              "label": "JVM lagrer typeparameteren som skjult metadata tilgjengelig via list.getGenericType()"
            },
            {
              "icon": "",
              "label": "Ingenting — generisk typeinformasjon slettes på kompileringstidspunktet, så ved kjøretid er objektet bare en List, og det er ingen måte å gjenopprette om det ble deklarert List<String> eller List<Integer>"
            }
          ]
        },
        {
          "question": "switch (day) { case 1: case 2: print(\"Weekday\"); break; case 6: print(\"Saturday\"); case 7: print(\"Sunday\"); break; default: print(\"?\"); } Hvis day er 6, hva skriver det?",
          "options": [
            {
              "icon": "",
              "label": "Bare Saturday — hver case-blokk i en switch stopper alltid etter sin egen print-setning"
            },
            {
              "icon": "",
              "label": "Bare Sunday — matching starter på case 6 men bare den siste matchende etiketten før break kjøres"
            },
            {
              "icon": "",
              "label": "Ingenting skriver, fordi day 6 har ingen matchende case med sin egen break direkte under"
            },
            {
              "icon": "",
              "label": "Saturday derefter Sunday — case 6 har ingen break, så kjøringen faller gjennom inn i neste cases-kode før den treffer følgende break"
            }
          ]
        },
        {
          "question": "En Product-klasse trenger en eneste, åpenbar \"naturlig\" sorteringsrekkefølge etter pris, pluss evnen til å sortere etter navn eller lagernivå på forskjellige steder i kodebasisene. Hvilken kombinasjon er det rette designet?",
          "options": [
            {
              "icon": "",
              "label": "Implementer Comparable<Product> tre separate ganger, en per ordning, og la anroperen velge hvilke compareTo som kjøres"
            },
            {
              "icon": "",
              "label": "Implementer Comparable<Product> for den naturlige prissorteringen, og skriv separate Comparator<Product> instanser for navn- og lagernivå-sorteringene som brukes andre steder"
            },
            {
              "icon": "",
              "label": "Bruk bare Comparator for hver sortering, inkludert pris, siden Comparable har ingen fordel her"
            },
            {
              "icon": "",
              "label": "Bruk bare Comparable ved å legge til tre overbelastede compareTo-metoder, en per ordning"
            }
          ]
        },
        {
          "question": "En metode kaller new FileReader(path), som deklarerer throws IOException. IOException strekker seg Exception, ikke RuntimeException. Hva må du gjøre for at dette kompileres?",
          "options": [
            {
              "icon": "",
              "label": "Ingenting — kompilatoren oppfyller bare dette for exceptions som utvider RuntimeException"
            },
            {
              "icon": "",
              "label": "Enten catch IOException i en try/catch eller deklarere throws IOException på din egen metode — checked exceptions må håndteres eller forplantes eksplisitt, i motsetning til unchecked RuntimeException-underklasser"
            },
            {
              "icon": "",
              "label": "Pakk kallene inn i en try/catch for RuntimeException, siden IOException automatisk er unchecked i moderne Java"
            },
            {
              "icon": "",
              "label": "Deklarere metoden som static — statiske metoder er fritatt fra checked exception-håndtering"
            }
          ]
        },
        {
          "question": "try (Resource a = new Resource(\"A\"); Resource b = new Resource(\"B\")) { ... } bruker to ressurser som implementerer AutoCloseable. Hvis try-blokken avsluttes normalt, i hvilken rekkefølge lukkes de?",
          "options": [
            {
              "icon": "",
              "label": "A lukkes først, derefter B, som matcher deklarasjonsordren"
            },
            {
              "icon": "",
              "label": "B lukkes først, derefter A — try-with-resources lukker ressurser i omvendt rekkefølge av hvordan de ble deklarert"
            },
            {
              "icon": "",
              "label": "Begge lukkes samtidig, siden try-with-resources parallelliserer opprydding"
            },
            {
              "icon": "",
              "label": "Bare B lukkes automatisk — A må fortsatt lukkes manuelt i en finally-blokk"
            }
          ]
        },
        {
          "question": "int getValue() { try { return 1; } finally { return 2; } } Hva gjør anroping getValue?",
          "options": [
            {
              "icon": "",
              "label": "Returnerer 1 — try-blokken returverdien er allerede committed før finally kjøres, så finally kan ikke endre den"
            },
            {
              "icon": "",
              "label": "Det kaster en unntakelse ved kjøretid, fordi en metode ikke kan returnere fra to steder"
            },
            {
              "icon": "",
              "label": "Returnerer 2 — en return-setning inni finally overstyrer og erstatter enhver return som allerede er i gang fra try-blokken, og kasserer verdien 1 helt"
            },
            {
              "icon": "",
              "label": "Det er en kompileringsfeil — finally får ikke inneholde en return-setning"
            }
          ]
        },
        {
          "question": "try { ... } catch (IOException e) { ... } catch (FileNotFoundException e) { ... }, og FileNotFoundException utvider IOException. Hva skjer når du prøver å kompilere dette?",
          "options": [
            {
              "icon": "",
              "label": "En kompileringsfeil — FileNotFoundException catch-blokken er uoppnåelig fordi den tidligere, mer generelle IOException catch-blokken allerede matcher hver FileNotFoundException"
            },
            {
              "icon": "",
              "label": "Det kompileres fint, og den mer spesifikke FileNotFoundException-blokken kjøres når nøyaktig den typen kastes"
            },
            {
              "icon": "",
              "label": "Det kompileres fint, og begge catch-blokker kjøres i ordren for en FileNotFoundException"
            },
            {
              "icon": "",
              "label": "Det er fine på kompileringstidspunktet men kaster en kjøretidsfeil første gang en FileNotFoundException faktisk skjer"
            }
          ]
        },
        {
          "question": "En klasse har en synchronized instansmetode process() og en synchronized statisk metode configure(). Hva låser hver enkelt spesifikk?",
          "options": [
            {
              "icon": "",
              "label": "process() låser monitoren til det spesifikke objektinstansen den kalles på, mens configure() låser monitoren til Class-objektet selv — delt av hver instans"
            },
            {
              "icon": "",
              "label": "Begge låser samme eneste globale lock for hele JVM, uavhengig av instans eller klasse"
            },
            {
              "icon": "",
              "label": "process() låser Class-objektet, og configure() låser hvilken som helst instans som tilfeldigvis kaller det"
            },
            {
              "icon": "",
              "label": "Ingen låser faktisk noe bare med mindre en synchronized blokk også brukes inni metodekroppen"
            }
          ]
        },
        {
          "question": "Et felt erklæres volatile int counter = 0;, og flere tråder kjører counter++ på det samtidig. Forhindrer volatile tabte oppdateringer her?",
          "options": [
            {
              "icon": "",
              "label": "Ja — volatile gjør hver operasjon på feltet atomisk, inkludert inkrementinger"
            },
            {
              "icon": "",
              "label": "Nei — volatile garanterer bare at lesinger ser den siste skriving på tvers av tråder (synlighet); counter++ er en les-modifiserings-skrive med flere trinn, og volatile gjør ingenting for å gjøre disse trinnene atomiske"
            },
            {
              "icon": "",
              "label": "Ja, men bare for int og long felt spesifikk, på grunn av hvordan JVM håndterer 64-bitverdier"
            },
            {
              "icon": "",
              "label": "Nei, og volatile mislykkes også å garantere synlighet for primitive typer som int"
            }
          ]
        },
        {
          "question": "Grensesnitt A og grensesnitt B erklærer hver en standard metode describe(). En klasse implementerer både A og B og overstyrer ikke describe() selv. Hva skjer?",
          "options": [
            {
              "icon": "",
              "label": "Kompilatoren velger interface A's versjon automatisk, siden den er oppført først i implements-klausulen"
            },
            {
              "icon": "",
              "label": "Begge versjonene kjøres, en etter en, hver gang describe() kalles"
            },
            {
              "icon": "",
              "label": "Det er fint på kompileringstidspunktet, men kaster en AmbiguousMethodException første gang describe() kalles"
            },
            {
              "icon": "",
              "label": "En kompileringsfeil — når to grensesnitt bidrar med samme standardmetode, må den implementerende klassen overstyres selv for å løse tvetydigheten, siden Java ikke gjetter hvilken du mente"
            }
          ]
        },
        {
          "question": "list.stream().filter(x -> x > 0).map(x -> x * 2); er skrevet men resultatet blir aldri tildelt en terminal-operasjon som .collect() eller .forEach(). Hva skjer faktisk når denne linjen kjøres?",
          "options": [
            {
              "icon": "",
              "label": "Ingenting skjer med listens elementer i det hele tatt — filter og map er lazy mellomliggende operasjoner som bare bygger opp en pipeline-beskrivelse; uten en terminal-operasjon, kjøres ingenting av denne pipeline"
            },
            {
              "icon": "",
              "label": "Hvert element filtreres og kartlegges umiddelbart, nøyaktig som hvis en terminal-operasjon ble kalt"
            },
            {
              "icon": "",
              "label": "Bare filter kjøres umiddelbart; map utsettes til en terminal-operasjon vises"
            },
            {
              "icon": "",
              "label": "Det kaster en IllegalStateException, fordi en stream-pipeline krever en terminal-operasjon for å kompilere"
            }
          ]
        }
      ],
      "optionOrderVersion": "0154f9576054ad6f"
    }
  }
}
