是否可以通过java中的反射更改默认初始字段值?

是否可以通过java中的反射更改默认初始字段值?,java,reflection,field,Java,Reflection,Field,比如说,我们有一个带有字段的类,它有一个默认的初始值,并且构造函数不会改变它 public class Server { private int pingFrequency = 500; public Server() { } } 现在,在构建对象之前,我不想将默认初始值更改为另一个值。原因是这个类被库使用,并且隐藏了对象实例。因此,我只能控制对象的构造时间,而不能控制对象的位置和方式 我试图通过反射获取字段,但我看不到任何改变默认值的方法 Field pingFrequency

比如说,我们有一个带有字段的类,它有一个默认的初始值,并且构造函数不会改变它

public class Server {
  private int pingFrequency = 500;

  public Server() {
  }
}
现在,在构建对象之前,我不想将默认初始值更改为另一个值。原因是这个类被库使用,并且隐藏了对象实例。因此,我只能控制对象的构造时间,而不能控制对象的位置和方式

我试图通过反射获取字段,但我看不到任何改变默认值的方法

Field pingFrequency =  Class.forName("Server").getDeclaredField("pingFrequency")
我想我必须在类加载器中更改一些内容,但我不知道更改的内容和方式


当您声明这样的类时,非常感谢

public class Server {
  private int pingFrequency = 500;

  public Server() {
  }
}
这与

public class Server {
  private int pingFrequency;

  public Server() {
    pingFrequency = 500;
  }
}

事实上,这三种变体都被编译成相同的字节码。所有字段初始值设定项和实例初始值设定项块的代码都会复制到此类的每个构造函数,就在超级构造函数调用和构造函数其余部分之间。[]
不会委托给此类的另一个构造函数的

更改赋值的唯一方法是修改所有构造函数的代码,以更改赋值。这不能通过反射实现,只能通过字节码操作工具实现

注意,当字段被声明为final时,如

public class Server {
  private final int pingFrequency = 500;

  public Server() {
  }
}
字节码中将有一个属性,用于报告赋值之外的常量值[]。但是,对于这样的编译时常量,每个普通的读取访问都将在编译时[]替换为常量值,因此即使更改赋值也不会产生任何效果(更改属性也不会有任何效果)[]。试图替换字段的实际用法会产生一个问题,即您无法将它们与常量数的其他用法区分开来
500


如果该字段是
静态的
最终的
,则根本没有赋值,常量值属性将用于初始化该字段,但是,更改它的效果与更改常量实例字段的效果一样,因为字段访问仍然替换为旧的常量值。

您不能这样做,因为您的字段是私有字段,而不是静态字段。只有在创建对象时,才能更改该值。但无论如何,这看起来不是一个很好的设计。您最好的选择可能是更改服务器类的字节码。但是必须在某个地方存储应该用作默认值的信息。它在哪里以及如何修改它会很有趣。
public class Server {
  private final int pingFrequency = 500;

  public Server() {
  }
}