Я пытаюсь реализовать граф с использованием универсальных шаблонов, и я хочу использовать общий аргумент как для узлов, так и для данных внутри узлов. Это сработает, если я сделаю это первым способом, но в идеале я бы хотел определить это вторым способом.
Почему не работает второй способ?
//OK
public class AdjacencyListGraph<E, N extends Node<E>> {
}
//Cannot resolve symbol E
public class AdjacencyListGraph<N extends Node<E>> {
}
Внутри N является параметром при добавлении узла и типом возвращаемого значения при запросе узлов, а E отображает узлы в хэш-карте и используется для запроса графа.




В контексте дженериков Java слово расширяет означает верхний граница, а не наследование. Значение этого слова перегружено в случае дженериков.
Обобщения были введены в java, чтобы дать разработчикам возможность писать более последовательный, чистый и менее ошибочный код, чем это было раньше. Все дело в разработке, а не в исполнении. В скомпилированном коде нет дженериков. Однако есть некоторая информация о фактических типах в метапространстве, которую вы можете получить через отражение, но это метаинформация, а не фактический код.
Во время компиляции общие типы стираются и заменяются фактическими границами (https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html). И вот основная причина вашей проблемы. Если предоставленная граница также является универсальной, компилятор не может выполнить стирание типа. Он просто не знает, каким типом он должен заменить общий в коде во время компиляции. Так вы получите ошибку компиляции.
//OK
public class AdjacencyListGraph<E, N extends Node<E>> {
}
В любом случае здесь вам нужно будет указать фактический тип E, и поэтому компилятор сможет разрешить фактическую привязку и выполнить стирание типа.
//Cannot resolve symbol E
public class AdjacencyListGraph<N extends Node<E>> {
}
В этом случае ваша привязка также становится общей. Компилятор не знает фактического типа. Это может быть любой тип. Таким образом, он не может выполнить стирание типа здесь и выдает ошибку компиляции.
Также вот несколько полезных ресурсов о дженериках: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.htmlhttps://docs.oracle.com/javase/tutorial/java/generics/index.html
Первый действительно отличный. Вот информация о слове extends и его значении в контексте обобщения: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Does%20extends%20always%20mean%20inheritance?
Спасибо за прекрасное объяснение. Может ли это быть реализовано в будущем как часть дженериков или это более сложно, чем я предполагаю?
Как вы хотите использовать параметры типа в методах?