In the context of java generics the word extends means the upper bound, not the inheritance. The meaning of that word is overloaded in case of generics.
Generics were introduced in java to give developers the ability to write more consistent, clean and less buggy code then it was before. It's all about the development, not the execution. There are no generics in the compiled code. However there is some information about actual types in metaspace which you can retrieve via reflection, but it's meta information, not the actual code.
During the compilation generic types are erased and replaced by actual bounds (https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html). And here is the root cause of your problem. If a provided bound is also generic then compiler is unable to perform type erasure. It simply dont know by which type it should replace the generic one in the code during compilation. So you will get compilation error.
//OK
public class AdjacencyListGraph<E, N extends Node<E>> {
}
Here anyway you will have to provide actual type E and so the compiler will be able to resolve the actual bound and perform type erasure.
//Cannot resolve symbol E
public class AdjacencyListGraph<N extends Node<E>> {
}
In this case your bound also becomes generic. The compiler do not know the actual type. It can be any type. So it cant perform type erasure here and gives you a compilation error.
Also here are some useful resources about generics:
http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
https://docs.oracle.com/javase/tutorial/java/generics/index.html
The first one is really great. Here is info about extends word and it's meaning in the generics context: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Does%20extends%20always%20mean%20inheritance?