JavaRush /Java Blog /Random-TK /Java-da generika teoriýasy ýa-da gabygy nädip işletmeli
Viacheslav
Dereje

Java-da generika teoriýasy ýa-da gabygy nädip işletmeli

Toparda çap edildi

Giriş

JSE 5.0-den başlap, Java dil arsenalyna generikler goşuldy.
Java-da generika teoriýasy ýa-da gabygy nädip ulanmaly - 1

Java-da generikler näme?

Generika (umumylaşdyrma) umumylaşdyrylan programmirlemäni amala aşyrmak üçin Java diliniň aýratyn serişdesidir: maglumatlary we algoritmleri suratlandyrmaga aýratyn çemeleşme, düşündirişini üýtgetmän dürli maglumatlar bilen işlemäge mümkinçilik berýär. Oracle web sahypasynda umumy sapaklara bagyşlanan aýratyn sapak: “ Sapak: Generika ”.

Ilki bilen, umumy zatlara düşünmek üçin olaryň näme üçin asla zerurdygyny we näme üpjün edýändigine düşünmeli. " Näme üçin Generikleri ulanmaly ?" Bölümindäki sapakda. Maksatlaryň biri, kompil-wagt görnüşini barlamak we aç-açan kasting zerurlygyny aradan aýyrmak diýilýär.
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 2
Synaglar üçin iň halanýan sapaklarymyzy onlaýn java düzüjisini taýýarlalyň . Geliň, bu kody göz öňüne getireliň:
import java.util.*;
public class HelloWorld{
	public static void main(String []args){
		List list = new ArrayList();
		list.add("Hello");
		String text = list.get(0) + ", world!";
		System.out.print(text);
	}
}
Bu kod gowy işlär. Usöne bize gelip, “Salam, dünýä!” Diýen jümläni aýtsalar näme bolar? ýenjildi we diňe Salam gaýdyp bilersiňizmi? Geliň, kod bilen setir bilen baglanyşygy aýyralyň ", world!". Has zyýansyz bolup biläýjek ýaly? Inöne aslynda, DÜZGÜN GÖRNÜŞDE ýalňyşlyk alarys : error: incompatible types: Object cannot be converted to String Esasy zat, biziň sanawymyzda Obýekt görnüşindäki obýektleriň sanawyny saklaýar. String Obýektiň nesli bolany üçin (ähli synplar Java-da Obýektden doly miras galanlygy sebäpli), aç-açan rol oýnamagy talap edýär, biz etmedik. Birleşdirilende, obýektde statiki usul String.valueOf (obj) çagyrylar, netijede Obýektdäki toString usuly diýler. .Agny, sanawymyzda Obýekt bar. Görnüşi ýaly, Obýekt däl-de, belli bir görnüş gerek bolsa, özümiziň kasting görnüşini etmeli bolarys:
import java.util.*;
public class HelloWorld{
	public static void main(String []args){
		List list = new ArrayList();
		list.add("Hello!");
		list.add(123);
		for (Object str : list) {
		    System.out.println((String)str);
		}
	}
}
Şeýle-de bolsa, bu ýagdaýda Sanaw obýektleriň sanawyny kabul edýär, diňe bir String däl, Integer-de saklaýar. Theöne iň erbet tarapy, bu ýagdaýda düzüjiniň nädogry zat görmezligi. Ine, bu ýerde ýerine ýetiriş döwründe ýalňyşlyk alarys (olar ýalňyşyň “Iş wagty” alnandygyny hem aýdýarlar). Erroralňyşlyk bolar: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String Razy, iň ýakymly däl. Bularyň hemmesi düzüjiniň emeli intellekt däldigi we programmistiň diýjek bolýan zatlarynyň hemmesini çaklap bilmeýändigi sebäpli. Kompýuteriň haýsy görnüşlerini ulanjakdygymyz hakda has giňişleýin maglumat bermek üçin Java SE 5 umumy önümleri hödürledi . Geliň, düzüjä isleýän zadymyzy aýdyp, wersiýamyzy düzedeliň:
import java.util.*;
public class HelloWorld {
	public static void main(String []args){
		List<String> list = new ArrayList<>();
		list.add("Hello!");
		list.add(123);
		for (Object str : list) {
		    System.out.println(str);
		}
	}
}
Görşümiz ýaly, indi Stringdäki aktýorlara mätäçlik ýok. Mundan başga-da, indi umumylyklary düzýän burç ýaýlar bar. Indi düzüji, sanawa 123 goşmaçany aýyrýançak, synpyň düzülmegine rugsat bermez, sebäbi bu Integer. Ol bize şeýle diýer. Köp adamlar generiklere "sintaktik şeker" diýýärler. Dogry aýdýarlar, sebäbi generikler düzülende hakykatdanam şol bir kastlara öwrüler. Toplanan synplaryň baş koduna seredeliň: el bilen guýmak we generikleri ulanmak bilen:
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 3
.Ygyndydan soň, generika baradaky islendik maglumatlar öçürilýär. Muňa "Type Erasure" ýa-da " Type Erasure " diýilýär . Görnüşi pozmak we generika JDK-nyň köne wersiýalary bilen yza gabat gelmegi üpjün etmek üçin düzülendir, şol bir wagtyň özünde düzüjä Java-yň täze wersiýalarynda görnüş görnüşine kömek bermäge mümkinçilik berýär.
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 4

