Java 如何实现参数数目未知的方法?
我有1个接口和3个类。我希望这个类能够同时实现需要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); } }
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());
}
}