1. Alle klassen ervenObject

Alle klassen in Java erven de Objectklasse impliciet.

We analyseren wat overerving is en hoe het werkt in Java in de Java Core-zoektocht. Voor nu zullen we een eenvoudig feit beschouwen dat hieruit volgt:

Een object van elke klasse kan aan een Objectvariabele worden toegewezen. Voorbeeld:

Code Opmerking
Object o = new Scanner(System.in);
De ovariabele slaat een verwijzing naar een Scannerobject op
Object o = new String();
De ovariabele slaat een verwijzing naar een Stringobject op
Object o = new Integer(15);
De ovariabele slaat een verwijzing naar een Integerobject op
Object o = "Hello";
De ovariabele slaat een verwijzing naar een Stringobject op

Dit is waar het goede nieuws eindigt. De compiler houdt het oorspronkelijke type object dat in een Objectvariabele is opgeslagen niet bij, dus u kunt geen andere methoden op het opgeslagen object aanroepen dan de methoden van de Objectklasse.

Als u de methoden moet aanroepen die zijn gekoppeld aan het oorspronkelijke type van het object, moet u eerst een verwijzing ernaar opslaan in een variabele van het juiste type en vervolgens de methoden op die variabele aanroepen:

Code Opmerking
Object o = new Scanner(System.in);
int x = o.nextInt();
Het programma zal niet compileren. De Objectklasse heeft geen nextInt()methode.
Object o = new Scanner(System.in);

Scanner console = (Scanner) o;

int x = console.nextInt();
Dit zal werken.

Hier slaan we een verwijzing naar een Scannerobject op in een Scannervariabele met behulp van een typecast-operator .

U kunt niet zomaar een variabele toewijzen Objectaan een scannervariabele, zelfs als de Objectvariabele een referentie naar een Scannerobject opslaat. Maar u kunt dit doen als u de typecast-operator gebruikt , die u al kent. Dit is het algemene uiterlijk:

Type name1 = (Type) name2;

Waar name1is de naam van een Typevariabele en name2is de naam van een Objectvariabele die een verwijzing naar een Typeobject opslaat.

Typecasting

Als het type van de variabele en het type van het object niet overeenkomen, ClassCastExceptionwordt er een gegenereerd. Voorbeeld:

Code Opmerking
Object o = new Integer(5);
String s = (String) o;
Tijdens runtime treedt er een fout op: hier wordt
een gegenereerdClassCastException

Er is een manier om deze fout in Java te voorkomen: we doen dit door het type object te controleren dat is opgeslagen in een variabele :

name instanceof Type

De instanceofoperator controleert of de namevariabele een Typeobject is.

Laten we als voorbeeld een string zoeken in een reeks van verschillende objecten:

Code Opmerking
Object[] objects = {10, "Hello", 3.14};

for (int i = 0; i < objects.length; i++)
{
   if (objects[i] instanceof String)
   {
      String s = (String) objects[i];
      System.out.println(s);
   }
}
Autoboxing converteert deze waarden naar respectievelijk een Integer, Stringen Double.

Loop over de reeks objecten

Als het object een is String

Sla het op in een Stringvariabele
Toon de variabele op het scherm.


2. Waarom generieke geneesmiddelen verschenen - collecties

Laten we terugkeren naar collecties.

Zodra Java-ontwikkelaars de ArrayListklasse hadden gemaakt, wilden ze deze universeel maken, zodat er elk type object in kon worden opgeslagen. Dus gebruikten ze een reeks Objects om de elementen op te slaan.

De kracht van deze aanpak is dat je een object van elk type aan de collectie kunt toevoegen.

Natuurlijk zijn er verschillende zwakke punten.

Nadeel 1.

Het was altijd nodig om een ​​typeconversie-operator te schrijven bij het ophalen van elementen uit een verzameling:

Code Opmerking
ArrayList numbers = new ArrayList();


for (int i = 0; i < 10; i++)
   numbers.add(i * 10);


int sum = 0;
for (int i = 0; i < 10; i++)
{
   sum = sum + (Integer) numbers.get(i);
}
Maak een verzameling om verwijzingen naar Objectobjecten op te slaan

Vul de verzameling met nummers 10, 20, ... 100;



Tel de elementen van de collectie


op Typecasting is noodzakelijk

Nadeel 2.

Er was geen garantie dat een collectie een specifiek type element bevat

Code Opmerking
ArrayList numbers = new ArrayList();


for (int i = 0; i < 10; i++)
   numbers.add(i * 2.5);


int sum = 0;
for (int i = 0; i < 10; i++)
{
   sum = sum + (Integer) numbers.get(i);
}
Maak een verzameling om verwijzingen naar Objectobjecten op te slaan

We vullen de verzameling met getallen die worden weergegeven als Doubleobjecten:
0.0, 2.5, 5.0, ...


Som de elementen van de verzameling op


Er treedt een fout op: a Doublekan niet worden gecast naar eenInteger

Gegevens kunnen overal in de verzameling worden geplaatst:

  • op een andere manier
  • in een ander programma
  • uit een bestand
  • via het netwerk

Nadeel 3.

De gegevens in de verzameling kunnen per ongeluk worden gewijzigd.