Çig görnüşler ýa-da çig görnüşler

Generika barada aýdanymyzda, elmydama iki kategoriýa bar: ýazylan görnüşler (Umumy görnüşler) we “çig” görnüşler (çig görnüşler). Çig görnüşler burç ýaýlarynda “kär” görkezmezden görnüşlerdir:
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 5
Görkezilen görnüşler "düşündiriş" görkezmek bilen tersine:
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 6
Görşümiz ýaly, skrinshotda ok bilen bellenen üýtgeşik dizaýny ulandyk. Bu Java SE 7-de goşulan ýörite sintaksis we oňa göwher diýilýän " göwher " diýilýär. Näme üçin? Göwheriň görnüşi bilen egrilen ýaýlaryň görnüşiniň arasynda meňzeşlik döredip bilersiňiz: Almaz sintaksis, " Type Inference<> " düşünjesi ýa-da görnüş görnüşi bilen baglanyşykly. Galyberse-de, düzüji, sag tarapda <> görüp, baha bellenen üýtgeýjiniň görnüşiniň deklarasiýasynyň ýerleşýän çep tarapyna seredýär. Bu bölümden sag tarapdaky bahanyň haýsy görnüşde ýazylýandygyna düşünýär. Aslynda, çep tarapda umumy görkezilen we sag tarapda görkezilmedik bolsa, düzüjiniň görnüşini görkezip biler:
import java.util.*;
public class HelloWorld{
	public static void main(String []args) {
		List<String> list = new ArrayList();
		list.add("Hello World");
		String data = list.get(0);
		System.out.println(data);
	}
}
Şeýle-de bolsa, bu täze stiliň generikler bilen köne stiliň garyndysy bolar. Bu gaty islenmeýän zat. Aboveokardaky kody düzenimizde habary alarys : Note: HelloWorld.java uses unchecked or unsafe operations. Aslynda, bu ýerde göwher goşmagyň näme üçin asla zerur däldigi düşnüksiz ýaly. Hereöne bir mysal:
import java.util.*;
public class HelloWorld{
	public static void main(String []args) {
		List<String> list = Arrays.asList("Hello", "World");
		List<Integer> data = new ArrayList(list);
		Integer intNumber = data.get(0);
		System.out.println(data);
	}
}
Radyma düşýär, “ArrayList” -iň kolleksiýany giriş hökmünde alýan ikinji konstruktory hem bar. Aldaw şu ýerde. Göwher sintaksis bolmasa, düzüjiniň aldanýandygyna düşünenok, göwher bilen düşünýär. Şonuň üçin # 1 düzgün : ýazylan görnüşleri ulansak elmydama göwher sintaksisini ulanyň. Otherwiseogsam, çig görnüşi ulanýan ýerimizde ýitirim bolmak howpy abanýar. "Barlanmadyk ýa-da howply amallary ulanýar" gündeligindäki duýduryşlardan gaça durmak üçin ulanylýan usul ýa-da synp barada ýörite bellik görkezip bilersiňiz: @SuppressWarnings("unchecked") Basyş, basmak, ýagny göni manyda duýduryşlary basmak üçin terjime edilýär. Whyöne näme üçin görkezmegi ýüregiňize düwdüňiz? Birinji düzgüni ýadyňyzdan çykarmaň, belki ýazmagy goşmaly bolarsyňyz.
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 7

Umumy usullar

Generikler usullary ýazmaga mümkinçilik berýär. “Oracle” gollanmasynda bu aýratynlyga bagyşlanan aýratyn bölüm bar: “ Umumy usullar ”. Bu gollanmadan sintaksisi ýatda saklamak möhümdir:
  • burç ýaýlaryň içinde ýazylan parametrleriň sanawyny öz içine alýar;
  • ýazylan parametrleriň sanawy yzyna gaýtarylan usuldan öň gidýär.
Bir mysala seredeliň:
import java.util.*;
public class HelloWorld{

    public static class Util {
        public static <T> T getValue(Object obj, Class<T> clazz) {
            return (T) obj;
        }
        public static <T> T getValue(Object obj) {
            return (T) obj;
        }
    }

    public static void main(String []args) {
		List list = Arrays.asList("Author", "Book");
		for (Object element : list) {
		    String data = Util.getValue(element, String.class);
		    System.out.println(data);
		    System.out.println(Util.<String>getValue(element));
		}
    }
}
Util synpyna seretseňiz, onda iki sany ýazylan usuly görýäris. Görnüş görnüşi bilen, görnüş kesgitlemesini düzüjä gönüden-göni berip bileris ýa-da özümiz kesgitläp bileris. Iki wariant hem mysalda getirilýär. .Eri gelende aýtsak, sintaksis bu hakda pikir etseň gaty mantykly. Usul ýazylanda, umumy usuldan öň umumy kesgitleýäris, sebäbi usuldan soň umumy ulansak, Java haýsy görnüşini ulanmalydygyny bilip bilmez. Şonuň üçin ilki bilen umumy T ulanjakdygymyzy mälim edýäris, soň bolsa bu umumy görnüşi yzyna gaýtararys diýýäris. Elbetde, Util.<Integer>getValue(element, String.class)ýalňyşlyk bilen şowsuz bolar incompatible types: Class<String> cannot be converted to Class<Integer>. Typazuw usullaryny ulananyňyzda, görnüşi pozmak barada elmydama ýadyňyzdan çykarmaly dälsiňiz. Bir mysala seredeliň:
import java.util.*;
public class HelloWorld {

    public static class Util {
        public static <T> T getValue(Object obj) {
            return (T) obj;
        }
    }

    public static void main(String []args) {
		List list = Arrays.asList(2, 3);
		for (Object element : list) {
		    System.out.println(Util.<Integer>getValue(element) + 1);
		}
    }
}
Gowy işlär. Onlyöne düzüjiniň diýilýän usulyň Integer görnüşiniň bardygyna düşünýänçä. Konsol çykyşyny aşakdaky setir bilen çalyşalyň: System.out.println(Util.getValue(element) + 1); thealňyşlygy alýarys: ikilik operatory üçin erbet operand görnüşleri '+', birinji görnüşi: Obýekt, ikinji görnüş: int .agny, görnüşler pozuldy. Düzediji hiç kimiň görnüşini görkezmändigini, görnüşiň Obýekt hökmünde görkezilendigini we kod ýerine ýetirilişiniň ýalňyşlyk bilen şowsuzdygyny görýär.
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 8

Umumy görnüşler

Diňe usullary däl, eýsem synplary hem ýazyp bilersiňiz. “Oracle” -yň gollanmasynda muňa bagyşlanan “ Umumy görnüşler ” bölümi bar. Bir mysala seredeliň:
public static class SomeType<T> {
	public <E> void test(Collection<E> collection) {
		for (E element : collection) {
			System.out.println(element);
		}
	}
	public void test(List<Integer> collection) {
		for (Integer element : collection) {
			System.out.println(element);
		}
	}
}
Bu ýerde hemme zat ýönekeý. Bir synp ulansak, umumy synpyň adyndan soň görkezilýär. Geliň indi esasy usulda bu synpyň mysalyny döredeliň:
public static void main(String []args) {
	SomeType<String> st = new SomeType<>();
	List<String> list = Arrays.asList("test");
	st.test(list);
}
Gowy işlär. Düzediji sanlaryň sanawynyň we setir görnüşiniň ýygyndysynyň bardygyny görýär. Emma generikleri pozup, muny etsek näme etmeli:
SomeType st = new SomeType();
List<String> list = Arrays.asList("test");
st.test(list);
Erroralňyşlygy alarys: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer erazmagy täzeden ýazyň. Synpda indi umumylyk ýoklugy sebäpli, düzüji Sanawdan geçenimizden bäri, sanaw <Integer> usuly has ýerliklidir. Aalňyşlyk bilen ýykylýarys. Şonuň üçin # 2 düzgün: Bir synp ýazylsa, mydama umumy görnüşini görkeziň .

