Co to jest Generics w Javie?

Generics in Java został wprowadzony w 2004 roku jako nowa funkcja języka programowania Java i był częścią wydania JDK 5. Jest najczęściej używany wraz ze środowiskiem kolekcji Java. Na dzień dzisiejszy jest to jedna z najbardziej znanych i poszukiwanych cech języka programowania Java.

Ogólną Javę odkryły cztery osoby, a mianowicie Gilad Bracha, Martin Odersky, David Stoutamire i Philip Wadler w 1998 roku. Było to rozszerzenie języka Java obsługującego typy ogólne. Miał on osiągnąć dwa główne cele, którymi są:

  1. Wpisz bezpieczeństwo
  2. Możliwość ponownego użycia kodu

Definicja generyków w Javie

Ogólne można zdefiniować jako sposób na ponowne użycie kodu przez zdefiniowanie ogólnych klas, interfejsów, konstruktorów i metod, które mogą być używane z różnymi typami danych, a także osiągnięcie bezpieczeństwa typu poprzez zadeklarowanie typu danych używanych wcześniej w implementacji, eliminując w ten sposób szanse na błąd w czasie wykonywania.

W jaki sposób generyczne są implementowane w Javie?

Generyczne są realizowane za pomocą nawiasów kątowych „”. Nawiasy zawierają parametr typu „T”. Przykład Parametr typu „T” to symbol zastępczy, który wskazuje, że typ danych zostanie mu przypisany w czasie wykonywania. Na przykład klasa ogólna zostanie zdefiniowana jako:

public class MyGenericClass (…)

Poniżej podano standardowe parametry typu:

  • T: Rodzaj
  • E: Element
  • N: liczba
  • K: Klucz
  • V: Wartość

S, U, V i tak dalej są używane do definiowania odpowiednio drugiego, trzeciego i czwartego parametru, w przypadku zastosowania wieloparametrowego.

Zrozumienie Generics w Javie

Do tej pory możesz się zastanawiać, co to jest bezpieczeństwo typu i jak to działa? Albo czym różnią się klasy ogólne, interfejsy, konstruktory i metody od naszych zwykłych klas i metod, które sprawiają, że można je ponownie wykorzystać? Dowiedzmy Się.

Java jako język o typie statycznym wymaga zadeklarowania „typu”, czyli typu danych wartości przechowywanej przez zmienną przed jej użyciem.

Przykład: String myString =”eduCBA”;

Tutaj „String” jest typem danych, „myString” jest zmienną, która będzie przechowywać wartość, której typem jest String.

Teraz, jeśli spróbujesz przekazać wartość logiczną zamiast ciągu, na przykład:

String myBooleanStr = true;

Natychmiast pojawi się błąd kompilacji stwierdzający „Niedopasowanie typu: nie można przekonwertować z wartości logicznej na ciąg znaków”.

Jak uzyskać możliwość ponownego użycia kodu za pomocą generycznych?

Teraz zdefiniujmy zwykłą metodę:

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

Tę metodę można wywołać tylko przez przekazanie parametru ciągu. Na przykład:

welcome(“eduCBA”);

Jego wyjściem będzie „welcome to eduCBA”.

Nie można jednak wywołać tej metody z pominięciem innych typów danych, takich jak liczba całkowita lub wartość logiczna. Jeśli spróbujesz to zrobić, pojawi się komunikat o błędzie podczas kompilacji informujący: „Metoda welcome (String) w typie Runner nie ma zastosowania do argumentów (boolean)”. Oznacza to, że nie można przekazać żadnego innego typu danych do metody, która akceptuje tylko ciąg jako parametr.

Oznacza to również, że jeśli chcesz wywołać podobną metodę dla innego typu danych, będziesz musiał napisać nową metodę, która akceptuje wymagany typ danych jako parametr. Ta funkcja przepisywania metod z parametrami różnych typów danych jest również znana jako przeciążanie metod. Główną wadą tego jest to, że zwiększa rozmiar twojego kodu.

Jednak możemy również użyć Generics, aby ponownie napisać powyższą metodę i użyć jej do dowolnego wymaganego typu danych.

Definiowanie ogólnej metody:

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

Uwaga : Tutaj „t” jest obiektem typu T. Do T zostanie przypisany typ danych, który jest używany do wywołania metody.

Teraz możesz ponownie użyć tej metody, wywołując ją w razie potrzeby jako ciąg znaków, wartość logiczną, liczbę całkowitą lub dowolny inny typ danych.

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

Powyższe instrukcje zapewnią następujące dane wyjściowe:

To jest Educa
To jest 1
To prawda

Dlatego też, używając tutaj ogólnych, jesteśmy w stanie ponownie użyć naszej metody dla różnych typów danych.

Jak osiągnąć bezpieczeństwo typu za pomocą leków generycznych?

Jedną z głównych różnic między tablicami a kolekcją jest to, że tablice mogą przechowywać tylko dane jednorodne, podczas gdy kolekcje mogą przechowywać dane heterogeniczne. Oznacza to, że kolekcje mogą przechowywać dowolny typ danych / obiekty zdefiniowane przez użytkownika.

