Dlaczego lista <type> absorbuje element nietypowy w czasie kompilacji i wykonywania?

Mam to demo, którego nie potrzebuję konkretnego rozwiązania z przerysowaną architekturą, ale samo zrozumienie, dlaczego tak się zachowuje, i wszystkiego, czego mi brakuje, aby tego uniknąć. Zastanawiam się, dlaczego:

Kompilator pozwala na wstawienie elementu, który nie jest typem listy na liście

Wyjątek ClassCast jest generowany, gdy próbujemy pobrać element zamiast go pchać

import Test.*; //Inner classes
import java.util.List;
import java.util.ArrayList;

public class Test<E extends Object> {

    private List<E> list = new ArrayList<E>();
    public Test() {}

    public static void main(String[] args) {
        Test<String> a = new Test<String>();
        a.addElement(new String());
        a.addElement(new Integer(0)); // No complain in comp/run-time, I dont understand why CastException is not thrown here
        String class1 = a.getElement(0); 
        String class2 = a.getElement(1); //No complain in comp but ClassCastException: Integer cannot be cast to String
        //Integer class3 = a.getElement(1); //Compilation error
    }

    public void addElement (Object node) { list.add((E) node); } //No complain in comp/run-time
    public E getElement(int index)       { return list.get(index); }
}

Co może być rozwiązaniem? Zwróć uwagę na linię addElement, w której muszę przekazać SuperClass, zamiast typu E. Jest to potrzebne dla mojej architektury, to jest po prostu prosta próbna demonstracja. Ale i tak casting do typu E powinien działać zgodnie z oczekiwaniami i rzucać CastException w czasie wykonywania, nie powinien?

questionAnswers(2)

yourAnswerToTheQuestion