Çäklendirmeler

Generikada görkezilen görnüşlere çäklendirme ulanyp bileris. Mysal üçin, konteýneriň diňe San hökmünde giriş hökmünde kabul edilmegini isleýäris. Bu aýratynlyk, “Oracle Tutorial” -da “ Çäklendirilen görnüş parametrleri” bölüminde beýan edilýär . Bir mysala seredeliň:
import java.util.*;
public class HelloWorld{

    public static class NumberContainer<T extends Number> {
        private T number;

        public NumberContainer(T number)  { this.number = number; }

        public void print() {
            System.out.println(number);
        }
    }

    public static void main(String []args) {
		NumberContainer number1 = new NumberContainer(2L);
		NumberContainer number2 = new NumberContainer(1);
		NumberContainer number3 = new NumberContainer("f");
    }
}
Görşüňiz ýaly, umumy görnüşi San synpy / interfeýs we onuň nesilleri hökmünde çäklendirdik. Gyzykly tarapy, diňe bir synpy däl, interfeýsleri hem kesgitläp bilersiňiz. Mysal üçin: public static class NumberContainer<T extends Number & Comparable> { Generika-da Wildcard düşünjesi bar https://docs.oracle.com/javase/tutorial/java/generics/wildcards.html Olar hem öz gezeginde üç görnüşe bölünýärler:
  • Upperokarky çäkli kartoçkalar - < ? belgisini uzadýar
  • Çäklendirilmedik kartoçkalar - < ? >
  • Aşaky çäklendirilen kartoçkalar - < ? super Integer >
Get Put diýilýän ýörelge “Wildcards” -a degişlidir . Olary aşakdaky görnüşde beýan edip bolar:
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 9
Bu ýörelge PECS (Önümçi sarp edijini giňeldýär) ýörelgesi hem diýilýär. Habré hakda “ Java API-iň ulanylyşyny gowulandyrmak üçin umumy kartoçkalary ulanmak ” makalasynda , şeýle hem akym akymy barada ajaýyp diskussiýada: “ Generics Java-da ýabany kartalary ulanmak ” atly makalada has köp okap bilersiňiz. Ine, Java çeşmesinden kiçijik mysal - Collections.copy usuly:
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 10
Nädip işlemejekdiginiň kiçijik mysaly:
public static class TestClass {
	public static void print(List<? extends String> list) {
		list.add("Hello World!");
		System.out.println(list.get(0));
	}
}

public static void main(String []args) {
	List<String> list = new ArrayList<>();
	TestClass.print(list);
}
Superöne super bilen çalyşsaňyz, hemme zat gowy bolar. Sanawy çykarmazdan ozal bir baha bilen dolduranymyz üçin, bu biziň üçin sarp ediji, ýagny sarp ediji. Şonuň üçin super ulanýarys.

Miras

Generikleriň başga bir üýtgeşik aýratynlygy bar - olaryň mirasy. Generikleriň mirasy "Oracle" gollanmasynda " Generika, miras we aşaky görnüşler " bölüminde beýan edilýär . Esasy zat aşakdakylary ýatda saklamak we durmuşa geçirmekdir. Muny edip bilmeris:
List<CharSequence> list1 = new ArrayList<String>();
Miras umumylyklar bilen başgaça işleýär:
Java-da generika teoriýasy ýa-da gabygy nädip işletmeli - 11
Ine, ýalňyşlyk bilen şowsuz boljak başga bir gowy mysal:
List<String> list1 = new ArrayList<>();
List<Object> list2 = list1;
Bu ýerde hem hemme zat ýönekeý. Sanaw <String> <Object> sanawynyň nesli däl, String Obýektiň neslidir.

Jemleýji

Şeýdip, generika ýadymyzy täzeledik. Theirhli güýjünde seýrek ulanylsa, käbir jikme-jiklikler ýatdan çykýar. Bu gysga syn, ýadyňyzy täzelemäge kömek eder diýip umyt edýärin. Has uly netijeler üçin aşakdaky materiallary okamagyňyzy maslahat berýärin: # Wiaçeslaw
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION