Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:使用类型参数信息访问静态Java方法_Java_Scala_Generics_Type Inference_Type Parameter - Fatal编程技术网

Scala:使用类型参数信息访问静态Java方法

Scala:使用类型参数信息访问静态Java方法,java,scala,generics,type-inference,type-parameter,Java,Scala,Generics,Type Inference,Type Parameter,我使用一个Java代码生成器(不幸的是,我无法摆脱它),它输出如下代码: abstract class Abs1 { //... } abstract class Abs2 { //... } interface I { //... } public static final class C1 extends Abs implements I { public final static Inner newInstance() { return Inner.create(); } p

我使用一个Java代码生成器(不幸的是,我无法摆脱它),它输出如下代码:

abstract class Abs1 { //... }
abstract class Abs2 { //... }
interface I { //... }

public static final class C1 extends Abs implements I {

  public final static Inner newInstance() { return Inner.create(); }

  public final class Inner extends Abs2 { 
    private static Inner create() { return new Inner(); }
  }

  public final static C1 build() { 
    // builds the object instantiating some fields with defaults
  }

}

final static class C2 extends Abs implements I {

  // exactly same as in C1: 

  public final static Inner newInstance() { return Inner.create(); }

  public final class Inner extends Abs2 { 
    private static Inner create() { return new Inner(); }
  }

  public final static C1 build() { 
    // builds the object instantiating some fields with defaults
  }

}
我有许多其他的类,像C1和C2在相同的风格。 正如您所看到的,每个外部类(C1、C2…)都有一个内部类,始终命名为内部类。此外,所有内部类都扩展了同一个抽象类

我想从字符串创建每个外部类的实例。我有一个实用工具(合并),可以将实例与其字符串合并

def createC1(str: String) = {
  val ins = C1.newInstance
  Merger(ins, str)
  ins.build
}

def createC2(str: String) = {
  val ins = C2.newInstance
  Merger(ins, str)
  ins.build
}
。。。这似乎是明显的代码重复。所以我想利用类型参数化

def build[A <: Abs](str: String) = {
  val ins = A.newInstance // this obviously won't compile - but this is my intent
  Merger(ins, str)
  ins.build
}
为什么它不推断
ins1
中的类型

编辑:使外部类保持静态。

问题 您试图创建的代码的主要问题是,您试图访问泛型类型的
静态
方法。Java和Scala中的泛型类型都不允许访问与该类型关联的
静态方法。我已经阅读了一些相当复杂的反射,您可以使用这些反射来访问泛型类型的
companion
对象,但是我强烈建议您在这种情况下避免类似的操作,因为这样的代码非常脆弱且不可维护。毕竟,任何抽象的目标都是使代码更易于使用,而不是更难

两个解决方案 在这种情况下,您可以轻松地做一些事情来进行抽象,使使用此代码更容易处理我假设您根本无法修改生成的代码,因为如果可以,我将跳过一些更好的方法来处理此问题。

解决方案1结构类型 此问题的第一个也是最简单的解决方案是使用结构类型。考虑下面的代码(它是Scala代码,但它应该java中的概念相同)。< /P> 现在,我想用下面的函数调用
newInstance
,它不会编译

这只比你理想的解决方案稍微多一点。但是,请注意,编译器发出警告的原因是结构类型需要反射,因此会导致运行时性能下降。但是,如果代码不在程序的关键部分,您可能不会担心它

解决方案2,只需传递函数 我们可以直接传递函数来完成工作,而不是使用结构类型。这比structural类型版本稍微详细一些,但也稍微快一些,更安全一些

scala> def makeInstance[A <: InnerFoo, B <: Foo](newInstanceProc: => A, buildProc: => B): B = {
     | newInstanceProc
     | // do some stuff
     | buildProc
     | }
makeInstance: [A <: InnerFoo, B <: Foo](newInstanceProc: => A, buildProc: => B)B

scala> makeInstance(Bar.newInstance, Bar.build)
res19: Bar = Bar$$anon$1@4d0402b
scala>def makeInstance[ab:B={
|newInstanceProc
|//做点什么
|buildProc
| }
makeInstance:[A B)B
scala>makeInstance(Bar.newInstance,Bar.build)
res19:Bar=Bar$$anon$1@4d0402b

公共最终类内部扩展Abs2
是否应该有
static
修饰符?我认为没有它是不合法的。@Isomarte:我将外部类设置为static。它现在应该是有效的。最后一段代码为您编译了吗?我不确定它是否不能满足您的要求,或者根本无法编译。我无法在我的REPL上编译等效代码。@isomarte您能告诉我确切的代码块吗?最后一块,您使用
ClassTag
scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Foo
trait InnerFoo
trait Bar extends Foo
trait Baz extends Foo
object Bar {
    class InnerBar extends InnerFoo
    def newInstance: InnerBar = new InnerBar
    def build: Bar = new Bar {}
}
object Baz {
    class InnerBaz extends InnerFoo
    def newInstance: InnerBaz = new InnerBaz
    def build: Baz = new Baz {}
}

// Exiting paste mode, now interpreting.

defined trait Foo
defined trait InnerFoo
defined trait Bar
defined trait Baz
defined object Bar
defined object Baz
def makeInstance[A <: Foo, B <: InnerFoo]: B = {
  A.newInstance
  // do some stuff
  A.build
}
scala> def makeInstance[A <: InnerFoo, B <: Foo](static: { def newInstance: A; def build: B }) = {
     | static.newInstance
     | // do some stuff
     | static.build
     | }
warning: there were two feature warnings; re-run with -feature for details
makeInstance: [A <: InnerFoo, B <: Foo](static: AnyRef{def newInstance: A; def build: B})B

scala> makeInstance(Bar)
res16: Bar = Bar$$anon$1@1601e47

scala> makeInstance(Baz)
res17: Baz = Baz$$anon$2@6de54b40
scala> def makeInstance[A <: InnerFoo, B <: Foo](newInstanceProc: => A, buildProc: => B): B = {
     | newInstanceProc
     | // do some stuff
     | buildProc
     | }
makeInstance: [A <: InnerFoo, B <: Foo](newInstanceProc: => A, buildProc: => B)B

scala> makeInstance(Bar.newInstance, Bar.build)
res19: Bar = Bar$$anon$1@4d0402b