Доступ к переменным внутри анонимного класса

1

У меня есть анонимный класс, и я хочу получить доступ к некоторым переменным внешнего класса от анонимного. Проблема в том, что всегда, когда я пытаюсь получить к нему доступ, он имеет то же значение, что и при его инициализации, даже если я изменяю его значение на другой анонимный класс.

это обрезанный код

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;}
}

Моя система сущностей основана на классах анонимуса, и до сих пор у меня не было никаких проблем. Если я использую еще 1 IntervlMechanism и напечатаю переменную мощности оттуда, я получу правильное значение. Это происходит только в классе ShaderParrametersListener.

  • 5
    if(power>0)power-=0.1f*Director.delta; - Я призываю вас рассмотреть преимущества удобочитаемости пробелов (и даже скобок).
  • 1
    IntervalMechanism объявляет power поле?
Показать ещё 12 комментариев
Теги:
class
anonymous-class

1 ответ

1
Лучший ответ

Я думаю, ваша проблема в том, что вы используете this ключевое слово внутри конструктора. См. Java - Утечка этого в конструкторе.

Как говорится в ответном ответе,

"Объект считается полностью инициализированным, когда его конструктор заканчивается. Поток, который может видеть только ссылку на объект после того, как этот объект был полностью инициализирован, гарантированно увидит правильно инициализированные значения для этих конечных полей объекта". Нет такой гарантии, если вы пропустите это в другой поток в конструкторе! Также "в конце конструктора" может быть переупорядочено VM ".

Я предполагаю, что world.worldrenderer.getShader("punchShockWave").setListener - это другой поток, который теперь имеет доступ к неполному конструированному объекту.

Я бы рекомендовал найти способ вызова вышеуказанного метода setListener после завершения вашего конструктора.

ОБНОВЛЕНИЕ Я вижу, что power поле не является final, поэтому может привести к аннулированию моей гипотезы, поскольку связанный вопрос, похоже, указывает, что эта проблема выполняется только для окончательных полей; однако я все равно попытаюсь подождать, пока конструктор не завершит передачу this объекта другому объекту. Возможно, попробуйте и посмотрите, исправляет ли он ошибку.

  • 0
    вау, я переместил setListener в метод tick (использовал логическое 'first', чтобы вызвать его только один раз), чтобы он вызывался после того, как ограничение объекта закончилось, и проблема исчезла, это очень хороший ответ, хороший работа, вы получите награду за 13 часов ...
  • 0
    Я рад это слышать, SteveL.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню