1. Alle klasser arverObject
Alle klasser i Java arver implicit Object
klassen.
Vi vil analysere, hvad arv er, og hvordan det fungerer i Java i Java Core-questen. Indtil videre vil vi overveje en simpel kendsgerning, der følger af dette:
Et objekt af enhver klasse kan tildeles til en Object
variabel. Eksempel:
Kode | Bemærk |
---|---|
|
Variablen o gemmer en reference til et Scanner objekt |
|
Variablen o gemmer en reference til et String objekt |
|
Variablen o gemmer en reference til et Integer objekt |
|
Variablen o gemmer en reference til et String objekt |
Det er her den gode nyhed slutter. Compileren holder ikke styr på den oprindelige type objekt, der er gemt i en Object
variabel, så du vil ikke være i stand til at kalde metoder på det gemte objekt ud over klassens metoder Object
.
Hvis du skal kalde de metoder, der er knyttet til objektets oprindelige type, skal du først gemme en reference til det i en variabel af den korrekte type, og derefter kalde metoderne på den variabel:
Kode | Bemærk |
---|---|
|
Programmet vil ikke kompilere. Klassen Object har ingen nextInt() metode. |
|
Dette vil virke. Her gemmer vi en reference til et Scanner objekt i en Scanner variabel ved hjælp af en typecast-operator . |
Du kan ikke bare gå og tildele en Object
variabel til en Scanner-variabel, selvom Object
variablen gemmer en reference til et Scanner
objekt. Men du kan gøre dette, hvis du bruger typecast-operatoren , som du allerede kender til. Dette er dens generelle udseende:
Type name1 = (Type) name2;
Hvor name1
er navnet på en Type
variabel, og name2
er navnet på en Object
variabel, der gemmer en reference til et Type
objekt.
Typecasting
Hvis variabelens type og objektets type ikke stemmer overens, ClassCastException
vil en blive kastet. Eksempel:
Kode | Bemærk |
---|---|
|
Der opstår en fejl under kørsel: a ClassCastException vil blive smidt her |
Der er en måde at undgå denne fejl i Java: vi gør dette ved at kontrollere typen af objektet, der er gemt i en variabel :
name instanceof Type
Operatøren instanceof
kontrollerer, om name
variablen er et Type
objekt.
Lad os som et eksempel finde en streng i en række forskellige objekter:
Kode | Bemærk |
---|---|
|
Autoboxing vil konvertere disse værdier til henholdsvis en Integer , String , og Double . Sløjfe over rækken af objekter Hvis objektet er en String Gem det til en String variabel Vis variablen på skærmen. |
2. Hvorfor generiske lægemidler dukkede op - samlinger
Lad os vende tilbage til samlinger.
Så snart Java-udviklere oprettede ArrayList
klassen, ønskede de at gøre den universel, så den kunne gemme enhver type objekt. Så de brugte en række Object
s til at gemme elementerne.
Styrken ved denne tilgang er, at du kan tilføje et objekt af enhver type til samlingen.
Selvfølgelig er der flere svagheder.
Ulempe 1.
Det var altid nødvendigt at skrive en typekonverteringsoperator, når man hentede elementer fra en samling:
Kode | Bemærk |
---|---|
|
Opret en samling for at gemme referencer til Object objekter Fyld samlingen med tal 10 , 20 , ... 100 ; Sum elementerne i samlingen Typecasting er nødvendig |
Ulempe 2.
Der var ingen garanti for, at en samling indeholder en bestemt type element
Kode | Bemærk |
---|---|
|
Opret en samling for at gemme referencer til Object objekter Vi fylder samlingen med tal repræsenteret som Double objekter: 0.0 , 2.5 , 5.0 , ... Sum elementerne i samlingen Der vil være en fejl: a Double kan ikke castes til enInteger |
Data kan lægges ind i samlingen hvor som helst:
- i en anden metode
- i et andet program
- fra en fil
- over netværket
Ulempe 3.
Dataene i samlingen kan ændres ved et uheld.
Du kan videregive en samling fyldt med dine data til en eller anden metode. Denne metode, skrevet af en anden programmør, føjer sine data til din samling.
Navnet på samlingen angiver ikke klart, hvilke typer data der kan gemmes i den. Og selvom du giver din variabel et klart navn, kan en reference til den overføres til et dusin metoder, og disse metoder vil bestemt ikke vide noget om det oprindelige navn på variablen.
3. Generiske lægemidler
I Java er alle disse problemer elimineret af denne seje ting kaldet generika.
I Java betyder generisk evnen til at tilføje typeparametre til typer. Resultatet er en kompleks sammensat type. Den generelle opfattelse af en sådan sammensat type er dette:
ClassName<TypeParameter>
Dette er en generisk klasse. Og det kan bruges overalt, hvor du normalt bruger klasser.
Kode | Beskrivelse |
---|---|
|
Oprettelse af variabler |
|
Oprettelse af objekter |
|
Oprettelse af arrays |
Kun Integer
variabler kan gemmes i en sådan samling:
Kode | Beskrivelse |
---|---|
|
ArrayList samling med Integer elementer Dette er tilladt Og det vil også virke
Autoboksning
Men dette er ikke tilladt: kompileringsfejl |
Du lærer, hvordan du opretter dine egne klasser med typeparametre i Java Collections-questen. Indtil videre vil vi se på, hvordan man bruger dem, og hvordan de virker.
4. Hvordan generika virker
Faktisk er generiske lægemidler frygtelig primitive.
Compileren erstatter simpelthen generiske typer med almindelige typer. Men når metoder af en generisk type bruges, tilføjer compileren en typecast-operator til at caste parametre til typeparametrene:
Kode | Hvad compileren gør |
---|---|
|
|
|
|
|
|
|
|
Antag, at vi har en metode, der summerer tallene i en samling af heltal:
Kode | Hvad compileren gør |
---|---|
|
|
Med andre ord er generika en slags syntaktisk sukker, ligesom autoboxing, men lidt mere. Med autoboxing tilføjer compileren metoder til at konvertere en int
til en Integer
og omvendt, og for generiske stoffer tilføjer den typecast-operatorer.
Efter compileren har kompileret dine generiske klasser med typeparametre, konverteres de simpelthen til almindelige klasser og typecast-operatorer. Information om typeargumenterne, der sendes til variabler af generiske typer, går tabt. Denne effekt kaldes også type sletning .
Nogle gange har programmører, der skriver generiske klasser (klasser med typeparametre), virkelig brug for informationen om de typer, der sendes som argumenter. I Java Collections-questen lærer du, hvordan du håndterer dette, og hvad det indebærer.
5. Et par fakta om generiske lægemidler
Her er nogle flere interessante fakta om generiske lægemidler.
Klasser kan have flere typeparametre. Det ser sådan ud:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
Faktisk er dette ikke rigtig overraskende. Hvor som helst compileren kan tilføje en operator til at caste til én type, kan den tilføje flere typecast-operatorer.
Eksempler:
Kode | Bemærk |
---|---|
|
Metodens put første parameter er en Integer , og den anden er enString |
Generiske typer kan også bruges som parametre . Det ser sådan ud:
ClassName<TypeParameter<TypeParameterParameter>>
Antag, at vi vil oprette en liste, der gemmer lister med strenge. I dette tilfælde får vi noget som dette:
// 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 typeparametre) kan også bruges som arraytyper. Det ser sådan ud:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Der sker ikke noget magisk her: vinkelparenteserne angiver blot typenavnet:
Kode | Ikke-generisk modstykke |
---|---|
|
|
|
|
|
|
GO TO FULL VERSION