什么是使用空摘要 class 的好替代方法?

What is a good alternative to using an empty abstract class?

假设我有以下内容:

public abstract class AbstractResponse {
  // this class is totally empty!
}

public class ResponseA extends AbstractResponse {
  // JSON POJO 
}

public class ResponseB extends AbstractResponse {
  // JSON POJO 
}

public abstract class AbstractClient {
  public abstract Class getType();

  public AbstractResponse readResponse() {
    ObjectMapper mapper = new ObjectMapper();
    AbstractResponse response;
    try {
        return (AbstractResponse) mapper.readValue(data, getType());
    } catch (IOException e) {...}
  }
}

public class ResponseAClient extends AbstractClient {
  public Class getType() {
    return ResponseA.class;
  }
}

public class ResponseBClient extends AbstractClient {
  public Class getType() {
    return ResponseB.class;
  }
}

ResponseAResponseB 除了是 JSON POJO 之外没有任何共同点。如您所见,我使用空摘要 class AbstractResponse 来避免客户端 classes ResponseAClientResponseBClientreadResponse() 的重复代码.

我的问题:

在类似情况下使用空摘要 class 是一种不好的做法吗?如果是,最好的编码方式是什么?我考虑过使用泛型,但我看到许多警告不鼓励使用 Java 泛型。

编辑: 感谢大家的快速回复。在@Kayaman 发表有用的评论后,我想这样重新表述我的问题:

对于我上面描述的那种情况,是否有比使用空 interface/abstract class 更好的实现方式。空 interface/abstract class.

似乎是不好的做法

使用界面。使用空抽象 class 是没有意义的(除非你想防止 classes 子class 另一个 class)。

至于你的 "many warnings that discourage the use of Java Generics.",我很乐意看到一些链接,因为那不是真的。

编辑:通用方法可以为您提供如下内容(Response 是一个空接口,用于标记具体响应 classes 并限制 Client 可以处理的允许类型)

public class Client<T extends Response> {
    private Class<T> clazz;
    public Client(Class<T> clazz) {
        this.clazz = clazz;
    }
    public T readResponse() {
        ObjectMapper mapper = new ObjectMapper();

        return (T) mapper.readValue(data, clazz);
    }
}

允许您处理强类型的响应。

Client<ResponseA> clientA = new Client<>(ResponseA.class);
ResponseA resp = clientA.readResponse();

所以问题"What's a good alternative to an empty abstract class"的答案是"Refactor and Redesign"。

我宁愿使用带有 @Retention(RetentionPolicy.RUNTIME) 的注释,而不是使用空接口或抽象 class。不过,这需要编写更多的代码,并且可能不是特别可读和快速(您要检查 class 是否具有此注释的部分)。

语言中存在空接口,例如Serializable。但是自从 Java 5 之后,它就不再有意义了。

import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public abstract class AbstractClient {
    public abstract Class getType();

    public Object readResponse() {
        ObjectMapper mapper = new ObjectMapper();
        try {
            Object response = mapper.readValue(data, getType());

            if (response.getClass().getDeclaredAnnotation(Response.class) == null) {
                // Not a valid type
            }

            return response;
        } catch (IOException e) {...}
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Response {

}

@Response
class ResponseA extends AbstractResponse {
    // JSON POJO
}

@Response
class ResponseB extends AbstractResponse {
    // JSON POJO
}


class ResponseAClient extends AbstractClient {
    public Class getType() {
        return ResponseA.class;
    }
}

class ResponseBClient extends AbstractClient {
    public Class getType() {
        return ResponseB.class;
    }
}