【问题标题】:How to call a method depending on its type generic?如何根据其泛型类型调用方法?
【发布时间】:2011-05-12 00:52:41
【问题描述】:

让下面的代码:

    public abstract class MySuperClass { 
       public abstract void update();
       /* ... */
    }

    public class A extends MySuperClass { 
       @Override
       public void update() { /* ... */ }
       /* ... */
    }

    public class B extends MySuperClass { 
       @Override
       public void update() { /* ... */ }
       /* ... */
    }

    public class Ticket<T extends MySuperClass> {
      private Class<T> c;
      public Ticket(Class<T> c){ this.c = c; }
      public Class<T> getClass() { return this.c; } 
      public void update() { /* HOW TO DO! */ }
      /* ... */
    }

    public class Main {
      public static void main(String[] args) {
        Ticket<A> myTicket1 = new Ticket<A>(A.class);
        Ticket<B> myTicket2 = new Ticket<B>(B.class);
        myTicket1.update();
        myTicket2.update();
      }
    }

如何根据他的类型(AB)等升级票证?

【问题讨论】:

  • 您不再喜欢金属/木材/汽车的类比了吗? ;)
  • 我查看了另一个被引用的问题,aioobe 是对的。在这两种情况下,您似乎都缺少一些继承的概念。为了进行更新,我只需要访问MySuperClass 对象。不管是A 还是B,Java 都会使用update() 实现。

标签: java generics reflection inheritance


【解决方案1】:

为什么Ticket 对更新的实际含义一无所知。它只需要将调用转发到MySuperClass 的实例。泛型类的全部意义在于,泛型类可以与任何对象(或对象子集)一起工作,而不必确切知道它是什么类型。

public class Ticket<T extends MySuperClass> {
  private T thing;
  public Ticket(T thing) {
    this.thing = thing;
  }
  public void update() {
    thing.update();
  }
  /* ... */
}

【讨论】:

    【解决方案2】:

    update() 是一个实例方法,因此您需要一个实例来调用它。这可以通过

    来实现
    getClass().newInstance().update();
    

    由于多态性,它会从 A 或 B 调用正确的方法。 但是要以更面向对象的方式解决它,您应该将一个实例传递给 Ticket 构造函数,然后调用 update()。

    【讨论】:

      【解决方案3】:

      我已经调整了您的示例,使其更有意义......并实现了update

      public class Ticket<T extends MySuperClass> {
          private Class<T> c;
          private T t;
      
          public Ticket(Class<T> c) throws InstantiationException, IllegalAccessException { 
              this.c = c; 
              this.t = c.newInstance();
          }
      
          public Class<T> getClass() { 
              return this.c; 
          } 
      
          public void update() {
              t.update();
          }
          /* ... */
      }
      

      update 方法调用t.update(),它将多态地分派到t 引用的实际对象的update 方法。请注意,我添加了代码来创建和存储Class&lt;T&gt; 的实例。

      更新 - 我已将例外添加到 Ticket 构造函数。这是您使用反射创建实例所付出的部分代价……而不是使用 new 创建实例并将它们作为参数传递。

      【讨论】:

      • 你可以。实际上,我对您的示例进行了调整;见c.newInstance()。但是没有必要使用反射来调用t.update()
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多