--Class inheritance with type parameter T --The actual type of T can be obtained by giving the constructor a T-type variadic argument.
The type of the elements of the array can be found later with ʻarray.getClass (). GetComponentType ()`, It's difficult to do the same with Lists such as ArrayList and LinkedList!
--People who have used the Class
class in java
--People who are interested in type parameters
Preparation
class Hoge
{
public static void main(String[] args)
{
ArrayList<Number> inteList = new ArrayList<>();
System.out.println(new ParamGetter(inteList).get());
//Get of ParamGetter class()In the method
//I want to display "Number" etc.
}
}
class ParamGetter
{
Class paramClass;
<T> ParamGetter(List<T> list)
{
this.paramClass = T.class;
//× This is NG
}
Class get(){return paramClass;}
}
//(For those who have reflected)
class ParamGetter
{
Type paramType;
<T> ParamGetter(List<T> list)
{
this.paramType = ((ParameterizedType)new ArrayList<T>(){}.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
Type get(){return paramType;}
}
Result: "T" is displayed
The same applies to the method [2] using the getGenericType ()
method of the Field
class.
toArray ()
class ParamGetter
{
Object array;
<T>ParamGetter(List<T> list)
{
this.array = (T[])list.toArray();
//☆System.out.println((T[])list.toArray());
}
Type get() throws NoSuchFieldException, SecurityException
{
return this.array.getClass().getComponentType();
}
}
Result (main): "class java.lang.Object" is displayed.
Serpentine The idea of "taking an element from a List and examining its type" might be possible, but it's actually inappropriate.
from
List but not
Number [] `
--In some cases, the number of elements is 0
-->Type information disappears at the stage of passing to the method
3.3 first passes a ʻArrayList type actual argument to the
List type dummy argument. Next, it is converted to a
T type array and stored in a ʻObject
type field.
Then, when get ()
is called, it finds the "runtime type" (array type) and checks the type of the elements in that array.
The result is ʻObject, You end up with
T = ʻObject
instead of T
= Number
.
In fact, when you run the ☆ code, you'll see that it's of type ʻObject []. → After all
T []= ʻObject []
System.out.println((T[])list.toArray());//Object[]It comes out with a mold.
From this, it can be seen that "the type parameter information has disappeared while being passed as an argument". Actually erased at compile time (becomes the most abstract type that can be received) [3]
What disappears at runtime cannot be removed even by reflection (reflection is a technology at runtime [4]) →
--When calling, write in a place that does not disappear --Give the class itself a type parameter and use it in the constructor
class Hoge<T> | Fuga survival | Fuga as |
---|---|---|
new Hoge(); | × | Type parameters of instance methods |
new Hoge<Fuga>(); | 〇 | Type parameters of the class[5] |
new Hoge(Fuga.class) | △ | Class type argument |
△ ・ ・ ・ It is not impossible, but it will be redundant.
5.2 ArrayList<T>
→ ArrayList_<T>
Thing you want to do:
new ArrayList_ <Number> (Object ...);
new ArrayList <Number> (Object ...);
and
Make it have almost the same meaning
And make Number
available at runtime
Has almost the same meaning → Realizable by inheritance Write with reference to Mr. saka1029's comment in this article
public class ArrayList_<T> extends ArrayList<T> {
public final Class<?> clazz;
public ArrayList_(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException(
"Do not specify dummy argument");
clazz = dummy.getClass().getComponentType();
}
public Class getComponentClass() {
return clazz;
}
}
new Hoge <t.getClass ()>
Instances of the generic type Hoge <T>
cannot be created from variables of type Class <T>
.
In short, new Hoge <t.getClass ()>
cannot be done.
If you write it in the method, it is possible to some extent as new Hoge <?>
,
Hoge<t.getClass()>.getClass().getDeclaredConstructor().newInstance()
It is not possible to create a generics type instance anywhere.
If you want to do this, you can pass a Class <?>
Type variable as an argument.
public class ArrayList_<T> extends ArrayList<T> {
public final Class<?> clazz;
public ArrayList_(T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException(
"Do not specify dummy argument");
clazz = dummy.getClass().getComponentType();
}
public ArrayList_(Class<T> clazz)//Add this
{
this.clazz = clazz;
}
public Class getComponentClass() {
return clazz;
}
}
[1]http://unageanu.hatenablog.com/entry/20071105/1194264963 [2]https://codeday.me/jp/qa/20181216/16785.html [3]https://qiita.com/pebblip/items/1206f866980f2ff91e77 The "most abstract type that can be received" in the text means the "upper boundary" in [3]. [4]https://java.keicode.com/lang/reflection.php [5] Pointed out by Mr. saka1029 in this article Others: https://java-beginner.com/thread-thread-and-runnable/
Recommended Posts