【问题标题】:How to use class type of method parameter?如何使用方法参数的类类型?
【发布时间】:2020-12-20 19:14:59
【问题描述】:

我有以下课程: Foo1 扩展 Bar 和 Foo2 扩展 Bar

我想在我的方法中传递 Foo1 或 Foo2 的类型来创建 Foo1 或 Foo2,如下所示:

public Bar createMethod( "either type of Foo1, or Foo2" fooType) {
    
    //returns the foo1 or foo2
}

有什么方法可以实现吗?

【问题讨论】:

  • 这听起来像是XY problem。你到底想达到什么目的?

标签: java oop


【解决方案1】:

您可以通过声明使用泛型来获得一些灵活性:

public <T extends Bar> T createMethod(Class<T> foo) {
    // do the factoring
    retrun (T) foo1 // (or foo2 depending on the foo passed);
} 

因此,以下所有分配都是有效的:

Bar b1 = createMethod(Foo1.class);
Bar b2 = createMethod(Foo2.class);
Foo1 f1 = createMethod(Foo1.class);
Foo2 f2 = createMethod(Foo2.class);

注意:在运行时,如果你没有返回预期的类型,你会得到一个ClassCastException。因此,如果您例如这样做:

public <T extends Bar> T createMethod(Class<T> foo) {
    return (T)new Foo2();
}

Foo1 foo1 = createMethod(Foo1.class);

【讨论】:

    【解决方案2】:

    代码如下:

            public static void main(String args[]){
    
            Bar barB = createMethod(FooB.class);
            Bar barA = createMethod(FooA.class);
    
            System.out.println("barB is instance of B " + (barB instanceof FooB) );
            System.out.println("barA is instance of A " + (barA instanceof FooA) );
    
        }
    
    
    
        public static Bar createMethod(Class foo) {
            if(foo.equals(FooA.class)) {
                FooA fooA = new FooA();
                return (Bar) fooA;
            }
            else{
                FooB fooB = new FooB();
                return (Bar) fooB;
            }
        }
    
    }
    
        class Bar{}
        
        class FooA extends Bar{}
        
        class FooB extends Bar{}
    

    你的 FooA 和 FooB 扩展了 Bar。

    【讨论】:

      【解决方案3】:

      Java 没有联合类型,所以像 A | B 这样的类型在 Java 中是不可能的。

      Java 15 通过 JEP 360 添加了密封类型,因此您可以创建一个只有两种无法扩展的类型的密封类型层次结构,从而有效地为您自己的类型模拟联合类型。

      通过传递Class 的实例,您可以使用反射来实例化该类型。

      public sealed interface FooBar permits Foo, Bar { }
      public final class Bar implements FooBar { }
      public final class Foo implements FooBar { }
      
      public FooBar createMethod(Class<? extends FooBar> type) {
         return type.newInstance();
      }
      

      如果没有密封类型,您必须接受第三方可能会扩展您的类型这一事实,因此不仅可以将这两种类型作为方法的参数。

      另一种可能性是使用字符串,并使用Class.forName(String) 来获取与完全限定类关联的类型:

      public FooBar createMethod(String type) {
         if (type.equals("your.type.Foo") || type.equals("your.type.Bar"))
              return Class.forName(type).newInstance();
      }
      

      【讨论】:

        【解决方案4】:

        你可以声明

        public Bar createMethod(Class<? extends Bar> fooType) {
            //returns the foo1 or foo2
        }
        

        然后调用

        Bar bar = createMethod(Foo1.class);
        

        【讨论】:

          猜你喜欢
          • 2019-07-21
          • 1970-01-01
          • 2015-12-26
          • 1970-01-01
          • 2013-02-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多