2

I am new to generics, and I came across this experiment.

import java.util.List;
import java.util.ArrayList;
public class Main {
    private static void addIntegerToNames(List listOfNames, Integer i) {
        listOfNames.add(i);
    }
    public static void main(String[] args) {
        List<String> Names = new ArrayList<String>();
        Names.add("stackOverFlow");
        addIntegerToNames(Names, 100);
        System.out.println(Names);
    }
}

Output : [stackOverFlow, 100]

The compiler does not throw an error while adding an integer to listOfNames because it sees that listOfNames is a list of objects. When this goes at runtime, it still doesn't throw an error, My assumption is that at runtime, "Names" is a List of Objects, because generics are only implemented at compile time.

I have two follow up questions.

  1. Is my assumption correct?
  2. Why did java not implemented generics strictly both at compile time and runtime ? Does the current implementation of generics not make Java more error-prone? Was it a tradeoff between performance and safety?
  • 1
    1.you are correct; 2.for compatibility with previous code, rawtypes are allowed – 时间只会一直走 Mar 17 '23 at 05:25
  • Your assumption is mostly correct. As for *why* they did not implement something, [you should clarify what you mean by "why"](https://meta.stackoverflow.com/q/293815/5133585). – Sweeper Mar 17 '23 at 05:27
  • Add this line to the code: `char foo = Names.get(1).charAt (2);`. You should get a `ClassCastException`. When generics were added to Java (version 5, year 2004), how generics were implemented conflicted with how arrays were implemented. The result was, if an array was allowed to be generic, there would be a loophole that would allow an element of a different type to be put into the array. Accessing the element where the incorrect type was would result in a `ClassCastException`. To prevent this, it was forbidden to create a generic array. So, why is this loophole still allowed? – Old Dog Programmer Mar 17 '23 at 14:51

1 Answers1

2

Java allows adding an int to a List<String> due to the way generics are implemented in the language. Generics in Java are implemented through type erasure, which means that the type information is erased at runtime and not available for runtime checks.

In other words, at runtime, a List<String> and a List<Integer> are both just List objects. This allows for greater compatibility between different versions of Java that might have different types of List objects. However, it also means that the compiler can't always catch type errors at compile-time.

To address this issue, Java provides some level of type checking at compile-time through the use of bounded type parameters and wildcards. By specifying a type parameter with an upper bound, such as List<? extends Number>, you can restrict the types that can be added to the list. This helps catch errors at compile-time and prevents type errors at runtime.

However, it's worth noting that even with these restrictions, it's still possible to cast objects to different types in Java, which can lead to runtime errors. This is why it's important to always use generics and type checking whenever possible to avoid errors and ensure code correctness.

Harinder
  • 11,776
  • 16
  • 70
  • 126