0

Good Day.

I am pretty sure that this question has been asked before but I couldn't find it.

Basically, how does the below code work:

import java.util.ArrayList;

public class Main{
    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<Integer>();
        
        a.add(10);
        
        change(a);
        
        System.out.println(a.get(0));
    }
    
    static void change(ArrayList v){
        if(v.size() > 0){
            v.set(0, "Hello");
        }
    }
}

It compiles and also runs successfully, printing "Hello". How could Java replace Integer with String?

I also tried adding in Main:

        a.set(0, 1002);
        
        for(Integer c: a){
            System.out.print(c + " ");
        }
        System.out.println("");

Once again, very surprising. I thought that maybe somwhow a gets changed to ArrayList<String> but the set method works normally?

Can anyone please explain this to me? Is this undefined behaviour?

Thanks.

MangoPizza
  • 269
  • 2
  • 8
  • 7
    [What is a raw type and why shouldn't we use it?](https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it) – knittl Apr 21 '22 at 17:52
  • 1
    You could do it you you used `Object` as your list type `(e.g. new ArrayList` But lists of mixed types is not not a good idea and can lead to problems. – WJS Apr 21 '22 at 18:16
  • 1
    When you compiled this code, you would have got a warning. That warning was telling you this could happen. – Louis Wasserman Apr 21 '22 at 18:17
  • 1
    Java doesn't replace Integer with String. `System.out.println(a.get(0));`Is using [println(Object)](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/PrintStream.html#println(java.lang.Object)) So it doesn't need to cast the String to an Integer. If you tired `Integer b = v.get(0);` you'd get different results. – matt Apr 21 '22 at 18:57

1 Answers1

2

Generic types like the <Integer> in your ArrayList are a compile-time concept, this information is lost at runtime. This is known as "type erasure".

You just use ArrayList (without type parameter) in the change method, which means that the compiler will not check for a type, so it's possible to add a String to an Integer List. If you used ArrayList<Integer>, the compiler would complain.

Internally, ArrayList uses a simple array of objects that can hold any type.

Michel K
  • 411
  • 1
  • 7