gpt4 book ai didi

java - 何时以 .methodName() 的形式在 Java 中使用带有方法调用的菱形运算符?

转载 作者:行者123 更新时间:2023-12-05 04:28:02 25 4
gpt4 key购买 nike

有时我会看到在方法调用中使用菱形运算符的示例。

一个语法示例是:

.<ClassName>methodName()

我不确定我是否完全理解在何种情况下有这种用途的情况。在引用文献中没有找到对此的解释。

你可以解释一下那个案例或建议我可以找到解释的信息来源吗?

我在下面提供了一个工作示例。此示例使用 RxJava2。那里Flowable.<Integer>create(emitter -> emit(emitter), BackpressureStrategy.BUFFER)没有 <Integer> 就无法编译因为方法 emit 接受 FlowableEmitter<Integer> emitter .


import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.schedulers.Schedulers;

public class Sample {

public static void main(String[] args) {
Flowable.<Integer>create(emitter -> emit(emitter), BackpressureStrategy.BUFFER)
.observeOn(Schedulers.computation(), true,2)
.map(data -> data * 1)
.subscribe(Sample::process,
err -> System.out.println("ERROR: " + err),
() -> System.out.println("DONE"));

}

public static void process(int value) {
System.out.println(value);
sleep(1000);
}

private static void emit(FlowableEmitter<Integer> emitter) {
int count = 0;

while(count < 10) {
count++;

System.out.println("Emitting ..." + count);
emitter.onNext(count);
sleep(500);
}
}

private static boolean sleep(int ms) {
try {
Thread.sleep(ms);
return true;
} catch (InterruptedException e) {
return false;
}
}


}

当我尝试使用纯 Java 模拟类似情况时,它不起作用。我理解错了什么?


public class Sample2 {

public static void main(String[] args) {
GenericClass.<Integer>genericMethod(param -> processParam(param));

}

private static void processParam(GenericClass<Integer> b) {
}
}

}

class GenericClass <T> {
public static <T> GenericClass<T> genericMethod(GenericInterface<T> genericinterface) {
return new GenericClass<T>();
}
}

interface GenericInterface <T> {
T doJob();
}

最佳答案

ClassName.<Type>methodName(...)是Java中方法调用的一种形式。 JLS 中列出了许多其他形式:

MethodInvocation:
MethodName ( [ArgumentList] )
TypeName . [TypeArguments] Identifier ( [ArgumentList] ) <--- this is the form in question
ExpressionName . [TypeArguments] Identifier ( [ArgumentList] )
Primary . [TypeArguments] Identifier ( [ArgumentList] )
super . [TypeArguments] Identifier ( [ArgumentList] )
TypeName . super . [TypeArguments] Identifier ( [ArgumentList] )

TypeArguments:
< TypeArgumentList >
TypeArgumentList:
TypeArgument {, TypeArgument}

<...>里面,您应该显式地为泛型方法的每个类型参数编写类型参数。

请注意 ClassName<Type>.methodName不是其中一种形式。

您在尝试用纯 Java 模拟此行为时遗漏的主要内容是 GenericInterface.doJob应该带一个参数,因为你传入的lambda有一个参数:

param -> processParam(param)
^^^^^

此参数的类型应为 GenericClass<T> ,因为那是processParam需要。

interface GenericInterface <T> {
void doJob(GenericClass<T> param);
}

这类似于 subscribe FlowableOnSubscribe<T> 中的方法,这就是Flowable.create作为参数。

请注意 subscribe采用与 Flowable.create 不同的类型返回,但我们采用与 GenericClass.genericMethod 相同的类型返回。这仍然模拟了“显式编写类型参数编译但省略它会产生错误”的相同行为,因此我不会费心创建新类型。

现在您得到与 Flowable.create 相同的行为RxJava 中的方法:

GenericClass.genericMethod(param -> processParam(param)); // error
GenericClass.<Integer>genericMethod(param -> processParam(param)); // OK

这是因为Java的类型推断算法不够强大,无法在第一种情况下正确推断类型。

虽然这和 RxJava 之间仍然存在差异 - Flowable.create需要 FlowableOnSubscribe<T> , 它有一个``

关于java - 何时以 .<ClassName>methodName() 的形式在 Java 中使用带有方法调用的菱形运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72689148/

25 4 0