Reputation: 3389
I have an anonymous class and I want to access some variables of the outer class from the anonymous.The problem is that always when I try to access it, it has the same value as when it was initialized even that i am changing its value on an other anonymous class.
this is the trimmed code
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 (its a static class inside the Shader class)
public abstract static class ShaderParrametersListener{
public Entity entity;
abstract public void setParameters(Shader shader);
public ShaderParrametersListener(){};
public ShaderParrametersListener(Entity entity){this.entity=entity;}
}
My entity system is based on anonymus classes and I didnt had any problem so far ,If i use 1 more IntervlMechanism and print the power variable from there ,I will get the correct value.This happens only in the ShaderParrametersListener class.
Upvotes: 1
Views: 204
Reputation: 3584
I think your issue is that you are using the this
keyword inside the constructor. See Java - Leaking this in constructor.
As the linked answer says,
"An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields". No such guarantee if you leak this to another thread in the constructor! Also 'at the end of the constructor' may be reordered by the VM."
My guess is that world.worldrenderer.getShader("punchShockWave").setListener
is the other thread that now has access to an incompletely constructed object.
I'd recommend finding a way to call the above setListener
method after your constructor has completed.
UPDATE I see that the power
field is not final
, so that may invalidate my hypothesis, as the linked question seems to indicate this problem holds for final fields only; however, I still would attempt to wait until after the constructor completes before passing this
to another object. Maybe try it out and see if it fixes the bug.
Upvotes: 1