我有一个匿名类,我想从匿名访问外部类的一些变量。问题是,当我尝试访问它时,它具有与初始化时相同的值,即使我正在改变它在另一个匿名类中的价值。
这是修剪后的代码
public class WeaponCircle extends Entity {
public static int TAG = gWorld.getNextTag();
float power=99; // <<<--the variable
public WeaponCircle(final gWorld world) {
super(world);
this.tag = TAG;
setGroups(Scene.SLOWABLE);
addMechanism(new IntervalMechanism(this,10) {
@Override
public void init() {
super.init();
world.worldrenderer.setWorldShader("punchShockWave");
world.worldrenderer.getShader("punchShockWave").getShader().setUniformf("screenSize", Tools.tempVec2.set(Gdx.graphics.getWidth(),Gdx.graphics.getHeight()));
power=4;
}
@Override
public void die() {
super.die();
world.worldrenderer.setClearWorldShader();
}
@Override
public void tick() {//this is called every frame
if(power>0)power-=0.1f*Director.delta;
Tools.con("debug0:"+power); //<<--------------------debug0 ,prints correct value
}
});
addMechanism(new MovementMechanism(this));
addMechanism(new SpriteMechanism(this,"sprites/sprites.png",714,284,1,235,235,gWorld.RENDER_LAYER4));
world.worldrenderer.addShader("punchShockWave", new Shader("shaders/default.ver","shaders/punch_shock_wave.frag",Shader.SCENE_SHADER));
world.worldrenderer.getShader("punchShockWave").setListener(new ShaderParrametersListener(this) {
@Override
public void setParameters(Shader shader) {//called every frame
WeaponCircle wc=(WeaponCircle)entity;//entity is the object that i passed in the constractor
/*irrelevant code*/
Tools.con("debug1:"+wc.power); //<<--------------------debug1 ,prints always 99
Tools.con("debug2:"+power); //<<--------------------debug2 ,prints always 99
/*irrelevant code*/
}
});
}
}
ShaderParrametersListener(它是Shader类中的静态类)
public abstract static class ShaderParrametersListener{
public Entity entity;
abstract public void setParameters(Shader shader);
public ShaderParrametersListener(){};
public ShaderParrametersListener(Entity entity){this.entity=entity;}
}
我的实体系统基于anonymus类,到目前为止我没有遇到任何问题,如果我再使用1个IntervlMechanism并从那里打印power变量,我将得到正确的值。这只发生在ShaderParrametersListener类中。 / p>
答案 0 :(得分:1)
我认为您的问题是您在构造函数中使用了this
关键字。请参阅Java - Leaking this in constructor。
正如相关答案所说,
“当构造函数完成时,对象被认为是完全初始化的。在该对象完全初始化之后只能看到对象引用的线程可以保证看到该对象的最终字段的正确初始化值”。如果你把它泄漏到构造函数中的另一个线程,就没有这样的保证!同样'在构造函数的末尾'可以由VM重新排序。“
我的猜测是world.worldrenderer.getShader("punchShockWave").setListener
是其他线程,现在可以访问未完全构造的对象。
我建议您在构造函数完成后找到一种方法来调用上面的setListener
方法。
更新我发现power
字段不是 final
,因此可能会使我的假设失效,因为链接的问题似乎表明这个问题仅适用于最终字段;但是,我仍然会尝试等到构造函数完成之后再将this
传递给另一个对象。也许尝试一下,看看它是否修复了这个bug。