泛型:创建参数化类参数

发布于 2024-12-07 04:48:44 字数 1408 浏览 1 评论 0原文

如何获取参数化的 Class 对象作为方法参数?

class A<T>
{
    public A(Class<T> c)
    {
    }

    void main()
    {
        A<String> a1 = new A<String>(String.class);     // OK
        A<List<String>> a2 = new A<List<String>>(List<String>.class);  // error
        A<List<String>> a3 = new A<List<String>>(Class<List<String>>);  // error
    }
}

你可能会问,我为什么要这么做?我有一个参数化类,其类型是另一个参数化类,并且其构造函数需要其他类类型作为参数。我知道运行时类没有关于其类型参数的信息,但这不应阻止我在编译时执行此操作。看来我应该能够指定一个类型,例如 List.class。还有其他语法可以做到这一点吗?

这是我的真实用例:

public class Bunch<B>
{
    Class<B> type;

    public Bunch(Class<B> type)
    {
        this.type = type;
    }

    public static class MyBunch<M> extends Bunch<List<M>>
    {
        Class<M> individualType;

        // This constructor has redundant information.
        public MyBunch(Class<M> individualType, Class<List<M>> listType)
        {
            super(listType);
            this.individualType = individualType;
        }

        // I would prefer this constructor.
        public MyBunch(Class<M> individualType)
        {
            super( /* What do I put here? */ );
            this.individualType = individualType;
        }
    }
}

这可能吗?

How does one get a parameterized Class object to be used as a method argument?

class A<T>
{
    public A(Class<T> c)
    {
    }

    void main()
    {
        A<String> a1 = new A<String>(String.class);     // OK
        A<List<String>> a2 = new A<List<String>>(List<String>.class);  // error
        A<List<String>> a3 = new A<List<String>>(Class<List<String>>);  // error
    }
}

Why do I want to do that, you may ask? I have a parameterized class whose type is another parameterized class, and whose constructor requires that other class type as an argument. I understand that runtime classes have no information on their type parameters, but that shouldn't prevent me from doing this at compile time. It seems that I should be able to specify a type such as List<String>.class. Is there another syntax to do this?

Here is my real usage case:

public class Bunch<B>
{
    Class<B> type;

    public Bunch(Class<B> type)
    {
        this.type = type;
    }

    public static class MyBunch<M> extends Bunch<List<M>>
    {
        Class<M> individualType;

        // This constructor has redundant information.
        public MyBunch(Class<M> individualType, Class<List<M>> listType)
        {
            super(listType);
            this.individualType = individualType;
        }

        // I would prefer this constructor.
        public MyBunch(Class<M> individualType)
        {
            super( /* What do I put here? */ );
            this.individualType = individualType;
        }
    }
}

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

等风来 2024-12-14 04:48:44

直接投怎么样?

super((Class<List<M>>)List.class);

类文字不会有您想要的类型参数。

How about just cast?

super((Class<List<M>>)List.class);

Class literals are not going to have the type parameters that you want.

娇女薄笑 2024-12-14 04:48:44

请记住,您不会在运行时获得作为类的 List,正确的方法可能是使用 TypeToken,正如 BalusC 告诉您的那样。如果没有 TypeToken,您无法转换为 List,但您可以创建如下内容:

public static class MyBunch2<List_M extends List<M>, M> extends Bunch<List_M>
{
    Class<M> individualType;

    @SuppressWarnings("unchecked")
        public MyBunch2(Class<M> individualType)
    {
        super((Class<List_M>) List.class);
        this.individualType = individualType;
    }
}

由于 List_M extends List 这并不像您希望的那样类型安全,但也许已经足够好了。创建实例会像编写一样丑陋,

MyBunch2<List<String>, String> a = new MyBunch2<List<String>, String>(String.class);

但是您可以使用工厂方法改进它

public static <M2> MyBunch2<List<M2>, M2> of(Class<M2> individualType){
    return new MyBunch2<List<M2>, M2>(individualType);
}

,然后编写

MyBunch2<List<String>, String> b = MyBunch2.of(String.class);

如果您使用的是 eclipse,代码辅助将帮助您编写丑陋的类 MyBunch2, String>;

当然,在运行时,this.type将是java.util.List,而不是java.util.List
为了得到正确的结果,请选择 TypeToken。

---继续---

您甚至可以创建另一个类

public static class MyBunch3<M> extends MyBunch2<List<M>, M>
{
        public MyBunch3(Class<M> individualType) {
            super(individualType);
        }
}

,然后创建实例,因为

MyBunch3<String> c = new MyBunch3<String>(String.class);

必须有一种方法可以在一个类中做到这一点......但我无法弄清楚

Remember you will NOT get a List as a class in runtime, and the right approach would probably be using TypeToken as BalusC told you. Without TypeToken, you can't cast to List, but you can create something like this:

public static class MyBunch2<List_M extends List<M>, M> extends Bunch<List_M>
{
    Class<M> individualType;

    @SuppressWarnings("unchecked")
        public MyBunch2(Class<M> individualType)
    {
        super((Class<List_M>) List.class);
        this.individualType = individualType;
    }
}

Since List_M extends List<M> this is not as typesafe as you may wish, but maybe is nice enough. Creating an instance will be as ugly as writing

MyBunch2<List<String>, String> a = new MyBunch2<List<String>, String>(String.class);

but you can improve it with a factory method

public static <M2> MyBunch2<List<M2>, M2> of(Class<M2> individualType){
    return new MyBunch2<List<M2>, M2>(individualType);
}

and then write

MyBunch2<List<String>, String> b = MyBunch2.of(String.class);

If you are using eclipse, code assist will help you writing the ugly class MyBunch2, String>

Of course, in runtime, this.type will be java.util.List, not java.util.List
To get it right, go for TypeToken.

---Continuation---

You can even make another class

public static class MyBunch3<M> extends MyBunch2<List<M>, M>
{
        public MyBunch3(Class<M> individualType) {
            super(individualType);
        }
}

And then create instances as

MyBunch3<String> c = new MyBunch3<String>(String.class);

There must be a way to do that in just one class...but I can't figure it out

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文