I Java-programmering er en av de grunnleggende måtene å overføre informasjon mellom koder via metoder gjennom verdiparametere. Dette er en mekanisme der verdiene i argumentene som blir sendt til en metode, kopieres til de respektive parameterne i metoden. Hvis du for eksempel har en metode som tar to parametre, age og weight, og sender to argumenter, myAge og myWeight, så kopieres verdiene fra argumentene inn i parameterne.
For å forstå dette bedre, kan vi se på en enkel kode. Hvis vi har følgende kode:
Her sendes verdiene av myAge og myWeight til metoden outputAgeAndWeight, og de kopieres til parameterne age og weight. Når denne metoden kjører, får vi utskriften "age: 23 weight: 185.4". Det som skjer bak kulissene, er at verdiene i argumentene blir "kopiert" inn i de respektive parameterne i metoden.
Denne prosessen kalles verdioverføring, eller passing by value, fordi det ikke er referanser til minneceller som blir delt, men snarere en kopi av verdiene. Når metoden er ferdig med å utføre sin oppgave, blir parametrene de-allokert, og minnene som ble brukt til å holde verdiene, blir frigitt.
En viktig ting å merke seg er at selv om navnene på argumentene og parameterne kan være like, vil det fortsatt bli opprettet separate minneceller for argumentene i klientkoden og for parameterne i metoden. Dette betyr at endringer på parameterne inne i metoden ikke påvirker verdiene i argumentene i klientkoden.
En annen illustrasjon av dette kan sees i følgende scenario:
I dette eksemplet har vi endret age i metoden, men når kontrollen går tilbake til main-metoden, vil myAge fortsatt være uendret.
Et viktig aspekt ved denne mekanismen er rekkevidden, eller scope, av variabler. Variablene i metoden er kun tilgjengelige innenfor det området (scope) der de er definert. Dette betyr at en metode kan ikke få tilgang til variabler som er deklarert utenfor den metoden. Hvis vi for eksempel endrer navnet på parameterne i metoden til å matche argumentene i klientkoden, vil koden fortsatt fungere på samme måte, men vi vil ikke påvirke variablene utenfor metoden.
Her er et eksempel der vi bytter navn på parameterne til å matche argumentene:
Her vil vi få verdien 24 for myAge i metoden, men variabelen myAge i main-metoden forblir 23. Dette forhindrer at metoden utilsiktet endrer dataene som er lagret i klientkoden.
Noen ganger kan det være ønskelig å endre argumentene i klientkoden ved å bruke metoder. Et eksempel på dette er en metode som bytter plass på to variabler, slik som i et swap-funksjon:
I dette tilfellet vil ikke verdiene av a og b bli byttet i main-metoden, til tross for at de blir byttet i swap-metoden. Dette skjer fordi metodens parametre er separate kopier av argumentene, og endringene i swap påvirker ikke de opprinnelige verdiene i main-metoden.
For at vi skulle kunne få en effekt av å bytte verdiene av a og b i klientkoden, måtte vi bruke referanser eller objekter, hvor endringene i objektet kan reflekteres tilbake til klientkoden. Men i verdiparametere skjer en kopi, og derfor er endringene lokale for metoden.
Videre kan det være nyttig å forstå hvordan minnebruk og parameteroverføring fungerer for å unngå ineffektivitet eller uforutsette feil i større programmer. I tilfeller der vi ønsker å ha direkte kontroll over verdier, kan det være nødvendig å bruke andre metoder som referanseparametre (f.eks. ved hjelp av objekter eller arrays).
Det er også viktig å merke seg at når verdiene blir kopiert inn i parameterne, blir det ikke gjort noen form for "delings"-operasjon mellom argumentene og parameterne. Dette beskytter dataene i klientkoden mot utilsiktede endringer, men kan også føre til at større mengder minne brukes i tilfelle av store datastrukturer.
Hvordan objektserialisering og deserialisering fungerer i spillprogrammering
Objektserialisering er en teknikk som benyttes til å konvertere objekter til et format som kan lagres på en diskfil, mens deserialisering innebærer å rekonstruere disse objektene når de blir lest tilbake fra filen. Når vi diskuterer dette konseptet i sammenheng med spillprogrammering, ser vi på hvordan objekter kan lagres og gjenopprettes ved hjelp av spesifikke verktøy og teknikker som tilbys av Java-plattformen, som ObjectOutputStream og ObjectInputStream.
I tradisjonell filhåndtering, som diskutert tidligere, kan informasjon skrives til en fil som tekststrenger ved hjelp av metoder som println og print i PrintWriter. Disse metodene konverterer dataene til ASCII-tegn. Dette innebærer at selv ikke-streng data (som heltall eller objektreferanser) må konverteres til strenger før de kan lagres. For eksempel, når et tall som 175 lagres, blir både strengen "175" og det faktiske tallet 175 skrevet som "175" i filen. Dette skaper et problem: informasjonen om datatypen går tapt, og for å lese dataene korrekt, må det være et beskrivende lagringsformat som kan informere om hvilken type data som ble lagret, i hvilken rekkefølge, og hvilken klasse objektet tilhørte.
En mer sofistikert tilnærming til dette er objektserialisering, som introduserer writeObject metoden fra ObjectOutputStream-klassen. Denne metoden kan skrive et objekt til en fil og samtidig lagre all nødvendig informasjon for å rekonstruere objektet ved lesing fra filen. Ved bruk av serialisering blir objektenes datamedlemmer, klasser, og rekkefølge nøye dokumentert i filen, slik at den kan gjenopprettes riktig senere. Deserialisering skjer deretter ved å bruke readObject metoden fra ObjectInputStream, som henter objektet fra filen og rekonstruerer det ved å bruke den lagrede informasjonen.
En praktisk applikasjon som illustrerer dette konseptet, finnes i eksemplet med lagring og gjenoppretting av objekter fra en spillapplikasjon som holder oversikt over båter i en marina. Ved hjelp av polymorfe array kan ulike typer båter (som er underklasser av en abstrakt Boat klasse) lagres og leses tilbake fra en fil på en effektiv måte. Når spilleren interagerer med spillbrettet ved å klikke på forskjellige knapper, kan båtene lagres til en fil ved hjelp av objektserialisering, og senere gjenopprettes når spilleren velger å vise båtene på nytt. Denne prosessen demonstrerer hvordan serialisering og deserialisering fungerer i praksis i et polymorfisk miljø.
En viktig detalj som bør understrekes er at for at et objekt skal kunne serialiseres, må objektets datamedlemmer være serialiserbare. Dette gjelder primitiv data som int og String, samt arrays av primitive typer. Java-API-dokumentasjonen gir detaljerte retningslinjer for hvilke datatyper som kan serialiseres, og hvilken klasse som må implementere Serializable grensesnittet. Hvis et objekt inneholder ikke-serialiserbare datamedlemmer, vil det oppstå en feilmelding når programmet forsøker å utføre serialisering.
En annen viktig betraktning er unntakshåndtering ved serialisering og deserialisering. Når objekter leses eller skrives til fil, kan det oppstå unntak, for eksempel filtilgangsproblemer eller typekonverteringsfeil. Dette er grunnen til at metoder som håndterer disse operasjonene, som de som er vist i eksemplet med marinaen, inkluderer mekanismer for å fange og håndtere unntak på en korrekt måte, enten gjennom try-catch blokker eller ved å inkludere en throws klausul i metodehodet.
Objektserialisering gir også muligheten for polymorfisme i filoperasjoner. Dette betyr at forskjellige typer objekter, som alle deler en felles superklasse, kan lagres og leses tilbake fra filen uten at det er nødvendig å spesifisere hver enkelt objekttype eksplisitt. Når objektene er relatert gjennom arv, kan filen inneholde en blanding av objekter som tilhører forskjellige klasser, og programmet kan fortsatt gjenkjenne og rekonstruere dem riktig.
For spillprogrammerere og utviklere som arbeider med persistens i objekter, er det derfor viktig å forstå hvordan serialisering og deserialisering fungerer for effektivt å kunne lagre og hente komplekse objekter fra filer. Dette åpner for mange muligheter i lagring og uthenting av spilldata, brukerinformasjon, og andre elementer som kan være nyttige i spillutvikling og databehandling.

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский