Java 如何实现参数数目未知的方法?

Java 如何实现参数数目未知的方法?,java,interface,java-8,variadic-functions,Java,Interface,Java 8,Variadic Functions,我有1个接口和3个类。我希望这个类能够同时实现需要transform方法的接口。此方法必须存在,但每个类不能超过一个。我不知道这个类使用了多少个参数 例如: public interface A{ public void transform(Object ... args); } public class B implements A{ public void transform(String a){ System.out.println(a); } }

我有1个接口和3个类。我希望这个类能够同时实现需要
transform
方法的接口。此方法必须存在,但每个类不能超过一个。我不知道这个类使用了多少个参数

例如:

public interface A{
    public void transform(Object ... args);
}

public class B implements A{
    public void transform(String a){
        System.out.println(a);
    }
}

public class C implements A{
    public void transform(Integer a, Character b){
        System.out.println(a+b);
    }
}

// super generic case if possible with Objects + primitive
public class D implements A{
    public void transform(int a, String b){
        System.out.println(a+b);
    }
}
这不管用。但我希望你明白了。在java中这样做可能吗?我应该如何用一般的方式称呼他们?假设我有其他方法,如:

void callTransf(A a, Object ... objs){
    Method m = a.getClass().getMethods()[0];
    m.invoke(a, objs)
}

一个可行的解决方案是将接口声明为通用接口:

public interface Transformation<S, R> {
    R transform(S source);
}
在此基础上,您声明转换如下:

public final class TransformationA implements Transformation<TransformationSourceForA, TransformationResultForA> {
    @Override
    public TransformationResultForA transform(TransformationSourceForA source) { ... }
}
公共最终类转换A实现转换{
@凌驾
公共TransformationResultForA transform(TransformationSourceForA source){…}
}

原则是将不同字段的需求委托给一个类,而不是方法的参数。

您所要求的是不可能的。 若接口方法使用Varargs,那个么其他方法也必须使用Varargs。所以一个解决方案是让两个类都使用这个接口。以下是总体思路:

public interface A{
    public void transform(char ... args);
}

public class B implements A{
    public void transform(char ... args){
        String s = "";
        for(char c : args){
        s += c;
        }
        System.out.println(s);
    }
}

public class C implements A{
    public void transform(char ... args){
        System.out.println(args[0] + args[1]);
    }
}
现在,当您在B中调用方法时,必须将字符串转换为字符数组:

String str = "example"; 
char[] charArray = str.toCharArray();
在中调用方法时,请确保将整数转换为字符:

int i = 5;
transform((char)Character.forDigit(i, 10), 'a'); // 10 stands for number radix which is probably 10  
这不是一个完美的解决方案,但它是可行的

但一个没有varargs的简单解决方案是只使用char数组,但同样需要将输入转换为char数组

public interface A{
    public void transform(char[]);
} 

public class B implements A{
        public void transform(char[] args){
            String s = "";
            for(char c : args){
            s += c;
            }
            System.out.println(s);
        }
    }

    public class C implements A{
        public void transform(char[] args){
            System.out.println(args[0] + args[1]);
        }
    }

不管怎么做,最终都会得到一个有点复杂的代码,即使使用泛型,也必须记住1方法接受1个参数,另一个方法接受2个参数。实际上,我认为最好是简单地将这些方法分开。

这是一个非常有趣的问题。如果您知道参数的最大数量,可以使用方法重载的概念

假设您知道,在最大值时,用户可以给出2个参数,然后您可以这样做

public void implementation(){
System.out.println("method with zero args")
}

public void implementation(String arg1){
System.out.println("method with one args and is:-"+arg1)
}

public void implementation(String arg1,String arg2){
System.out.println("method with two  args and are :-"+arg1+"  "+arg2)
}
如果您不知道参数的最大数量,可以通过多种方式实现。 1.创建集合并将其存储在集合对象中,然后将该对象作为参数传递

List args= new List();
l.add(arg1)
----------
----------
----------
l.add(argn)
public interface Input {
}
现在将此作为参数传递给函数调用作为

objecReference.implementation(l)
2.使用var-arg方法。 这是从Java1.8解决此类问题的非常简单的方法

实施中

public String implementation(int(change to required datattype)...x){
    //here x will act like an array
    for(int a:x){//iam assuming int values are coming
    System.out.println(a)
}
}
现在可以使用至少0个参数调用此函数,如

    objecReference.implementation()
    objecReference.implementation(10)
    objecReference.implementation(10,20)
    objecReference.implementation(12,23,34,5,6)

你可以实现你想要的,通过一些改变和一些函数编程的帮助

TL;DR

主要思想是
transform
方法不接收任何参数。相反,它将返回某个函数接口的实例

此功能接口的实现将由
transform
方法(如果它有参数)执行的代码组成

