调用 Scala 的泛型类从 Java 中丢失泛型信息

huangapple go评论47阅读模式
英文:

invoking scala generic classes from java looses generic info

问题

尝试在Scala库中定义的Java类中使用。定义如下:

final class ScenarioBuilder(...) extends StructureBuilder[ScenarioBuilder]
trait StructureBuilder[B <: StructureBuilder[B]] extends Execs[B] with Feeds[B]

是的,这是Gatling。

我的Java代码:

public ScenarioBuilder callMyApi(ScenarioBuilder in) {
    return in.feed(myFeeder.asScala())
            .exec(addCookie(Cookie("key", "value")).asScala())
            .exec(http("my api call")
                .get("/api").asScala());
}

IDE认为这段代码是正确的,但每当我尝试编译它时,我都会收到以下错误:

symbol:   method exec(io.gatling.core.action.builder.ActionBuilder)
location: class java.lang.Object
or
java: incompatible types: java.lang.Object cannot be converted to io.gatling.core.structure.ScenarioBuilder

换句话说,来自Feeds[B]B feed(...)Execs[B]B exec(...)方法总是返回Object,而我希望BScenarioBuilder

我能想到的唯一编译和运行这段代码的方法是:

public ScenarioBuilder callMyApi(ScenarioBuilder in) {
    StructureBuilder<ScenarioBuilder> sb = in;
    sb = (StructureBuilder<ScenarioBuilder>) sb.feed(myFeeder.asScala())
            .exec(addCookie(Cookie("key", "value")).asScala());
    return (ScenarioBuilder) sb.exec(http("my api call")
                .get("/api").asScala());
}

这看起来令人不悦。

问题:

  • 为什么Java无法从Scala类中识别泛型信息?
  • 是否有更好的方法来在Java中使用Scala Gatling API?
  • 为什么IDE认为第一种变体是正确的,而编译器不这样认为?

是的,我知道Gatling中有Java API,尽管由于某种原因,make方法的定义如下:

public ScenarioBuilder make(
  Function<io.gatling.core.structure.ScenarioBuilder, io.gatling.core.structure.ScenarioBuilder>
      f) {
    return new ScenarioBuilder(f.apply(wrapped));
}

对我来说,这是一个非常开放的问题,为什么会这样定义。

提前感谢您。

更新:
Java-1.8,Scala-2.11.8

myFeeder = listFeeder(Arrays.asList(
            Collections.singletonMap("items", Arrays.asList("Item 1", "Item 2"))
)).circular()

Gatling版本-3.9.0,尽管问题不是关于Gatling本身,而主要是关于如何从Java调用具有泛型的Scala代码。

由于某种原因,javac无法在Scala类中看到泛型信息,我想知道为什么。

至于Gatling,我通过正确使用API解决了这个问题,简而言之,不要使用"make"方法来构建从不同步骤"exec(ChainBuilder)"的场景。

英文:

trying to use in java class defined in scala library.
Definition:

final class ScenarioBuilder(...) extends StructureBuilder[ScenarioBuilder]
trait StructureBuilder[B &lt;: StructureBuilder[B]] extends Execs[B] with Feeds[B]

yes, it is Gatling.

my java code:

    public ScenarioBuilder callMyApi(ScenarioBuilder in) {
        return in.feed(myFeeder.asScala())
                .exec(addCookie(Cookie(&quot;key&quot;, &quot;value&quot;)).asScala())
                .exec( http(&quot;my api call&quot;)
                    .get(&quot;/api&quot;).asScala());
    }

Idea finds this code correct, but whenever i try to compile it i get this errors:

symbol:   method exec(io.gatling.core.action.builder.ActionBuilder)
location: class java.lang.Object
or
java: incompatible types: java.lang.Object cannot be converted to io.gatling.core.structure.ScenarioBuilder

in other words methods B feed(...) from Feeds[B] and B exec(...) from Execs[B] always return Object and i would expect B to be ScenarioBuilder

the only way to compile and run this code i came up with is this:

    public ScenarioBuilder callMyApi(ScenarioBuilder in) {
        StructureBuilder&lt;ScenarioBuilder&gt; sb = in;
        sb = (StructureBuilder&lt;ScenarioBuilder&gt;) sb.feed(myFeeder.asScala())
                .exec(addCookie(Cookie(&quot;key&quot;, &quot;value&quot;)).asScala());
        return (ScenarioBuilder) sb.exec( http(&quot;my api call&quot;)
                    .get(&quot;/api&quot;).asScala());
    }

and it looks disgusting

questions:

  • why does java misses generic info from scala classes?
  • is there better way to utilise scala Gatling api in java?
  • why does IDE finds the first variant correct and compiler does not?

yes, i know there's java api in Gatling though by some reason method make is defined like this:

  public ScenarioBuilder make(
      Function&lt;io.gatling.core.structure.ScenarioBuilder, io.gatling.core.structure.ScenarioBuilder&gt;
          f) {
    return new ScenarioBuilder(f.apply(wrapped));
  }

and to me it is very open question why it is defined this way.

thanks in advance

UPD:
java- 1.8, scala- 2.11.8

myFeeder  = listFeeder(Arrays.asList(
                Collections.singletonMap(&quot;items&quot;, Arrays.asList(&quot;Item 1&quot;, &quot;Item 2&quot;))
)).circular()

Gatling version - 3.9.0 though the question not about Gatling itself it is mostly about calling scala code with generics from java.

By some reason javac does not see generic info in scala classes, and i wonder why.

As to Gatling i've solved the issue by proper API usage, long story short don't use make methods for construction scenario from different steps exec(ChainBuilder) is the choice.

答案1

得分: 2

免责声明: Gatling的作者在此

不要。 Gatling的Java DSL并不是为与Scala DSL互操作而构建的。特别是,asScala() 是一个内部方法。

要么选择其中一个,要么不要混在一起使用。

英文:

Disclaimer: Gatling's author here

> is there better way to utilise scala Gatling api in java?

Don't. Gatling's Java DSL wasn't built with interoperability with the Scala DSL in mind. In particular, asScala() is an internal.

Go with either one or the other, but don't mix them together.

huangapple
  • 本文由 发表于 2023年2月14日 18:56:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75446830.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定