1. Alle klasser arverObject
Alle klasser i Java arver implisitt Objectklassen.
Vi vil analysere hva arv er og hvordan det fungerer i Java i Java Core-oppdraget. For nå skal vi vurdere ett enkelt faktum som følger av dette:
Et objekt av en hvilken som helst klasse kan tilordnes til en Objectvariabel. Eksempel:
| Kode | Merk |
|---|---|
|
Variabelen olagrer en referanse til et Scannerobjekt |
|
Variabelen olagrer en referanse til et Stringobjekt |
|
Variabelen olagrer en referanse til et Integerobjekt |
|
Variabelen olagrer en referanse til et Stringobjekt |
Det er her de gode nyhetene slutter. Kompilatoren holder ikke styr på den opprinnelige typen objekt som er lagret i en Objectvariabel, så du vil ikke kunne kalle andre metoder på det lagrede objektet enn metodene til Objectklassen.
Hvis du trenger å kalle metodene knyttet til objektets opprinnelige type, må du først lagre en referanse til den i en variabel av riktig type, og deretter kalle metodene på den variabelen:
| Kode | Merk |
|---|---|
|
Programmet vil ikke kompilere. Klassen Objecthar ingen nextInt()metode. |
|
Dette vil fungere. Her lagrer vi en referanse til et Scannerobjekt i en Scannervariabel ved hjelp av en typecast-operator . |
Du kan ikke bare gå og tilordne en Objectvariabel til en Scanner-variabel, selv om Objectvariabelen lagrer en referanse til et Scannerobjekt. Men du kan gjøre dette hvis du bruker typecast-operatoren , som du allerede vet om. Dette er dens generelle utseende:
Type name1 = (Type) name2;
Hvor name1er navnet på en Typevariabel, og name2er navnet på en Objectvariabel som lagrer en referanse til et Typeobjekt.
Typecasting
Hvis variabelens type og objektets type ikke samsvarer, vil a ClassCastExceptionbli kastet. Eksempel:
| Kode | Merk |
|---|---|
|
En feil vil oppstå under kjøring: a ClassCastExceptionvil bli kastet her |
Det er en måte å unngå denne feilen i Java: vi gjør dette ved å sjekke typen objekt som er lagret i en variabel :
name instanceof Type
Operatøren instanceofsjekker om namevariabelen er et Typeobjekt.
Som et eksempel, la oss finne en streng i en rekke forskjellige objekter:
| Kode | Merk |
|---|---|
|
Autoboksing vil konvertere disse verdiene til henholdsvis Integer, String, og Double. Sløyfe over utvalget av objekter Hvis objektet er en StringLagre det i en Stringvariabel Vis variabelen på skjermen. |
2. Hvorfor generika dukket opp - samlinger
La oss gå tilbake til samlingene.
Så snart Java-utviklere opprettet ArrayListklassen, ønsket de å gjøre den universell, slik at den kunne lagre alle typer objekter. Så de brukte en rekke Objects for å lagre elementene.
Styrken med denne tilnærmingen er at du kan legge til et objekt av enhver type i samlingen.
Selvfølgelig er det flere svakheter.
Ulempe 1.
Det var alltid nødvendig å skrive en typekonverteringsoperator når du henter elementer fra en samling:
| Kode | Merk |
|---|---|
|
Opprett en samling for å lagre referanser til Objectobjekter Fyll samlingen med tall 10, 20, ... 100; Sum elementene i samlingen Typecasting er nødvendig |
Ulempe 2.
Det var ingen garanti for at en samling inneholder en bestemt type element
| Kode | Merk |
|---|---|
|
Opprett en samling for å lagre referanser til Objectobjekter Vi fyller samlingen med tall representert som Doubleobjekter: 0.0, 2.5, 5.0, ... Sum elementene i samlingen Det vil oppstå en feil: a Doublekan ikke kastes til enInteger |
Data kan legges inn i samlingen hvor som helst:
- i en annen metode
- i et annet program
- fra en fil
- over nettverket
Ulempe 3.
Dataene i samlingen kan endres ved et uhell.
Du kan overføre en samling fylt med dataene dine til en eller annen metode. Denne metoden, skrevet av en annen programmerer, legger dataene til samlingen din.
Navnet på samlingen indikerer ikke tydelig hvilke typer data som kan lagres i den. Og selv om du gir variabelen din et klart navn, kan en referanse til den overføres til et dusin metoder, og disse metodene vil definitivt ikke vite noe om det opprinnelige navnet på variabelen.
3. Generiske legemidler