UWAGA: Kolekcje mogą przechowywać tylko obiekty (typ danych zdefiniowany przez użytkownika), a nie pierwotny typ danych. Aby pracować z pierwotnymi danymi, kolekcje typów korzystają z klas opakowań.

Rozważmy teraz ArrayList.

ArrayList myList = new ArrayList();

Dodajmy dane typu String, Integer i Double do obiektu ArrayList.

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

Podczas drukowania obiektu ArrayList widzimy, że zawiera on następujące wartości: (eduCBA, 1, 5.2).

Teraz, jeśli chcesz pobrać te wartości do zmiennych, będziesz musiał je rzutować czcionką.

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

W przypadku, gdy nie wykonasz rzutowania, pojawi się komunikat o błędzie podczas kompilacji z informacją „Niedopasowanie typu: nie można przekonwertować z obiektu na ciąg”.

Na podstawie tego można wywnioskować, że podczas pobierania obiektów z ArrayList należy typować rzut do odpowiednich typów. Pytanie, które się tutaj pojawia, brzmi: skąd będziesz wiedzieć, do którego typu danych chcesz go rzutować? W czasie rzeczywistym twoja ArrayList będzie zawierać tysiące rekordów, a rzutowanie jej na różne typy danych dla każdego pojedynczego obiektu nie będzie opcją. Może się zdarzyć, że typujesz go na niewłaściwy typ danych. Co się wtedy stanie?

Tym razem nie pojawi się błąd czasu kompilacji, ale zostanie zgłoszony błąd środowiska wykonawczego informujący: „Wyjątek w wątku„ main ”java.lang.ClassCastException: java.lang.Integer nie można rzutować na java.lang.String na com.serviceClasess.Runner .main (Runner.java:43) ”.

Ponieważ nie możemy zagwarantować rodzaju danych znajdujących się w kolekcji (w tym przypadku ArrayList), uważa się, że ich użycie w odniesieniu do typu nie jest bezpieczne. W tym miejscu wchodzą leki generyczne zapewniające bezpieczeństwo typu.

Używanie ArrayList z Generics:

ArrayList myList = new ArrayList();

Zauważ, że w nawiasach kątowych „” określony jest typ String, co oznacza, że ​​ta konkretna implementacja ArrayList może przechowywać tylko dane typu String. Jeśli spróbujesz dodać do niego jakikolwiek inny typ danych, po prostu wyrzuci błąd czasu kompilacji. Tutaj masz bezpieczny typ ArrayList, eliminując jego szansę na dodanie innego typu danych niż „String”.

Teraz, gdy określiłeś typ danych, który można dodać do swojej kolekcji za pomocą ogólnych, nie musisz już typować go podczas pobierania danych. Oznacza to, że możesz po prostu odzyskać swoje dane, pisząc:

String someStr = myList.get(0);

W jaki sposób Generics w Javie sprawia, że ​​praca jest tak łatwa?

Pomaga uczynić kolekcje bezpiecznymi pod względem typu, dzięki czemu kod nie zawiedzie w późniejszym czasie z powodu wyjątku czasu wykonywania. Oszczędza to również programistom kodowania przed koniecznością typowania każdego obiektu w kolekcji, dzięki czemu tworzenie kodu jest szybsze i łatwiejsze. Korzystając z ogólnych klas i metod, można również ponownie użyć kodu zgodnie z wymaganym typem danych podczas implementacji.

Co jeszcze możesz zrobić z Generics w Javie?

Do tej pory widzieliśmy, jak możemy osiągnąć bezpieczeństwo typu i możliwość ponownego użycia kodu za pomocą generycznych. Teraz spójrzmy na inne funkcje, które zapewniają ogólne. Oni są:

  1. Typy ograniczone i wielokrotne ograniczone
  2. Wpisz symbole wieloznaczne

Typ ograniczony: W przypadku typu ograniczonego typ danych parametru jest ograniczony do określonego zakresu. Osiąga się to za pomocą słowa kluczowego „przedłuża”.

Na przykład rozważmy klasę ogólną z parametrem typu ograniczonego, który rozszerza interfejs Runnable:

class myGenericClass()

Teraz podczas tworzenia obiektu w innej klasie:

myGenericClass myGen = new myGenericClass();

Powyższe stwierdzenie wykona się idealnie bez żadnych błędów. W przypadku typu ograniczonego można przekazać ten sam typ klasy lub jego typ klasy podrzędnej. Możesz także powiązać typ parametru z interfejsem i przekazać jego implementacje podczas jego wywoływania, jak w przypadku naszego przykładu powyżej.

Co się stanie, jeśli spróbujesz użyć innego rodzaju parametru?

myGenericClass myGen = new myGenericClass();

W powyższym przypadku pojawi się błąd czasu kompilacji z informacją: „Niedopasowanie graniczne: liczba całkowita typu nie jest prawidłowym zamiennikiem rzutowania typu myGenericClass”.