为了表示
a
接口的每个子类的不同类型和/或不同数量的参数,我们将在方法
transform
的返回类型中使用协方差

这意味着函数接口将是泛型的(因此,
A
的每个子类的参数类型可能不同),并且将有子接口扩展此函数接口,每个子接口在其单个抽象方法中接受不同数量的参数。这将允许
transform()
方法的返回值具有1、2、3、。。。等等

要执行
transform()
方法返回的代码,我们将执行以下操作:

instanceOfB.transform().execute("hello");
instanceOfC.transform().execute(1, 'a');
instanceOfD.transform().execute(1, "hello");
最后,为了能够以通用的方式执行代码,基本函数接口定义了一个varargs方法
executeVariadic(Object…args)
,每个子函数接口都将其作为默认方法来实现,将其委托给其
execute
方法,并根据需要转换参数


现在是长版本…

让我们首先将
接口重命名为更具描述性的接口。由于它定义了一个名为
transform
的方法,我们将其命名为
Transformer

然后,让我们创建一个功能接口,它将表示
Transformer
接口的
transform
方法。这是:

@FunctionalInterface
public interface Transformation {

    void executeVariadic(Object... args);
}
这个接口只定义了一个单一的抽象方法(SAM),它接收一个
Object…
varargs参数。它在那里,以便子接口可以覆盖它

现在,让我们创建一个
Transformation1
功能接口,扩展
转换
接口:

@FunctionalInterface
public interface Transformation1<A> extends Transformation {

    void execute(A a);

    @Override
    @SuppressWarnings("unchecked")
    default void executeVariadic(Object... args) {
        this.execute((A) args[0]);
    }
}
想法是一样的:
Transformation2
接口扩展了
Transformation
接口,我们重写了
executeVariadic
方法,以便将其委托给
execute
方法,相应地抛出参数(并抑制恼人的警告)

为了完整起见,让我们介绍一下
Transformation3
接口,它类似于前面的
TransformationX
接口:

@FunctionalInterface
public interface Transformation3<A, B, C> extends Transformation {

    void execute(A a, B b, C c);

    @Override
    @SuppressWarnings("unchecked")
    default void executeVariadic(Object... args) {
        this.execute((A) args[0], (B) args[1], (C) args[2]);
    }
}
这就是你现在的基本界面。
transform
方法不再有参数,而是返回一个
Transformation

现在让我们看看如何实现
B
C
D
类。但首先,请允许我将它们分别重命名为
TransformerB
TransformerC
TransformerD

这是
转换器b

public class TransformerB implements Transformer {

    @Override
    public Transformation1<String> transform() {
        return a -> System.out.println(a); // or System.out::println
    }
}
b.transform()
返回
Transformation1
的一个实例,该实例的
execute
方法将立即用它所需的
字符串
参数调用

现在让我们看一下Transformer C的实现:

public class TransformerC implements Transformer {

    @Override
    public Transformation2<Integer, Character> transform() {
        return (a, b) -> System.out.println(a + b);
    }
}
对于
TransformerD
示例,我使用了三参数转换:

public class TransformerD implements Transformer {

    public Transformation3<Integer, Double, String> transform() {
        return (a, b, c) -> System.out.println(a + b + c);
    }
}

这是所有类型安全的,因为泛型类型可以在
Trans中指定
TransformerB b = new TransformerB();
b.transform().execute("hello");
public class TransformerC implements Transformer {

    @Override
    public Transformation2<Integer, Character> transform() {
        return (a, b) -> System.out.println(a + b);
    }
}
TransformerC c = new TransformerC();
c.transform().execute(1, 'A');
public class TransformerD implements Transformer {

    public Transformation3<Integer, Double, String> transform() {
        return (a, b, c) -> System.out.println(a + b + c);
    }
}
TransformerD d = new TransformerD();
d.transform().execute(12, 2.22, "goodbye");
void callTransf(Transformer a, Object... args) {
    a.transform().executeVariadic(args);
}
callTransf(b, "hello");
callTransf(c, 1, 'A');
callTransf(d, 12, 2.22, "goodbye");
public interface A<T> {

    public void transform(T ... args);
}

public class B implements A<String> {

    @Override
    public void transform(String... args) {

    }

}


public class C implements A<Integer> {

    @Override
    public void transform(Integer... args) {

    }

}
public interface Input {
}
public interface Transformable {
  void transform(Input input);
}
public class InputForA implements Input {
  int a;
  String b;

  public int getA() {
    return a;
  }

  public InputForA setA(int a) {
    this.a = a;
    return this;
  }

  public String getB() {
    return b;
  }

  public InputForA setB(String b) {
    this.b = b;
    return this;
  }
}
public class TransformerA implements Transformable {
  @Override
  public void transform(Input input) {
    InputForA inputForA = (InputForA) input;
    System.out.println(inputForA.getA() + inputForA.getB());
  }
}