U kunt een verzameling gevuld met uw gegevens doorgeven aan een of andere methode. Die methode, geschreven door een andere programmeur, voegt zijn gegevens toe aan je verzameling.

De naam van de verzameling geeft niet duidelijk aan welke soorten gegevens erin kunnen worden opgeslagen. En zelfs als u uw variabele een duidelijke naam geeft, kan er een verwijzing naar worden doorgegeven aan een dozijn methoden, en die methoden zullen absoluut niets weten over de oorspronkelijke naam van de variabele.


3. Generieke geneesmiddelen

Generieken op Java

In Java worden al deze problemen geëlimineerd door dit coole ding dat generieke geneesmiddelen wordt genoemd.

In Java betekent generieke geneesmiddelen de mogelijkheid om typeparameters aan typen toe te voegen. Het resultaat is een complex samengesteld type. Het algemene beeld van zo'n samengesteld type is dit:

ClassName<TypeParameter>

Dit is een generieke klasse. En het kan overal worden gebruikt waar u normaal gesproken lessen gebruikt.

Code Beschrijving
ArrayList<Integer> list;
Variabelen maken
list = new ArrayList<Integer> ();
Objecten maken
ArrayList<Integer>[] array;
Arrays maken

IntegerIn zo'n verzameling kunnen alleen variabelen worden opgeslagen:

Code Beschrijving
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(new Integer(1));
list.add(2);
list.add("Hello");
ArrayListverzameling met Integerelementen
Dit mag
En dit gaat ook lukken
Autoboxen

Maar dit is niet toegestaan: compilatiefout

Je leert hoe je je eigen klassen kunt maken met typeparameters in de Java Collections-zoektocht. Voor nu zullen we bekijken hoe ze te gebruiken en hoe ze werken.


4. Hoe generieke geneesmiddelen werken

Generieke geneesmiddelen zijn eigenlijk vreselijk primitief.

De compiler vervangt eenvoudig generieke typen door gewone typen. Maar wanneer methoden van een generiek type worden gebruikt, voegt de compiler een typecast-operator toe om parameters aan de typeparameters te casten:

Code Wat de compiler doet
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList list = new ArrayList();
list.add(1);
list.add( (Integer) 1 );
int x = list.get(0);
int x = (Integer) list.get(0);
list.set(0, 10);
list.set(0, (Integer) 10);

Stel dat we een methode hebben die de getallen in een verzameling gehele getallen optelt:

Code Wat de compiler doet
public int sum(ArrayList<Integer> numbers)
{
   int result = 0;

   for (int i = 0; i < numbers.size(); i++)
      result = result + numbers.get(i);

   return result;
}
public int sum(ArrayList numbers)
{
   int result = 0;

   for (int i = 0; i < numbers.size(); i++)
      result = result + (Integer) numbers.get(i);

   return result;
}

Met andere woorden, generieke geneesmiddelen zijn een soort syntactische suiker, net als autoboxing, maar dan iets meer. Met autoboxing voegt de compiler methoden toe voor het converteren van an intnaar an Integeren vice versa, en voor generieke versies voegt het typecast-operators toe.

Nadat de compiler uw generieke klassen met typeparameters heeft gecompileerd, worden ze eenvoudig geconverteerd naar gewone klassen en typecast-operators. Informatie over de type-argumenten die zijn doorgegeven aan variabelen van generieke typen gaat verloren. Dit effect wordt ook wel typeverwijdering genoemd .

Soms hebben programmeurs die generieke klassen schrijven (klassen met typeparameters) echt behoefte aan de informatie over de typen die als argumenten worden doorgegeven. In de Java Collections quest leer je hoe je hiermee om moet gaan en wat het inhoudt.



5. Een paar feiten over generieke geneesmiddelen

Hier zijn enkele meer interessante feiten over generieke geneesmiddelen.

Klassen kunnen verschillende typeparameters hebben. Het ziet er ongeveer zo uit:

ClassName<TypeParameter1, TypeParameter2, TypeParameter3>

Eigenlijk is dit niet echt verrassend. Overal waar de compiler een operator kan toevoegen om naar één type te casten, kan hij meerdere typecast-operators toevoegen.

Voorbeelden:

Code Opmerking
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(7, "Hello");
map.put(-15, "Hello");
De puteerste parameter van de methode is een Integer, en de tweede is eenString

Generieke typen kunnen ook als parameters worden gebruikt . Het ziet er ongeveer zo uit:

ClassName<TypeParameter<TypeParameterParameter>>

Stel dat we een lijst willen maken waarin lijsten met tekenreeksen worden opgeslagen. In dit geval krijgen we zoiets als dit:

// 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);

Generieke typen (typen met typeparameters) kunnen ook als arraytypen worden gebruikt. Het ziet er ongeveer zo uit:

ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];

Er gebeurt hier niets magisch: de punthaken geven alleen de typenaam aan:

Code Niet-generieke tegenhanger
ArrayList<String>[] list = new ArrayList<String>[10];
StringArrayList[] list = new StringArrayList[10];
ArrayList<Integer>[] list = new ArrayList<Integer>[10];
IntegerArrayList[] list = new IntegerArrayList[10];
ArrayList<Scanner>[] list = new ArrayList<Scanner>[10];
ScannerArrayList[] list = new ScannerArrayList[10];