Java泛型方法从返回类型获取类

huangapple go评论87阅读模式
英文:

Java Generic Methods get Class from Returntype

问题

我想创建一个映射器,它读取两个实体类的规范中的各个变量,并将各种数据类型(带内容)传递给一个转换器,然后在各种条件下返回数据。
我的问题是,我还没有完全熟悉Java泛型,因此需要帮助来确定以最佳方式/标准化方式确定返回类型。

据我所了解,我必须定义一个泛型类或将类传递给泛型方法,这应该是正确的,对吗?因为我之前已经尝试过在不传递类作为参数的情况下定义泛型方法,并且不能从中确定类型在Java中不应该起作用。

你能否给我展示一个示例,如果有一个泛型类可用,泛型方法如何确定返回类型?

public abstract class Converter {
    public static <TInto, TFrom> TInto convertDataTypes(TFrom from) {
        TInto into = null;
        // TODO: 初始化 into;
        // TODO: 获取 into 类
        return into;
    }
}

我还尝试了使用简单的 'Type',因为 ParameterizedType 抛出异常,但是 'getActualTypeArguments' 不起作用,或者我仍然没有获得想要的正确类型(Boolean)...

我还没有完全理解的是,即使我指定了泛型类型,当我调用泛型方法时,它仍然不识别我附加到方法的内容。
示例的函数调用如下:

Boolean b = Converter.<Boolean, String>convertDataTypes("true");
英文:

I would like to create a mapper that reads the individual variables with the specification of two entity classes and passes the various data types (with content) to a converter, which then returns the data under various conditions.
My problem is that I am not yet 100% familiar with Java Generics and therefore need help how to determine the return types in the best possible/standardized way.

As far as I found out, I have to define a generic class or pass the class to the generic method, that should be correct, right? Because I had already tried to define a generic method without passing the class as a parameter and to determine the type from this is not supposed to work in Java.

Could you maybe show me an example, how a generic method determines the return type, if a generic class is available?

public abstract class Converter{
    public static &lt;TInto, TFrom&gt; TInto convertDataTypes(TFrom from){
        TInto into = null;
        /* My Try 
        Class&lt;?&gt; intoClass = (Class&lt;?&gt;) ((java.lang.reflect.ParameterizedType Converter.class.getDeclaredMethods()[0]
                .getGenericReturnType()).getActualTypeArguments()[0];

        into = (TInto) intoClass.getDeclaredConstructor().newInstance();
        */
        // TODO: init into;
        // TODO: get into class
        return into;
    }
}

I also tried with the simple 'Type', because ParameterizedType throws an exception, but then 'getActualTypeArguments' doesn't work, or I still don't get the correct type (Boolean) that I want...

What I also didn't quite understand is why even if I specify the generic types, so when I call the generic method it doesn't recognize what I attach to the method.
Function call simply as Example:

Boolean b = Converter.&lt;Boolean,String&gt;convertDataTypes(&quot;true&quot;);

答案1

得分: 1

是的,Java的类型擦除使得在运行时无法推断泛型类型,除非明确传递类信息。更正式地说:

由于类型擦除,泛型类型信息在运行时不会保留,它会移除所有泛型类型信息,用它们的边界或者用Object替代,如果类型参数没有边界的话。

因此,处理这个问题的典型方式是确实将所需返回类型的Class对象传递给方法,让我们尝试为String->Integer创建一些内容,例如:

abstract class Converter {

    public static <TInto, TFrom> TInto convertDataTypes(TFrom from, Class<TInto> intoClass) {
        TInto into = null;

        if (intoClass == String.class && from instanceof Integer) {
            into = intoClass.cast(Integer.toString((Integer) from));
        } else if (intoClass == Integer.class && from instanceof String) {
            into = intoClass.cast(Integer.parseInt((String) from));
        }
        // 可能会有更多的转换器,根据给定的类型

        return into;
    }
}

用法:

Integer i = Converter.convertDataTypes("41", Integer.class);
String s = Converter.convertDataTypes(41, String.class);
英文:

Yes, Java's type erasure makes it impossible to infer the generic type at runtime without explicitly passing the class. More formal:
> the generic type information is not retained at runtime due to type erasure, which removes all generic type information, replacing it with their bounds or with Object if the type parameters are unbounded.

So the typical way to handle this problem is indeed to pass the Class object of the desired return type to the method, let's try to create something for String->Integer for example:

abstract class Converter {

    public static &lt;TInto, TFrom&gt; TInto convertDataTypes(TFrom from, Class&lt;TInto&gt; intoClass) {
        TInto into = null;

        if (intoClass == String.class &amp;&amp; from instanceof Integer) {
            into = intoClass.cast(Integer.toString((Integer) from));
        } else if (intoClass == Integer.class &amp;&amp; from instanceof String) {
            into = intoClass.cast(Integer.parseInt((String) from));
        }
        // maybe you&#39;ll have more converters here, depending on the given types

        return into;
    }
}

Usage:

Integer i = Converter.convertDataTypes(&quot;41&quot;, Integer.class);
String s = Converter.convertDataTypes(41, String.class);

huangapple
  • 本文由 发表于 2023年7月13日 00:04:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76672503.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定