I Java elimineres alle disse problemene av denne kule tingen som kalles generika.
I Java betyr generikk muligheten til å legge til typeparametere til typer. Resultatet er en kompleks kompositttype. Det generelle synet på en slik sammensatt type er dette:
ClassName<TypeParameter>
Dette er en generisk klasse. Og den kan brukes uansett hvor du vanligvis bruker klasser.
| Kode | Beskrivelse |
|---|---|
|
Opprette variabler |
|
Opprette objekter |
|
Opprette arrays |
Bare Integervariabler kan lagres i en slik samling:
| Kode | Beskrivelse |
|---|---|
|
ArrayListsamling med Integerelementer Dette er tillatt Og dette vil også fungere
Autoboksing
Men dette er ikke tillatt: kompileringsfeil |
Du vil lære hvordan du lager dine egne klasser med typeparametere i Java Collections-oppdraget. Foreløpig skal vi se på hvordan du bruker dem og hvordan de fungerer.
4. Hvordan generika fungerer
Egentlig er generika fryktelig primitive.
Kompilatoren erstatter ganske enkelt generiske typer med vanlige typer. Men når metoder av en generisk type brukes, legger kompilatoren til en typecast-operatør for å kaste parametere til typeparameterne:
| Kode | Hva kompilatoren gjør |
|---|---|
|
|
|
|
|
|
|
|
Anta at vi har en metode som summerer tallene i en samling av heltall:
| Kode | Hva kompilatoren gjør |
|---|---|
|
|
Generika er med andre ord en slags syntaktisk sukker, akkurat som autoboksing, men litt mer. Med autoboksing legger kompilatoren til metoder for å konvertere en inttil en Integerog omvendt, og for generiske stoffer legger den til typecast-operatører.
Etter at kompilatoren har kompilert de generiske klassene dine med typeparametere, blir de ganske enkelt konvertert til vanlige klasser og typecast-operatører. Informasjon om typeargumentene som sendes til variabler av generiske typer går tapt. Denne effekten kalles også type sletting .
Noen ganger trenger programmerere som skriver generiske klasser (klasser med typeparametere) virkelig informasjonen om typene som sendes som argumenter. I Java Collections-oppdraget lærer du hvordan du håndterer dette og hva det innebærer.
5. Noen få fakta om generiske legemidler
Her er noen flere interessante fakta om generika.
Klasser kan ha flere typeparametere. Det ser omtrent slik ut:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
Egentlig er dette egentlig ikke overraskende. Hvor som helst hvor kompilatoren kan legge til en operatør for å kaste til én type, kan den legge til flere typecast-operatører.
Eksempler:
| Kode | Merk |
|---|---|
|
Metodens putførste parameter er en Integer, og den andre er enString |
Generiske typer kan også brukes som parametere . Det ser omtrent slik ut:
ClassName<TypeParameter<TypeParameterParameter>>
Anta at vi ønsker å lage en liste som vil lagre lister med strenger. I dette tilfellet får vi noe slikt:
// List of greetings
ArrayList<String> listHello = new ArrayList<String>();
listHello.add ("Hello");
listHello.add ("Hi");
// List of goodbyes
ArrayList<String> listBye = new ArrayList<String>();
listBye.add("Bye");
listBye.add ("Goodbye");
// List of lists
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
lists.add(listHello);
lists.add(listBye);
Generiske typer (typer med typeparametere) kan også brukes som matrisetyper. Det ser omtrent slik ut:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Det er ikke noe magisk som skjer her: vinkelparentesene indikerer bare typenavnet:
| Kode | Ikke-generisk motstykke |
|---|---|
|
|
|
|
|
|
GO TO FULL VERSION