Search code examples
javafinal

final variable keeps changing but shouldnt


I am engineering a program for my bachelor thesis that displays the inner geometry of a steel wire rope depending on the z location (location in the cable).

To test I "walk through" a piece of the cable, with this piece of code (sl is a strand list, initialized already, that works fine):

    Cable c = new Cable(sl);
    ImageFrame ts = new ImageFrame(c);

    try {
        while (location <2 ) {
            location = location + 0.01; 
            Thread.sleep(100);
            c.update(location);
            ts.repaint();
        }
        System.exit(0);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

The cables function update just should recalculate the geometry of the cable. My class cable has a list of strands, and what this update function does, is just calling the update function for all these strands:

public void update(double z) {
for(int i=0;i<strandList.size() ;i++) {
            strandList.get(i).updateStrand(z);

        }

    }

The object Strand looks like this:

public abstract class Strand {

    Punt middenCable;
    final Punt nulpoint_midden;
    Punt midden;
    Double angle;
    Double d_to_core;
    Image img;
    int img_size;
    BufferedImage bf;

    /**
     * 
     * @param c centre of the cable
     * @param p middle of the strand
     * @param ang angle at this point
     * @param dtc distance to core
     * @param i image
     */
    public Strand(Punt c,Punt p,Image i) {
        nulpoint_midden = p; //location of strand at z=0
        middenCable =c;
        midden = p; // for drawing
        img = i;
        img_size = 135; //TODO adapt
        bf = new BufferedImage(img_size, img_size, BufferedImage.TRANSLUCENT );
        bf.getGraphics().drawImage(img, 0, 0, null);
}



    /**
     * angle goed zetten tov de z
     * @param z
     */
    abstract public  void updateStrand(Double z);






    public void paint(Graphics g){
        g.setColor(Color.RED); //cirkels rood
        //rotate around itself
        int x = (int) (this.midden.getX() - img_size/2  );
        int y = (int) (this.midden.getY() - img_size/2 );
        int st = (int) this.img_size;
          Graphics2D g2d = (Graphics2D) g.create();

          g2d.setColor(Color.RED);

          AffineTransform at = new AffineTransform();
          at.setToRotation(Math.toRadians(angle), midden.getX(), midden.getY());
          g2d.setTransform(at);
          g2d.drawImage(bf, x, y, null);
          g2d.dispose();
        }

In the paint-function it rotate around itself with a certain angle. But the problem is the abstract function "update strand". What this should do is change the coordinates of the punt Midden to the location it actually is at. The parameter nulpoint_midden should not change and be constant, for calculation. For the object type outer strand (extends strand) the updatestrand is like beneath:

import java.awt.Image;


public class OuterStrand extends Strand{
    private double rotateconstant1 = 10; //tweaken tot perfecte laylength
    private double rotateconstant2 = (2*Math.PI/34); //tweaken tot perfecte laylength


    public OuterStrand(Punt c,Punt p, Image i) {
        super(c, p,i);
    }

    @Override
    public void updateStrand(Double z) {
        //       midden updaten
        double xpoint = nulpoint_midden.getX(); //original point
        double ypoint = nulpoint_midden.getY(); //original point
        double cCableX = super.middenCable.getX();
        double cCableY = super.middenCable.getY(); 
        double dx = nulpoint_midden.getX() - cCableX;
        double dy = ypoint - cCableY;
        System.out.println(xpoint+ "   " +ypoint) ;

        double curangle = Math.atan2(dy, dx);

        double dist     = Math.sqrt(dx*dx + dy*dy);

        double dangle = rotateconstant2 * z;
        double x1 = cCableX + dist * Math.cos(dangle + curangle);
        double y1 = cCableY + dist * Math.sin(dangle + curangle);

        super.midden.setX(x1);
        super.midden.setY(y1);

        //      rotate around itself
        super.angle = z * Math.PI * rotateconstant1;

    }


}

So the println gives the xpoint and ypoint, and this should be constant. But actually, it changes (so the punt nulpoint_midden changes value). I have no idea why this value changes. here is my print:

> 500.0   200.0
> 500.55439838802135   200.00051226305845
> 501.66318759079536   200.00461035702926
> 503.32632406233347   200.0184412864145
> 505.54367148773895   200.0512248625842
> 508.3149156018249   200.11525184075379
> 511.63945065512087   200.22587972200301
> 515.5162375992163   200.40152475227
> 519.9436341271526   200.66364828540742
> 524.9191967987913   201.03673531535162
> 530.439455611731   201.54826262515832
> 536.4996615512757   202.22865365075 (etcetera)

Because of this changing values, the representation is not correct. Due to the walking through the cable, it should rotate at a constant speed, but is actually accelerating.

I am sorry for the long explanation, but if someone sees my mistake and tells me what i am doing wrong that would be great. Thanks!


Solution

  • The final keyword means the reference may be assigned only once, but it doesn't mean that the object being referenced is somehow prevented from having its values changed.


    There's a potential bug in your constructor:

    nulpoint_midden = p;
    midden = p;
    

    The two instance variables refer to the same object: if you call a setter on midden, nulpoint_midden will appear to change too.