Подтвердить что ты не робот

Java generics: несколько общих параметров?

Мне было интересно, можно ли написать функцию, которая принимает несколько общих типов следующим образом:

public int void myfunction(Set<T> a, Set<T> b) {
    return 5;
}

Set<Integer> setA = new HashSet<Integer>();
Set<String> setB = new HashSet<String>();
int result = myfunction(setA, setB);

Будет ли это работать? Обобщает ли общий параметр в каждом параметре, что каждый параметр должен иметь тот же тип T, что и общий?

Спасибо!

4b9b3361

Ответ 1

Да - возможно (хотя и не с вашей сигнатурой метода) и да, с вашей подписью типы должны быть одинаковыми.

С сигнатурой, которую вы указали, T должен быть связан с одним типом (например, String или Integer) на сайте вызова. Вы можете, однако, объявить сигнатуры методов, которые принимают несколько параметров типа

public <S, T> void func(Set<S> s, Set<T> t)

Обратите внимание на приведенную выше подпись, что я объявил типы S и T в самой подписи. Поэтому они различны и не зависят от каких-либо общих типов, связанных с классом или интерфейсом, который содержит эту функцию.

public class MyClass<S, T> {
   public        void foo(Set<S> s, Set<T> t); //same type params as on class
   public <U, V> void bar(Set<U> s, Set<V> t); //type params independent of class
}

Возможно, вам стоит взглянуть на некоторые подписи методов классов коллекции в пакете java.util. Дженерики - довольно сложный вопрос, особенно когда рассматриваются подстановочные знаки (? extends и ? super). Например, часто бывает, что метод, который может принимать Set<Number> в качестве параметра, также должен принимать Set<Integer>. В этом случае вы увидите такую ​​подпись:

public void baz(Set<? extends T> s);

Есть много вопросов, которые уже есть для SO, чтобы вы могли посмотреть на эту тему!

Не уверен, что точка возврата int из функции, хотя вы можете сделать это, если хотите!

Ответ 2

Вы можете объявлять несколько типов переменных типа или метода. Например, используя параметры типа для метода:

<P, Q> int f(Set<P>, Set<Q>) {
  return 0;
}

Ответ 3

Более того, вы можете наследовать дженерики:)

@SuppressWarnings("unchecked")
public <T extends Something<E>, E extends Enum<E> & SomethingAware> T getSomething(Class<T> clazz) {
        return (T) somethingHolderMap.get(clazz);
    }

Ответ 4

a и b оба должны быть наборами одного и того же типа. Но ничто не мешает вам писать

myfunction(Set<X> a, Set<Y> b)

Ответ 5

В определении функции вы сдерживаете наборы a и b для одного и того же типа. Вы также можете написать

public <X,Y> void myFunction(Set<X> s1, Set<Y> s2){...}

Ответ 6

Вы можете выполнить один из следующих подходов:

1) Основной, одиночный тип:

//One type
public static <T> void fill(List <T> list, T val) {

    for(int i=0; i<list.size(); i++){
        list.set(i, val);
    }

}

2) Несколько типов:

// multiple types as parameters
public static <T1, T2> String multipleTypeArgument(T1 val1, T2 val2) {

    return val1+" "+val2;

}

3) Ниже будет повышена ошибка компилятора, так как "T3 не входит в список родовых типов, которые используются в части объявления функции.

//Raised compilation error
public static <T1, T2> T3 returnTypeGeneric(T1 val1, T2 val2) {
    return 0;
}

Правильно: компилирует fine

public static <T1, T2, T3> T3 returnTypeGeneric(T1 val1, T2 val2) {
    return 0;
}

Пример кода класса:

package generics.basics;

import java.util.ArrayList;
import java.util.List;

public class GenericMethods {

/*
 Declare the generic type parameter T in this method. 

 After the qualifiers public and static, you put <T> and 
 then followed it by return type, method name, and its parameters.

 Observe : type of val is 'T' and not '<T>'

 * */
//One type
public static <T> void fill(List <T> list, T val) {

    for(int i=0; i<list.size(); i++){
        list.set(i, val);
    }

}

// multiple types as parameters
public static <T1, T2> String multipleTypeArgument(T1 val1, T2 val2) {

    return val1+" "+val2;

}

/*// Q: To audience -> will this compile ? 
 * 
 * public static <T1, T2> T3 returnTypeGeneric(T1 val1, T2 val2) {

    return 0;

}*/

 public static <T1, T2, T3> T3 returnTypeGeneric(T1 val1, T2 val2) {

    return null;

}

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.add(10);
    list.add(20);
    System.out.println(list.toString());
    fill(list, 100);
    System.out.println(list.toString());

    List<String> Strlist = new ArrayList<>();
    Strlist.add("Chirag");
    Strlist.add("Nayak");
    System.out.println(Strlist.toString());
    fill(Strlist, "GOOD BOY");
    System.out.println(Strlist.toString());


    System.out.println(multipleTypeArgument("Chirag", 100));
    System.out.println(multipleTypeArgument(100,"Nayak"));

}

}

//определение класса завершается

Пример вывода:

[10, 20]
[100, 100]
[Chirag, Nayak]
[GOOD BOY, GOOD BOY]
Chirag 100
100 Nayak