Wat is Generics in Java?

Generics in Java werd in 2004 geïntroduceerd als een nieuwe functie van de programmeertaal Java en maakte deel uit van de JDK 5-release. Het wordt het meest gebruikt samen met het framework voor Java-collecties. Vanaf vandaag is het een van de meest prominente en gewilde functies van de programmeertaal Java.

Generiek Java werd in 1998 gevonden door vier personen, namelijk Gilad Bracha, Martin Odersky, David Stoutamire en Philip Wadler. Het was een uitbreiding van de Java-taal die generieke typen ondersteunde. Het was bedoeld om twee hoofddoelen te bereiken:

  1. Type veiligheid
  2. Code herbruikbaarheid

Definitie van generieken in Java

Generics kunnen worden gedefinieerd als een manier om herbruikbaarheid van codes te bereiken door generieke klassen, interfaces, constructeurs en methoden te definiëren die met verschillende gegevenstypen kunnen worden gebruikt en ook om typeveiligheid te bereiken door het gegevenstype dat vooraf in de implementatie wordt gebruikt aan te geven, waardoor het elimineren van de kans op een runtime-fout.

Hoe worden generieke geneesmiddelen in Java geïmplementeerd?

Generics worden geïmplementeerd met behulp van hoekige beugels "". De haakjes omsluiten de typeparameter "T" erin. Voorbeeld De typeparameter "T" is een plaatshouder die aangeeft dat er tijdens de uitvoering een gegevenstype aan wordt toegewezen. Een generieke klasse wordt bijvoorbeeld gedefinieerd als:

public class MyGenericClass (…)

Dit zijn de standaardtypeparameters:

  • T: Type
  • E: Element
  • N: nummer
  • K: Sleutel
  • V: Waarde

S, U, V enzovoort worden gebruikt om respectievelijk tweede, derde en vierde parameters te definiëren in het geval dat er meerdere parameters worden gebruikt.

Generics in Java begrijpen

Nu vraagt ​​u zich misschien af ​​wat type veiligheid is en hoe het werkt? Of hoe verschillen generieke klassen, interfaces, constructors en methoden van onze reguliere klassen en methoden die ze herbruikbaar maken? Laten we het uitzoeken.

Omdat Java een statisch getypte taal is, moet u het "type" aangeven dat het gegevenstype is van de waarde die de variabele vasthoudt voordat u deze gebruikt.

Voorbeeld: String myString =”eduCBA”;

Hier is "String" het gegevenstype, "myString" is de variabele met een waarde waarvan het type String is.

Als u nu bijvoorbeeld een Booleaanse waarde probeert door te geven in plaats van een tekenreeks:

String myBooleanStr = true;

U krijgt onmiddellijk een compilatie-fout met de melding "Type komt niet overeen: kan niet converteren van boolean naar String".

Hoe bereiken we herbruikbaarheid van codes met generieke geneesmiddelen?

Laten we nu een normale methode definiëren:

public static void welcome(String name)(
System.out.println("welcome to " + name);
)

Deze methode kan alleen worden opgeroepen door een tekenreeksparameter door te geven. Bijvoorbeeld:

welcome(“eduCBA”);

De output is "welkom bij eduCBA".

U kunt deze methode echter niet gebruiken door andere gegevenstypen, zoals integer of boolean, te omzeilen. Als u dat probeert te doen, wordt u tijdens de compilatie een foutmelding gegeven waarin staat: "De methode welcome (String) in het type Runner is niet van toepassing op de argumenten (boolean)". Dit betekent dat u geen ander gegevenstype kunt doorgeven aan een methode die alleen een tekenreeks als parameter accepteert.

Dit betekent ook dat als u een vergelijkbare methode voor een ander gegevenstype wilt gebruiken, u een nieuwe methode moet schrijven die het vereiste gegevenstype als parameter accepteert. Dit kenmerk van herschrijfmethoden met parameters van verschillende gegevenstypen wordt ook wel methode-overload genoemd. Het grote nadeel hiervan is dat het uw code groter maakt.

We kunnen Generics echter ook gebruiken om de bovenstaande methode opnieuw te schrijven en te gebruiken voor elk gegevenstype dat we nodig hebben.

Een generieke methode definiëren:

public static void welcome(T t)(
System.out.println("it is " + t);
)

Opmerking : hier is "t" een object van het type T. T krijgt het gegevenstype toegewezen dat wordt gebruikt om de methode op te roepen.

Nu kunt u deze methode opnieuw gebruiken door deze indien nodig aan te roepen voor een tekenreeks of een Boolean of een geheel getal of een ander gegevenstype.

welcome("educate");
Integer Myint = 1;
welcome(Myint)
welcome(true);

De bovenstaande verklaringen geven de onderstaande uitvoer:

Het is Educa
Het is 1
Dat is waar

Door generieke middelen hier te gebruiken, kunnen we onze methode daarom opnieuw gebruiken voor verschillende gegevenstypen.

