java 抽象的静态方法 class

java static method for abstract class

我有一个 java 摘要 class 将扩展 class 声明为“JsonSerializable”

public abstract class JsonSerializable {
    private final String path;

    public JsonSerializable(String path) {
        this.path = path;
    }
} 

现在,如果我尝试“加载”扩展 JsonSerializable 的 class,我需要获取要加载的 class 的“文件路径”。 我目前的做法如下:

private static <T extends JsonSerializable> T getNew(Class<T> tClass) throws [...] {
        return tClass.getDeclaredConstructor().newInstance();
}

但是,如果构建一个新的 class(我正在尝试加载的类型)有一些副作用(例如,在初始化时,class 在另一个内部“注册”自己) 或者如果 IS 没有不带参数的构造函数?

有没有更好的方法来做到这一点?我不想创建一个只包含每个 class.

的文件路径的“FileRegistry”class

But what if the constructing of a new class (of the type I am trying to load) has some side effects (e.g. upon initialization, the class "registers" itself inside another one)

Constructor#newInstance 调用构造函数。如果它有副作用,那些事情就会发生。但请注意,理想情况下,构造函数应该只初始化对象而没有副作用(尤其是在构造函数完成之前不会泄漏 object/publosh 和 this 引用。

or if there IS no constructor with no arguments?

在这种情况下,getDeclaredConstructor() 会抛出异常。但是,您可以使用 Class#getDeclaredConstructors.

获取所有构造函数

但是,您可以在 JsonSerializable.

的 Javadoc 中指定 类 扩展 JsonSerializable 必须具有 no-args-constructor 并且没有副作用

虽然您 可以 创建新实例而不使用 Unsafe 调用构造函数,但应避免这种情况,因为它会使变量未初始化,可能导致未来出现异常。

恕我直言,这看起来更像是您要加载的 class 上注释 @JsonSerializable(path="some.path") 的用例。

代码可能如下所示:

// JsonSerializable.java
import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonSerializable {
    String path();
}

注解将在 class 上使用,如下所示:

// Options.java
@JsonSerializable(path="filepath.ending")
public class Options {
    private String example_property;
    private int example_property2;

    public Options() {
    }
}

然后读取注释的代码将是:

private static <T> T getNew(Class<T> tClass) throws Exception {
    JsonSerializable annotation = tClass.getAnnotation(JsonSerializable.class);
    System.out.println(annotation.path()); // Just to show how the path is read
    // here you would insert code to read the class the way you need
    return tClass.getDeclaredConstructor().newInstance();
}