java - 从通用管理器类中,如何以静态方式访问有关其实例的信息?

标签 java generics inheritance static

我正在尝试创建一个在线竞技场游戏,玩家可以在其中创建自定义竞技场来玩。我希望将竞技场设置保存在 MySQL 数据库中,以便保存竞技场以供进一步玩。

问题是,阿里纳斯有不同的变体。因此可以有丛林竞技场、沙漠竞技场等。所有这些不同的变体(抽象类 Arena 的子类)必须存储在不同的表中,因为每种类型的竞技场的变量(以及列)都不同。

我的问题是:从下面描述的包含泛型类型数组的 Manager 类中,如何从子 (T) 类及其父类获取所需的列。我使用通用类型是因为我还想稍后使用此类来管理玩家信息(也需要存储在数据库中)。

这是 Manager 类:

public class Manager<T extends Savable> {
  private Connection connection;
  private List<Column<?>> columns;

  private List<T> instances;

  public Manager() {
    fillColumnArray()

    try {
      connection = getSQLConnection();
      Statement s = connection.createStatement();
      s.executeUpdate(getCreateQuery())
      s.close();

    } catch (SQLException e) {
        e.printStackTrace();
    }
  }

  public void fillColumnArray() {
    // Somehow, manages to get the needed columns from
    // the parent class and the child class
  }

  public Connection getSQLConnection() {
    // Creates a mysql connection to a database
    // from parameters on a local file and returns it
  }

  public String getCreateQuery() {
    // Creates the query from the previously found columns
  }

  /* */
}

这是管理器中使用的 Column 类:

public class Column<U> {
  private String name;
  private U defaultValue;

  /* */
}

这里是 Arena 类的可能变量和一个可能的子级

public abstract class Arena implements Savable {
  private Vector centerPosition;
  private int radius;
  private int gameLenght;

  /* */
}

public class JungleArena extends Arena {
  private int treeHeight;
  private boolean daytime;

  /* */
}

我想到了很多不同的可能性。其中之一是在 Savable 接口(interface)中添加 requestColumns() 方法,但此选项不起作用,因为创建 Manager 后,我只能以静态方式访问 T 类。

然后我想到在子级和父级中添加一个静态方法 requestColumns() 但由于我使用的是泛型类型,编译器将无法理解该方法来自何处。

然后我想到将 T 类型转换为其特定的 Arena 类型,但当使用相同的类来存储玩家时,它在我的项目中将无法进一步工作。

希望这足够清楚。

是否有人有一个让事情顺利进行的想法,或者只是您理解的另一种做事方式?

谢谢

最佳答案

考虑到您已经拥有实例并且您可以使用该实例以通用方式为您获取此信息,我不确定为什么您需要静态地执行此操作。我也不清楚您打算如何从类中获取列的值,如果您还没有,这个答案可以处理这个问题。

就我个人而言,由于还没有任何有值(value)的框架能够做到这一点,我会定义一个注释来放置在列字段的公共(public) getter 上。就像这样:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Column {
    String name() default "";
}

然后,您可以使用反射来获取这些 getter,然后调用实例上的方法,从而也获取值。例如,给定此类:

class Entity {
    ...

    @Column(name = "Name")
    public getName() { return name; }

    @Column(name = "Height")
    public getHeight() { return height; }
}

我可以像这样获取列名称和值:

    Entity e = new Entity("First", 42);
    Method[] methods = e.getClass().getMethods();
    Map<String, Method> colums = new HashMap<>();
    for (Method m : methods) {
        Column c = m.getAnnotation(Column.class);
        if (c != null) {
            colums.put(c.name(), m);
        }
    }
    colums.entrySet().forEach(entry -> {
        try {
            System.out.println(entry.getKey() + ": " + entry.getValue().invoke(e));
        } catch (IllegalAccessException | InvocationTargetException e1) {
            e1.printStackTrace();
        }
    });


Output >
Height: 42
Name: First

关于java - 从通用管理器类中,如何以静态方式访问有关其实例的信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42171485/

相关文章:

java - 在 hsqldb 中禁用主机名验证

Java PrintWriter 不发送字节数组

c++ - 如何通过接口(interface)存储成员函数指针

kotlin - 在使用实现类的接口(interface)中实现泛型方法

c++ - 嵌套类的继承和可见范围

C++ 多重继承关闭同名运算符

Java 8 列表到现有 map

java - 如何通过控制台在 Linux 中启动 Java 服务器?

java - 相同 JDK 上的相同代码可以在 Eclipse 上编译,但会在 Netbeans、IDEA 或命令行上导致类型不可转换

c# - 隐藏基类的属性