[Java] To know the type information of type parameters at runtime

0. Conclusion first

--Class inheritance with type parameter T --The actual type of T can be obtained by giving the constructor a T-type variadic argument.


1. Challenges

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!


2. Target audience

--People who have used the Class class in java --People who are interested in type parameters


3. Bad example


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.
    }
}

3.1 T.class is not possible

class ParamGetter
{
    Class paramClass;
    <T> ParamGetter(List<T> list)
    {
        this.paramClass = T.class;
        //× This is NG
    }
    Class get(){return paramClass;}
}

3.2 Reflection fails [1]

//(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.


3.3 Failed to array with 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.

--You can do ʻInteger [] from List but not Number [] ` --In some cases, the number of elements is 0 -->

4. Root cause

Type information disappears at the stage of passing to the method


3.3 first passes a ʻArrayList type actual argument to theList type dummy argument. Next, it is converted to aT 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]


5. Solution

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


5.1 Replace type parameter with argument

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;
    }
}


6 (Bonus) Enables 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;
    }
}

reference

[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

[Java] To know the type information of type parameters at runtime
Output of the book "Introduction to Java"
[Java] Be careful of the key type of Map
[Java] How to get the authority of the folder
Java Welcome to the Swamp of 2D Arrays
[Java] How to get the URL of the transition source
How to write Scala from the perspective of Java
[Java] How to get the maximum value of HashMap
I want to know the answer of the rock-paper-scissors app
GetXxxx of ResultSet was addicted to primitive type (Java)
[Rails] How to get the contents of strong parameters
Java: Use Stream to sort the contents of the collection
I tried to summarize the basics of kotlin and java
Get to the abbreviations from 5 examples of iterating Java lists
20190803_Java & k8s on Azure The story of going to the festival
Command to check the number and status of Java threads
How to get the longest information from Twitter as of 12/12/2016
How to derive the last day of the month in Java
The story of pushing Java to Heroku using the BitBucket pipeline
Be sure to compare the result of Java compareTo with 0
Reintroduction to Java for Humanities 0: Understanding the Act of Programming
Whether to make the server side at the time of system rebuild with Kotlin or Java
Input to the Java console
Know the convenience of Docker (-compose) now (information list that I referred to when using it)
[Java] Various summaries attached to the heads of classes and members
Examine the system information of AWS Lambda operating environment in Java
A solution to the problem of blank spaces at the beginning of textarea
I want to understand the flow of Spring processing request parameters
Java Converts disparate character codes to the same character code at once
I tried the input / output type of Java Lambda ~ Map edition ~
Want to know what Ruby n is the power of 2? (Power judgment of 2)
The milliseconds to set in /lib/calendars.properties of Java jre is UTC
From fledgling Java (3 years) to Node.js (4 years). And the impression of returning to Java
I tried to summarize the methods of Java String and StringBuilder
[Java] How to convert from String to Path type and get the path
How to check for the contents of a java fixed-length string
How to get the length of an audio file in java
How to increment the value of Map in one line in Java
[Java] Delete the elements of List
[java8] To understand the Stream API
Compile Java at the command prompt
[Java version] The story of serialization
[Java] Runtime Data Areas of JVM
Welcome to the Java Library Swamp! !!
[Java] Correct comparison of String type
The road from JavaScript to Java
The origin of Java lambda expressions
How to use Java enum type
java regular expression-no loss to know-
[Java] How to retrieve the parameters passed from html on the server side
The story of forgetting to close a file in Java and failing
[Java Servlet] The road of Senri is also one step to the first
I want to know the JSP of the open portlet when developing Liferay
Get the type of an array element to determine if it is an array
How to find out the Java version of a compiled class file
Reason to add L to the number to be put in Java long type
[Java] How to get to the front of a specific string using the String class
How to find the total number of pages when paging in Java
How to change the value of a variable at a breakpoint in intelliJ
How to get the absolute path of a directory running in Java
[Java improvement case] How to reach the limit of self-study and beyond