代码之家  ›  专栏  ›  技术社区  ›  pvgoddijn

我应该如何铸造具有多个边界的Java泛型?

  •  16
  • pvgoddijn  · 技术社区  · 16 年前

    是否可以将Java中的对象转换为组合泛型类型?

    我的方法如下:

    public static <T extends Foo & Bar> void doSomething(T object) {
        //do stuff
    }
    

    如果我有一个实现两个接口(foo&bar)的类,那么调用此方法是没有问题的。

    问题是,当我需要调用此方法时,需要传递给它的对象将作为 java.lang.Object 为了让编译器满意,我需要对它进行强制转换。但我不知道怎么做这个演员。

    编辑:

    问题在于这样一个函数:

    public void problemFunction (Object o) {
      if ( o instanceof Foo && o instanceof Bar) {
          doSomething((Problematic cast) o);
      }
    }
    

    }

    5 回复  |  直到 9 年前
        1
  •  12
  •   erickson    16 年前

    不幸的是,没有合法的演员阵容可以满足这种情况。必须有一个已知的类型来实现所有需要作为边界的接口,以便可以强制转换到它。可能是为此目的创建的类型,也可能是某个现有类型。

    interface Baz extends Foo, Bar { }
    
    public void caller(Object w) {
      doSomething((Baz) w);
    }
    

    如果知道其他类型,比如 Baz ,为了满足界限,可以测试这些类型,并在调用方中有一个分支来调用 doSomething 对这些类型进行强制转换。它不漂亮。

    您也可以使用委托,创建自己的类 巴兹 满足 剂量测定法 . 然后将传递给您的对象包装在 巴兹 类,并将包装传递给 剂量测定法 .

    private static class FooBarAdapter implements Foo, Bar {
      private final Object adaptee;
      FooBarAdapter(Object o) {
        adaptee = (Foo) (Bar) o;
      }
      public int flip() { return ((Foo) adaptee).flip(); }
      public void flop(int x) { ((Foo) adaptee).flop(x); }
      public void blort() { ((Bar) adaptee).blort(); }
    }
    
    public void problemFunction (Object o) {
      doSomething(new FooBarAdapter(o));
    }
    
        2
  •  17
  •   Ron C    9 年前

    Java 8介绍了 casting with additional bounds . 你可以投一个 Object 作为一个 class 具有多重 interfaces (或者只是多重的 界面 )

    因此:

    doSomething((Problematic cast) o);
    

    就这样:

    doSomething((Foo & Bar) o);
    
        3
  •  7
  •   James Van Huis    16 年前
    public static <T extends Foo & Bar> void doSomething(T object)
    

    这似乎表明您将对所讨论的对象执行多个操作。

    我认为,如果您在对象上执行的所需操作足够独特,可以跨接口分离,那么它们就足够独特,值得拥有自己的方法。

    很可能您可以重新构造此代码以调用单独的方法来执行所需的操作。这可能会使整个操作从客户机的角度更加清晰。

    而不是:

    public void problemFunction (Object o) {
      if (o instanceof Foo && o instanceof Bar) {
          doSomething((Problematic cast) o);
      }
    }
    

    它变成:

    public void problemFunction(Object o) {
      if (o instanceof Foo && o instanceof Bar) {
          fooifySomething((Foo) o);
          baratizeSomething((Bar) o);
      }
    }
    
        4
  •  5
  •   user4316588    10 年前

    通过将联合类型编码为方法的类型参数的可怕方法,可以“向上强制转换”为联合类型;对于您的示例,您可以编写

    private <Q extends Foo & Bar> Q upcast(final Object in) {
        return (Q) in;
    }
    
    // ... elsewhere...
    
    if (myObject instanceof Foo && myObject instanceof Bar) {
        doSomething(upcast(myObject));
    }
    
        5
  •  -1
  •   sk.    16 年前

    作为解决方法,您可以定义另一个扩展foo和bar的接口foo bar,并让您的类实现它。它甚至不必是顶级接口——如果不想混乱或修改其余代码,可以将其声明为私有:

    private interface FooBar extends Foo, Bar {}
    public void problemFunction (Object o) {
      if ( o instanceof Foo && o instanceof Bar) {
          doSomething((FooBar) o);
      }
    }