Hi I'm new to Java so this question might be ridiculous though, I wonder how to get actual type in Java.
I mean, let's say there's a code block as belows:
List<String> foo_list = new ArrayList<>();
ArrayList<String> foo_arrayList = new ArrayList<>();
then foo_list.getClass()
and foo_arrayList.getClass()
both would return "java.util.ArrayList" right?
but if I try to pass foo_list into a function that expects ArrayList<String>
as a argument, it causes compile time error like follows:
java: method X in class Y cannot be applied to given types;
required: java.util.ArrayList<java.lang.String>
found: java.util.List<java.lang.String>
reason: actual argument java.util.List<java.lang.String> cannot be converted to java.util.ArrayList<java.lang.String> by method invocation conversion
so even though that foo_list.getClass()
returns "java.util.ArrayList", I guess(from the error log) its actual type is "java.util.List<java.lang.String>".. (I might guess wrong)
how can I get the "java.util.List<java.lang.String>" with foo_list
?
thanks.
CodePudding user response:
You seem to be confusing compile-time type with runtime type. At compile time, your foo_list
is indeed a List<String>
because that's how you declared it. The only way to check its compile-time type is to look at your code. Check the place where you declare the variable, and you'll see what its type is.
At runtime, your foo_list
is an ArrayList
. (Not an ArrayList<String>
because the parameter <String>
is lost due to type erasure. By the way, type erasure happens only at runtime. There is no type erasure at compile time.)
CodePudding user response:
The best practice here is to have the interface as a parameter to the method, not the implementation. In your particular case, if the method takes List instead of ArrayList, everything will work. Not only that, you will be able to shove other List interface implementations into this method as well - which is cool.
CodePudding user response:
This is very basic casting. You don't need to even use Generics.
List<String> foo_list = new ArrayList<>();
ArrayList<String> foo_list2 = (ArrayList<String>)foo_list;
Now you can call your method with foo_list2
.
You could do the same thing with an Object.
Object a = "a string";
String s = (String)a;
A method public void check(String i)
would accept s
but there would be a compile time error if you tried to call check(a)
.