Metoda ma takie samo kasowanie jak inna metoda w typie

Dlaczego nie jest legalne posiadanie tych dwóch metod w tej samej klasie?

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

I get the compilation error

Metoda add (Set) ma takie samo kasowanie add (Set) jak inna metoda W teście typu.

Chociaż mogę to obejść, zastanawiałem się, dlaczego javac tego nie lubi.

Widzę, że w wielu przypadkach logika tych dwóch metod byłaby bardzo podobna i mogłaby zostać zastąpiona przez jedną

public void add(Set<?> set){}

} metoda, ale nie zawsze jest to case.

To jest bardzo irytujące, jeśli chcesz mieć dwa constructors, które biorą te argumenty, ponieważ wtedy nie możesz po prostu zmienić nazwy jednego z constructors.

 300
Author: Mithun, 2010-01-04

6 answers

Ta reguła ma na celu uniknięcie konfliktów w kodzie starszym, który nadal używa typów surowych.

Oto ilustracja, dlaczego nie było to dozwolone, zaczerpnięta z JLS. Załóżmy, że zanim generyki zostały wprowadzone do Javy, napisałem taki kod:

class CollectionConverter {
  List toList(Collection c) {...}
}

Przedłużasz moją klasę, o tak:

class Overrider extends CollectionConverter{
  List toList(Collection c) {...}
}

Po wprowadzeniu leków generycznych, postanowiłem zaktualizować swoją bibliotekę.

class CollectionConverter {
  <T> List<T> toList(Collection<T> c) {...}
}
Nie jesteś gotowy na aktualizacje, więc zostaw klasę w spokoju. W aby poprawnie nadpisać metodę toList(), projektanci języka zdecydowali, że surowy typ jest "równoważny" do dowolnego typu uogólnionego. Oznacza to, że chociaż podpis metody nie jest już formalnie równy podpisowi mojej klasy nadrzędnej, to metoda nadal jest nadpisywana.

Teraz, czas mija, a Ty decydujesz, że jesteś gotowy, aby zaktualizować klasę. Ale trochę schrzanisz i zamiast edytować istniejącą, surową metodę toList(), dodajesz nową metodę, taką jak to:

class Overrider extends CollectionConverter {
  @Override
  List toList(Collection c) {...}
  @Override
  <T> List<T> toList(Collection<T> c) {...}
}

Ze względu na równoważność nadpisywania typów surowych, obie metody są w poprawnej formie, aby nadpisać metodę toList(Collection<T>). Ale oczywiście kompilator musi rozwiązać jedną metodę. Aby wyeliminować tę dwuznaczność, klasy nie mogą mieć wielu metod, które są równoważne-to znaczy wiele metod z tymi samymi typami parametrów po usunięciu.

Kluczem jest to, że jest to reguła języka zaprojektowana w celu zachowania zgodności ze starym kodem używającym typów surowych. Informatyka nie jest ograniczeniem wymaganym przez usunięcie parametrów typu; ponieważ rozdzielczość metody występuje w czasie kompilacji, dodanie typów generycznych do identyfikatora metody byłoby wystarczające.

 303
Author: erickson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-12 23:21:04

Java generics używa typu erasure. Bit w nawiasach kątowych (<Integer> i <String>) zostanie usunięty, więc skończysz z dwiema metodami, które mają identyczny podpis (add(Set) widzisz w błędzie). Nie jest to dozwolone, ponieważ środowisko uruchomieniowe nie wie, którego użyć dla każdego przypadku.

Jeśli Java kiedykolwiek dostanie reified generics, to możesz to zrobić, ale teraz jest to prawdopodobnie mało prawdopodobne.

 98
Author: GaryF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-04 10:02:03

Dzieje się tak dlatego, że Generyki Javy są zaimplementowane z typu Erasure .

twoje metody zostaną przetłumaczone, w czasie kompilacji, na coś w stylu:

Rozdzielczość metody występuje w czasie kompilacji i nie uwzględnia parametrów typu. (zobacz odpowiedź Ericksona )

void add(Set ii);
void add(Set ss);

Obie metody mają ten sam podpis bez parametrów typu, stąd błąd.

 38
Author: bruno conde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:53

Problem polega na tym, że Set<Integer> i Set<String> są faktycznie traktowane jako Set z JVM. Wybór typu zbioru (w Twoim przypadku String lub Integer) jest tylko cukrem składniowym używanym przez kompilator. JVM nie rozróżnia Set<String> i Set<Integer>.

 16
Author: kgiannakakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-04 10:05:09

Możliwe jest, że kompilator tłumaczy Set (Integer) na Set(Object) w kodzie bajtowym Javy. W takim przypadku Set (Integer)będzie używany tylko w fazie kompilacji do sprawdzania składni.

 3
Author: rossoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-04 10:02:47

Zdefiniuj pojedynczą metodę bez Typu Jak void add(Set ii){}

Możesz podać typ podczas wywoływania metody w oparciu o swój wybór. Będzie działać dla każdego typu zestawu.

 2
Author: Idrees Ashraf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-16 07:54:02