1. Alla klasser ärverObject
Alla klasser i Java ärver implicit Objectklassen.
Vi kommer att analysera vad arv är och hur det fungerar i Java i Java Core-uppdraget. För nu ska vi överväga ett enkelt faktum som följer av detta:
Ett objekt av vilken klass som helst kan tilldelas en Objectvariabel. Exempel:
| Koda | Notera |
|---|---|
|
Variabeln olagrar en referens till ett Scannerobjekt |
|
Variabeln olagrar en referens till ett Stringobjekt |
|
Variabeln olagrar en referens till ett Integerobjekt |
|
Variabeln olagrar en referens till ett Stringobjekt |
Det är här de goda nyheterna slutar. Kompilatorn håller inte reda på den ursprungliga typen av objekt som sparats i en Objectvariabel, så du kommer inte att kunna anropa andra metoder på det sparade objektet än klassens metoder Object.
Om du behöver anropa metoderna som är associerade med objektets ursprungliga typ, måste du först spara en referens till den i en variabel av rätt typ och sedan anropa metoderna för den variabeln:
| Koda | Notera |
|---|---|
|
Programmet kommer inte att kompilera. Klassen Objecthar ingen nextInt()metod. |
|
Detta kommer att fungera. Här sparar vi en referens till ett Scannerobjekt i en Scannervariabel med hjälp av en typecast-operator . |
Du kan inte bara gå och tilldela en Objectvariabel till en Scanner-variabel, även om Objectvariabeln lagrar en referens till ett Scannerobjekt. Men du kan göra detta om du använder typecast-operatorn , som du redan känner till. Detta är dess allmänna utseende:
Type name1 = (Type) name2;
Var name1är namnet på en Typevariabel, och name2är namnet på en Objectvariabel som lagrar en referens till ett Typeobjekt.
Typecasting
Om variabelns typ och objektets typ inte stämmer överens, kommer a ClassCastExceptionatt kastas. Exempel:
| Koda | Notera |
|---|---|
|
Ett fel kommer att uppstå vid körning: a ClassCastExceptionkommer att kastas här |
Det finns ett sätt att undvika detta fel i Java: vi gör detta genom att kontrollera typen av objekt som lagras i en variabel :
name instanceof Type
Operatören instanceofkontrollerar om namevariabeln är ett Typeobjekt.
Som ett exempel, låt oss hitta en sträng i en rad olika objekt:
| Koda | Notera |
|---|---|
|
Autoboxning omvandlar dessa värden till respektive Integer, String, och Double. Slinga över arrayen av objekt Om objektet är ett StringSpara det till en Stringvariabel Visa variabeln på skärmen. |
2. Varför generika dök upp - samlingar
Låt oss återgå till samlingarna.
Så fort Java-utvecklare skapade ArrayListklassen ville de göra den universell, så att den kunde lagra vilken typ av objekt som helst. Så de använde en array av Objects för att lagra elementen.
Styrkan med detta tillvägagångssätt är att du kan lägga till ett objekt av vilken typ som helst i samlingen.
Naturligtvis finns det flera svagheter.
Nackdel 1.
Det var alltid nödvändigt att skriva en typkonverteringsoperator när man hämtade element från en samling:
| Koda | Notera |
|---|---|
|
Skapa en samling för att lagra referenser till Objectobjekt Fyll samlingen med siffror, 10, 20... 100; Summa elementen i samlingen Typecasting är nödvändig |
Nackdel 2.
Det fanns ingen garanti för att en samling innehåller en specifik typ av element
| Koda | Notera |
|---|---|
|
Skapa en samling för att lagra referenser till Objectobjekt Vi fyller samlingen med siffror representerade som Doubleobjekt: 0.0, 2.5, 5.0, ... Summa elementen i samlingen Det kommer att uppstå ett fel: a Doublekan inte castas till enInteger |
Data kan läggas in i samlingen var som helst:
- i en annan metod
- i ett annat program
- från en fil
- över nätverket
Nackdel 3.
Uppgifterna i samlingen kan ändras av misstag.
Du kan skicka en samling fylld med dina data till någon metod. Den metoden, skriven av en annan programmerare, lägger till sina data till din samling.
Namnet på samlingen anger inte tydligt vilka typer av data som kan lagras i den. Och även om du ger din variabel ett tydligt namn, kan en referens till den skickas till ett dussintal metoder, och de metoderna kommer definitivt inte att veta något om variabelns ursprungliga namn.
3. Generika

I Java elimineras alla dessa problem av denna coola sak som kallas generika.
I Java betyder generika möjligheten att lägga till typparametrar till typer. Resultatet är en komplex komposittyp. Den allmänna synen på en sådan sammansatt typ är denna:
ClassName<TypeParameter>
Detta är en generisk klass. Och den kan användas överallt där du normalt använder klasser.
| Koda | Beskrivning |
|---|---|
|
Skapa variabler |
|
Skapa objekt |
|
Skapar arrayer |
Endast Integervariabler kan lagras i en sådan samling:
| Koda | Beskrivning |
|---|---|
|
ArrayListsamling med Integerelement Detta är tillåtet Och detta kommer också att fungera
Autoboxning
Men detta är inte tillåtet: kompileringsfel |
Du kommer att lära dig hur du skapar dina egna klasser med typparametrar i Java Collections-uppdraget. För nu ska vi titta på hur man använder dem och hur de fungerar.
4. Hur generika fungerar
Egentligen är generika fruktansvärt primitiva.
Kompilatorn ersätter helt enkelt generiska typer med vanliga typer. Men när metoder av en generisk typ används, lägger kompilatorn till en typecast-operator för att casta parametrar till typparametrarna:
| Koda | Vad kompilatorn gör |
|---|---|
|
|
|
|
|
|
|
|
Anta att vi har en metod som summerar talen i en samling heltal:
| Koda | Vad kompilatorn gör |
|---|---|
|
|
Generika är med andra ord ett slags syntaktisk socker, precis som autoboxning, men lite mer. Med autoboxning lägger kompilatorn till metoder för att konvertera en inttill en Integeroch vice versa, och för generika lägger den till typecast-operatorer.
Efter att kompilatorn har kompilerat dina generiska klasser med typparametrar, konverteras de helt enkelt till vanliga klasser och typecast-operatorer. Information om typargumenten som skickas till variabler av generiska typer går förlorad. Denna effekt kallas även typradering .
Ibland behöver programmerare som skriver generiska klasser (klasser med typparametrar) verkligen informationen om de typer som skickas som argument. I Java Collections-uppdraget får du lära dig hur du hanterar detta och vad det innebär.
5. Lite fakta om generika
Här är några mer intressanta fakta om generika.
Klasser kan ha flera typparametrar. Det ser ut ungefär så här:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
Egentligen är detta inte riktigt förvånande. Överallt där kompilatorn kan lägga till en operatör för att casta till en typ, kan den lägga till flera typecast-operatorer.
Exempel:
| Koda | Notera |
|---|---|
|
Metodens putförsta parameter är en Integeroch den andra är enString |
Generiska typer kan också användas som parametrar . Det ser ut ungefär så här:
ClassName<TypeParameter<TypeParameterParameter>>
Anta att vi vill skapa en lista som lagrar listor med strängar. I det här fallet kommer vi att få något i stil med detta:
// 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);
Generiska typer (typer med typparametrar) kan också användas som arraytyper. Det ser ut ungefär så här:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Det är inget magiskt som händer här: vinkelparenteserna indikerar bara typnamnet:
| Koda | Icke-generisk motsvarighet |
|---|---|
|
|
|
|
|
|
GO TO FULL VERSION