Wiele typów ograniczonych: W przypadku wielu typów ograniczonych możemy powiązać typ danych parametru z więcej niż jednym typem. Na przykład,

Class myGeneric()

W takim przypadku można przekazać dowolny typ, który rozszerza klasę Number i implementuje interfejs Runnable. Jednak w przypadku używania wielu typów ograniczonych należy zwrócić uwagę na kilka rzeczy:

  1. Nie możemy przedłużać więcej niż jednej klasy na raz.
  2. Możemy rozszerzyć dowolną liczbę interfejsów w tym samym czasie, który nie ma ograniczeń dla interfejsów.
  3. Nazwa klasy powinna zawsze znajdować się na pierwszym miejscu, a następnie nazwa interfejsu, jeśli nie, spowoduje to błąd czasu kompilacji.

Wpisz symbole wieloznaczne: Są reprezentowane przez „?” - symbol znaku zapytania. Wykorzystuje dwa główne słowa kluczowe:

rozszerza (aby zdefiniować górną granicę) i super (aby zdefiniować dolne granice).

Na przykład,

ArrayList al

Ten obiekt ArrayList „al” będzie przechowywać dowolne dane typu T i wszystkie jego podklasy.

ArrayList al

Ten obiekt ArrayList „al” będzie przechowywać dowolne dane typu T i wszystkie jego nadklasy.

Zalety generics w Javie

1. Elastyczność : Generics zapewnia naszemu kodowi elastyczność w dostosowywaniu różnych typów danych za pomocą klas ogólnych i metod.

2. Konserwacja i ponowne użycie kodu: Ze względu na ogólne klasy i metody nie trzeba ponownie pisać kodu, w przypadku zmiany wymagań na późniejszym etapie, co ułatwia utrzymanie i ponowne użycie kodu.

3. Bezpieczeństwo typu: Zapewnia bezpieczeństwo typu ramom kolekcji, definiując wcześniej typ danych, które kolekcja może przechowywać i eliminując wszelkie szanse na awarię w czasie wykonywania z powodu ClassCastException.

4. Eliminacja potrzeby rzutowania typu: Ponieważ typy danych przechowywane przez kolekcje są już określone, nie trzeba ich rzutować podczas pobierania. Zmniejsza to długość kodu, a także zmniejsza wysiłek kodera.

Ogólne umiejętności językowe

Aby pracować z Generics, powinieneś dobrze znać podstawy języka Java. Powinieneś zrozumieć, jak działa sprawdzanie i rzutowanie tekstu. Niezbędna jest dogłębna znajomość innych pojęć, takich jak przeciążanie metod, relacje między klasami nadrzędnymi i podrzędnymi, interfejsy i ich implementacje. Zrozumienie różnicy między pierwotnymi typami danych (typ danych zdefiniowanymi przez system) a obiektami (typ danych zdefiniowanymi przez użytkownika) jest kluczowe, jeśli chodzi o pracę ze strukturą kolekcji.

Dlaczego powinniśmy używać Generics w Javie?

Korzystanie z generycznych sprawia, że ​​nasz kod jest łatwiejszy w utrzymaniu, ponieważ zmniejsza potrzebę przepisywania kodu specyficznego dla typu danych za każdym razem, gdy zmienia się wymaganie. Używając ogólnego typu ograniczonego, można ograniczyć typ danych, a jednocześnie zapewnić elastyczność kodu poprzez zdefiniowanie jego zakresu. Twój kod ma mniejsze szanse na awarię w późniejszym czasie, ponieważ zapewnia bezpieczeństwo typu, dzięki czemu kod jest mniej podatny na błędy.

Zakres generics w Javie

Zakres ogólny jest ograniczony do czasu kompilacji. Oznacza to, że koncepcja ogólna ma zastosowanie tylko w czasie kompilacji, ale nie w czasie wykonywania. Na przykład,

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

Tutaj wszystkie powyższe cztery stwierdzenia są takie same. Umożliwiają dodawanie dowolnego typu danych do obiektu listy.

Wniosek

Generics ułatwia kodowanie koderowi. Zmniejsza szanse na wystąpienie wyjątku ClassCastException w czasie wykonywania, zapewniając silną kontrolę typu. Całkowicie eliminuje potrzebę rzutowania typu, co oznacza, że ​​trzeba napisać mniej kodu. Zapewnia nam możliwość opracowania ogólnych algorytmów, które są niezależne od typu danych, z którymi pracują.

Polecane artykuły

To był przewodnik po Co to jest generics w Javie ?. Tutaj omówiliśmy umiejętności, zakres, działanie, zrozumienie i przewagę generycznych w Javie. Możesz także przejrzeć nasze inne sugerowane artykuły, aby dowiedzieć się więcej -

  1. Co to jest Common Gateway Interface
  2. Jak zainstalować Javę 8
  3. co to jest soapUI
  4. Co to jest JavaScript?
  5. Java Booleans