Обобщено заключение от целеви тип в Java

1. Въведение

Type Inference е въведен в Java 5, за да допълни въвеждането на генерични продукти и е значително разширен в следните версии на Java, което също е посочено като Generalized Target-Type Inference.

В този урок ще разгледаме тази концепция с примерни кодове.

2. Дженерици

Generics ни предостави много предимства, като повишена безопасност на типа, избягване на грешки при преливане на тип и общи алгоритми. Можете да прочетете повече за генеричните лекарства в тази статия.

Въвеждането на генерични препарати обаче доведе до необходимостта от писане на шаблонния код поради необходимостта от предаване на параметри на типа . Някои примери са:

Map
    
      mapOfMaps = new HashMap
     
      (); List strList = Collections.emptyList(); List intList = Collections.emptyList();
     
    

3. Въведете извод преди Java 8

За да се намали ненужната многословност на кода, в Java е въведено Type Inference, което представлява процес на автоматично извеждане на неуточнени типове данни на израз въз основа на контекстната информация.

Сега можем да извикаме същите родови типове и методи, без да посочваме типовете параметри. Компилаторът автоматично извежда типовете параметри, когато е необходимо.

Можем да видим същия код, използвайки новата концепция:

List strListInferred = Collections.emptyList(); List intListInferred = Collections.emptyList(); 

В горния пример, въз основа на очакваните типове на връщане List и List , компилаторът може да изведе параметъра type на следния общ метод:

public static final  List emptyList() 

Както виждаме, полученият код е кратък. Сега можем да извикаме общи методи като обикновен метод, ако параметърът тип може да бъде изведен.

В Java 5 можем да направим Type-Inference в специфичен контекст, както е показано по-горе.

Java 7 разшири контекста, в който може да се изпълни. Той представи оператора с диаманти. Можете да прочетете повече за диамантения оператор в тази статия.

Сега можем да изпълним тази операция за конструктори на общ клас в контекст на присвояване. Такъв пример е:

Map
    
      mapOfMapsInferred = new HashMap();
    

Тук Java Compiler използва очаквания тип присвояване, за да изведе параметрите на типа на конструктора HashMap .

4. Обобщено заключение от целеви тип - Java 8

Java 8 допълнително разшири обхвата на Type Inference. Ние наричаме тази разширена способност за извод като Генерализиран извод за целеви тип. Можете да прочетете техническите подробности тук.

Java 8 също представи Lambda Expressions. Ламбда изразите нямат явен тип. За техния тип се прави извод, като се разглежда целевият тип на контекста или ситуацията. Типът цел на израз е типът данни, който Java Compiler очаква в зависимост от това къде се появява изразът.

Java 8 поддържа извод, използвайки Target-Type в контекст на метод. Когато извикваме общ метод без изрични аргументи на типа, компилаторът може да разгледа извикването на метода и съответните декларации на метода, за да определи аргумента на типа (или аргументите), които правят призоваването приложимо.

Нека разгледаме примерния код:

static  List add(List list, T a, T b) { list.add(a); list.add(b); return list; } List strListGeneralized = add(new ArrayList(), "abc", "def"); List intListGeneralized = add(new ArrayList(), 1, 2); List numListGeneralized = add(new ArrayList(), 1, 2.0);

В кода ArrayList не предоставя изрично аргумента на типа. Така че, компилаторът трябва да го направи. Първо, компилаторът разглежда аргументите на метода add. След това той разглежда параметрите, предадени при различни извиквания.

Той извършва анализ на извода за приложимост на извикването, за да определи дали методът се прилага за тези извиквания . Ако са приложими множество методи поради претоварване, компилаторът ще избере най-специфичния метод.

След това компилаторът извършва анализ на извод на тип извикване, за да определи аргументите на типа. Очакваните целеви типове също се използват в този анализ . Той извежда аргументите в трите екземпляра като ArrayList , ArrayList и ArrayList .

Заключението за целеви тип ни позволява да не посочваме типове за параметрите на ламбда израза:

List intList = Arrays.asList(5, 2, 4, 2, 1); Collections.sort(intList, (a, b) -> a.compareTo(b)); List strList = Arrays.asList("Red", "Blue", "Green"); Collections.sort(strList, (a, b) -> a.compareTo(b));

Тук параметрите a и b нямат изрично дефинирани типове. Техните типове се извеждат като Integer в първия Lambda Expression и като String във втория.

5. Заключение

В тази бърза статия разгледахме Type Inference, която заедно с генеричните продукти и Lambda Expression ни позволява да напишем кратък Java код.

Както обикновено, пълният изходен код може да бъде намерен в Github.