Hoe bereiken we typeveiligheid met behulp van generieke geneesmiddelen?

Een van de grote verschillen tussen arrays en verzameling is dat arrays alleen homogene gegevens kunnen opslaan, terwijl collecties heterogene gegevens kunnen opslaan. Dat wil zeggen dat collecties elk door de gebruiker gedefinieerd gegevenstype / objecten kunnen opslaan.

OPMERKING: Collecties kunnen alleen objecten bevatten (door de gebruiker gedefinieerd gegevenstype) en geen primitief gegevenstype. Om met primitieve gegevens te werken, maken typecollecties gebruik van wrapper-klassen.

Laten we nu eens kijken naar een ArrayList.

ArrayList myList = new ArrayList();

Laten we gegevens van het type String, Integer en Double toevoegen aan het ArrayList-object.

myList.add("eduCBA");
myList.add(1);
myList.add(5.2);

Bij het afdrukken van het ArrayList-object kunnen we zien dat het de volgende waarden bevat: (eduCBA, 1, 5.2).

Als u deze waarden vervolgens in variabelen wilt ophalen, moet u ze typen.

String someStr = (String)myList.get(0);
Integer someInt = (Integer)myList.get(1);
Double someFlt = (Double)myList.get(2);

In het geval dat u niet typt, wordt u tijdens de compilatie een foutmelding gegeven met de melding "Type mismatch: can convert from Object to String".

Hieruit kunt u concluderen dat u tijdens het ophalen van de objecten uit uw ArrayList deze naar hun respectieve typen moet typecasten. De vraag die hier opkomt, is hoe weet je welk gegevenstype je het moet typecasten? In realtime zal uw ArrayList duizenden records bevatten en het typecasting naar verschillende gegevenstypen voor elk afzonderlijk object is geen optie. Mogelijk typ je het naar het verkeerde gegevenstype. Wat gebeurt er dan?

Deze keer krijg je geen compilatietijd, maar krijg je een runtime-fout met de melding "Uitzondering in thread" main "java.lang.ClassCastException: java.lang.Integer kan niet worden gecast naar java.lang.String op com.serviceClasess.Runner .main (Runner.java:43)”.

Aangezien we het type gegevens dat in een verzameling aanwezig is (in dit geval ArrayList) niet kunnen garanderen, worden ze als onveilig beschouwd voor gebruik met betrekking tot het type. Dit is waar generieke geneesmiddelen een rol spelen om typeveiligheid te bieden.

ArrayList gebruiken met Generics:

ArrayList myList = new ArrayList();

Merk op dat binnen hoekige haakjes "" het String-type is opgegeven, wat betekent dat deze specifieke implementatie van ArrayList alleen String-type gegevens kan bevatten. Als u een ander gegevenstype probeert toe te voegen, geeft dit eenvoudigweg een compilatietijdfout. Hier hebt u uw ArrayList typebestendig gemaakt door de kans op het toevoegen van een ander gegevenstype dan "String" te elimineren.

Nu u het gegevenstype hebt opgegeven dat met behulp van generieke geneesmiddelen aan uw verzameling mag worden toegevoegd, hoeft u het niet langer te typen tijdens het ophalen van uw gegevens. Dat wil zeggen dat u eenvoudig uw gegevens kunt ophalen door te schrijven:

String someStr = myList.get(0);

Hoe maakt Generics in Java het werken zo gemakkelijk?

Het helpt om uw collecties typeveilig te maken, zodat uw code op een later tijdstip niet faalt vanwege een run-time uitzondering. Het voorkomt ook dat de codeerder elk object in de verzameling moet typecasten, waardoor de codeontwikkeling sneller en eenvoudiger wordt. Door gebruik te maken van generieke klassen en methoden kan men de code ook hergebruiken volgens het vereiste gegevenstype tijdens de implementatie.

Wat kunt u nog meer doen met Generics in Java?

Tot nu toe hebben we gezien hoe we typeveiligheid en codeherbruikbaarheid met generieke geneesmiddelen kunnen bereiken. Laten we nu eens kijken naar de andere functies die generieken bieden. Zij zijn:

  1. Begrensde en meerdere begrensde typen
  2. Typ jokertekens

Bounded Type: In het geval van een begrensd type is het datatype van een parameter begrensd tot een bepaald bereik. Dit wordt bereikt met behulp van het sleutelwoord "breiden".

Laten we bijvoorbeeld een generieke klasse overwegen met een parameter van het begrensde type die de uitvoerbare interface uitbreidt:

class myGenericClass()

Terwijl u het object in een andere klasse maakt:

myGenericClass myGen = new myGenericClass();

De bovenstaande verklaring wordt perfect uitgevoerd zonder fouten. Dat is in het geval van het begrensde type, u kunt hetzelfde klastype of het onderliggende klastype doorgeven. U kunt het parametertype ook binden aan een interface en de implementaties ervan doorgeven wanneer u het oproept, zoals in ons voorbeeld hierboven.

Wat gebeurt er als u een ander type parameter probeert te gebruiken?

myGenericClass myGen = new myGenericClass();

In het bovenstaande geval krijgt u een compilatie-fout met de melding "Bound mismatch: Het type Integer is geen geldige vervanging voor de typecast van het type myGenericClass".

Meerdere begrensde typen: In geval van meerdere begrensde typen kunnen we het parametergegevenstype aan meer dan één type binden. Bijvoorbeeld,

Class myGeneric()

In dit geval kunt u elk type passeren dat de nummerklasse uitbreidt en een uitvoerbare interface implementeert. Bij het gebruik van meerdere begrensde typen moeten echter enkele dingen worden opgemerkt:

  1. We kunnen niet meer dan één klas tegelijk uitbreiden.
  2. We kunnen een willekeurig aantal interfaces uitbreiden op een moment dat er geen limiet is voor interfaces.
  3. De klassenaam moet altijd eerst komen, gevolgd door de interfacenaam, anders resulteert dit in een compilatie-fout.

Type jokertekens: ze worden voorgesteld door "?" - vraagtekensymbool. Het maakt gebruik van twee hoofdzoekwoorden:

verlengt (om bovengrens te definiëren) en super (om ondergrenzen te definiëren).

Bijvoorbeeld,

ArrayList al

Dit ArrayList-object "al" zal alle gegevens van type T en al zijn subklassen bevatten.

ArrayList al

Dit ArrayList-object "al" zal alle gegevens van type T en al zijn superklassen bevatten.

Voordelen van generieken op Java

1. Flexibiliteit : Generics biedt onze code de flexibiliteit om verschillende datatypen te ondersteunen met behulp van generieke klassen en methoden.

2. Codeonderhoud en herbruikbaarheid : vanwege generieke klassen en methoden hoeft de code niet opnieuw te worden geschreven in geval van een wijziging in de vereisten in een later stadium waardoor de code gemakkelijker te onderhouden en opnieuw te gebruiken is.

3. Typeveiligheid: biedt typeveiligheid aan het verzamelraamwerk door het gegevenstype te definiëren dat de verzameling vooraf kan bevatten en eventuele faalkansen tijdens runtime als gevolg van ClassCastException te elimineren.

4. Eliminatie van de noodzaak om te typen: omdat de gegevenstypen die door de collecties worden bewaard, al zijn bepaald, hoeft u deze niet te typen tijdens het ophalen. Dit vermindert de lengte van de code en vermindert ook de inspanning van een codeerder.

Generics in Java skills

Om met Generics te werken, moet u goed vertrouwd zijn met de basisprincipes van Java. U moet begrijpen hoe typecontrole en typecasting werkt. Grondige kennis van andere concepten zoals methodeoverbelasting, de relatie tussen ouder- en kindklassen, interfaces en hun implementaties zijn noodzakelijk. Ook het begrijpen van het verschil tussen primitieve gegevenstypen (systeemgedefinieerd gegevenstype) en objecten (door de gebruiker gedefinieerd gegevenstype) is van cruciaal belang als het gaat om het werken met het collectiekader.

Waarom zouden we Generics in Java gebruiken?

Het gebruik van generieke geneesmiddelen maakt onze code onderhoudbaarder omdat het de noodzaak vermindert om gegevenstype-specifieke code te herschrijven telkens wanneer er een wijziging in de vereiste is. Door het generieke begrensde type te gebruiken, kunt u het gegevenstype beperken en tegelijkertijd uw code flexibel maken door het bereik te definiëren. Het is minder waarschijnlijk dat uw code op een later tijdstip faalt, omdat het type veiligheid biedt waardoor uw code minder foutgevoelig wordt.

Scope for Generics in Java

Generics scope is beperkt tot compilatie tijd. Dat betekent dat het generieke concept alleen van toepassing is tijdens het compileren, maar niet tijdens de uitvoering. Bijvoorbeeld,

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

Hier zijn alle vier bovenstaande uitspraken één en dezelfde. Hiermee kunnen alle soorten gegevens aan het lijstobject worden toegevoegd.

Conclusie

Generics maakt codering eenvoudig voor een coder. Het vermindert de kansen op ClassCastException tijdens runtime door een sterke typecontrole. Elimineert volledig de noodzaak voor typecasting, wat betekent dat minder code hoeft te worden geschreven. Het biedt ons de mogelijkheid generieke algoritmen te ontwikkelen die onafhankelijk zijn van het gegevenstype waarmee ze werken.

Aanbevolen artikelen

Dit is een handleiding geweest voor Wat is Generics in Java ?. Hier hebben we de vaardigheden, het toepassingsgebied, het werken, het begrip en het voordeel van generieke zaken in Java besproken. U kunt ook onze andere voorgestelde artikelen doornemen voor meer informatie -

  1. Wat is Common Gateway Interface
  2. Hoe Java te installeren 8
  3. wat is soapUI
  4. Wat is JavaScript?
  5. Java Booleans