泛型多类型

4

将方法定义为

myMethod(Object... obj){}

允许使用任意数量和类型的参数。

我希望使用泛型来严格定义参数的数量和类型。

例如,假设上面提到的myMethod(Object ...)是一个名为MyClass的类中的方法,并且可以通过默认构造函数实例化MyClass

我需要以类似于以下方式定义实例:

MyClass<Integer, Integer, String> instance1 = new MyClass<Integer, Integer, String>();
MyClass<String, String, Integer, Integer> instance2 = new MyClass<String, String, Integer, Integer>();

因此,上述类型定义将设置对 myMethod() 调用所允许的参数数量和类型:

instance1.myMethod(1, 2, "test");
instance2.myMethod("one", "two", 1, 2);

问题是:如何定义MyClass,以便允许任意数量的类型参数?
将不胜感激地接受任何建议。

myMethod() 中,您会如何处理这些参数? - harto
目的是装饰一个 <code>java.sql.PreparedStatement</code> 实现,使得所装饰类的实例将包含 SQL 查询所需参数的定义。 - Joel Shemtov
用另一个刚好具有相同参数类型的准备语句来替换一个准备好的语句可能并不实用。更好的做法是选择具有某些定义目的和含义的更强类型接口。 - Tom Hawtin - tackline
6个回答

4
您无法更改每个类的类型参数数量,但您可以进行一些巧妙的操作。
class Tuple
{ 
    Object[] objects() { return ...; }
}
class Tuple1 ...
class Tuple2 ...
class Tuple3<T1,T2,T3> extends Tuple
{
    static public<S1,S2,S3> Tuple3<S1,S2,S3> of(S1 o1, S2 o2, S3 o3){ return ...; }
}
class Tuple4<T1,T2,T3,T4> extends Tuple
{
    static public<S1,S2,S3,S4> Tuple4<S1,S2,S3,S4> of(S1 o1, S2 o2, S3 o3, S4 o4){ return ... ; }
}
...
class Tuple9 ...

class MyClass<TupleN extends Tuple>
{
    void myMethod(TupleN ntuple)
    {
        Object[] objects = ntuple.objects();
        // work on objects
    }
}

MyClass<Tuple3<Integer,Integer,String>> instance3 = new MyClass<Tuple3<Integer, Integer, String>>();
instance3.myMethod( Tuple3.of(1,2,"test") );

这不值得。有时为了简单起见,你必须放弃外部类型检查。


现在我有点喜欢这个元组的想法,都是你的错!of 方法可以全部移动到 Tuple 类中,以便编写 Tuple.of(1,2,"test") - irreputable
到目前为止,这似乎是最好的选择,我会考虑使用它。如果我使用它,我会接受这个答案。目的是什么?!我有一个有用(我认为)的java.sql.PreparedStatement装饰器,可以按以下方式使用:aPreparedStatement.executeUpdate(param1, param2, param3);我希望传递给此方法的参数受实例声明的约束,类似于泛型类型所做的。 - Joel Shemtov
为什么要声明一个类型安全的实例stmtBlah,而不是声明一个老式的方法,当然是类型安全的,updateBlah(Integer,Integer,String) - irreputable

3

这有什么意义吗?我无法想象出一个场景,它会是最好的解决方案。我不是贬低你,但值得一提的是,你应该遵循KISS原则。听起来你正陷入过度设计的困境,这会导致代码味道难闻。

可能有用的另一种设计模式是构造器模式。维基页面上的示例并不是很好,但你应该阅读Effective Java关于构造器的部分。通过链接修改器方法并通过构造器方法调用私有构造器,构造器可以帮助创建由必需和/或可选参数构造的不可变对象:

public class MyClass {

    private final String string1;
    private final String string2;
    private final int int1;
    private final int int2;

    private MyClass(Builder builder) {
        this.string1 = builder.string1;
        this.string2 = builder.string2;
        this.int1 = builder.int1;
        this.int2 = builder.int2;
    }

    public String getString1() {
        return string1;
    }

    public String getString2() {
        return string2;
    }

    public int getInt1() {
        return int1;
    }

    public int getInt2() {
        return int2;
    }

    public static class Builder {
        private String string1;
        private String string2;
        private int int1;
        private int int2;

        // set required parameters in the constructor
        public Builder() { }

        public Builder string1(String string1) {
            this.string1 = string1;
            return this;
        }

        public Builder string2(String string2) {
            this.string2 = string2;
            return this;
        }

        public Builder int1(int int1) {
            this.int1 = int1;
            return this;
        }

        public Builder int2(int int2) {
            this.int2 = int2;
            return this;
        }

        public MyClass build() {
            return new MyClass(this);
        }
    }
}

您可以按照以下方式构建一个对象:
MyClass myClass = new MyClass.Builder().string1("sample1").string2("sample2").int1(1).int2(2).build();

或者(使用相同的类)

MyClass myClass = new MyClass.Builder().string1("sample1").int1(1).build();

这些方法名很糟糕,但我根据您的假设情景进行翻译。


3

我认为你试图做的事情是无法实现的,但或许你可以介绍一下myMethod()的作用?


3

当你有3或4个参数时,调用站点非常丑陋,MyClass <X <Integer,X <Integer,X <String,END>>>> instance3instance3.call(x(1,x(2,x(“test”,END))))。我更喜欢我的元组想法。 - irreputable
预留已经就位,但我仍然认为这绝非坏主意!我会考虑使用它。当我们谈论准备好的语句时,可能会有许多参数,而简单性在这里是一个考虑因素。 - Joel Shemtov

0
你可以尝试这样做:
类类型:MyClass <List<?>>

这也是我的第一反应,但它不允许类型安全的异构列表元素——这最终是问题的关键。 - Andrzej Doyle

0

你必须满足于使用myMethod(Object...)。在运行时,MyClass的实例甚至不知道参数类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接