Статический класс обновляет статические переменные, но статические методы не обновляют статические переменные - PullRequest
0 голосов
/ 29 апреля 2011

Я просмотрел несколько страниц, но на большинстве из них, похоже, возникают проблемы с пониманием того, что означает статическое. У меня есть проблема в том, что мы используем статический класс, FocusListener и ActionListener.Класс, который обрабатывает события, вызывает статический класс, и когда JTextfield заполняется и вкладывается в FocusListener, мгновенно обновляет эту статическую переменную.Когда все JTextfields заполнены и FocusListener обновил переменные, происходит отправка JButton.Как только кнопка нажата, статические методы вызываются для завершения любых переменных, которые вычисляются с использованием ранее обновленных переменных.Пользователь не знает об этом.Переменные не обновляются, и мне любопытно, правильно ли я это реализую?Заранее спасибо.

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class WellParameters extends JInternalFrame implements FocusListener, ActionListener {
    JLabel  measuredDepthL, ..., pitGainL, drillBitSizeL, 
                mudInActivePitsL, mainPanelLabel;
        JTextField  measuredDepthT, ..., pitGainT, drillBitSizeT, mudInActivePitsT;
        JPanel  mainPanel, firstPanel, secondPanel, thirdPanel, fourthPanel, submitButtonPanel;
        JButton submitButton;

        WellParameters() {  
            super("Well Parameters", true, true, false, true);
            this.setBounds(0, 0, 600, 385);
            this.setVisible(true);
            this.setLayout(new BorderLayout());

            ...//GUI Stuff

            this.add(submitButtonPanel, BorderLayout.SOUTH);
        }
    @Override
    public void focusGained(FocusEvent e) {} //Ignore this!

    @Override
    public void focusLost(FocusEvent e) {
        try {
            if(e.getSource() == measuredDepthT) {
                KillWellCalculations.measuredDepth = Integer.parseInt(measuredDepthT.getText());

              ...//Others 

            } else if(e.getSource() == mudInActivePitsT) {
                KillWellCalculations.mudInActivePits = Double.parseDouble(mudInActivePitsT.getText());
            }
        } catch (Exception ignore) {}

    }
    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            if(e.getSource() == submitButton) {
            System.out.println(KillWellCalculations.pumpEfficiency);
            KillWellCalculations.setPressureBeforeCasingBurstAndFormationFracture(); //Doesn't work
            KillWellCalculations.setCirculatingPressures();
            KillWellCalculations.setTriplexPumpCapacity();
            System.out.println(KillWellCalculations.mudInActivePits);
            System.out.println(KillWellCalculations.pumpFactor);
            System.out.println(KillWellCalculations.finalCirculatingPressure);}
        }
        catch(Exception ignore) {}
    }
}

Это был GUI, а это статический класс ... Это 2 отдельных класса.Не в том же файле.пакет killwellsheet;

public class KillWellCalculations {

    static int measuredDepth;           //Total Depth from open hole to bottom

        ... //Tons of other variables

    static double totalStrokes;         //add strokes

    //Used to set different circulating pressures for the well
    public static void setCirculatingPressures() {
        initialCirculatingPressure = circulatingPressureKillRate + shutInDrillPipePressure;
        finalCirculatingPressure = circulatingPressureKillRate * (killMudWeight/currentMudWeight);
    }   
    //Calculates capacity of anypipe
    private static double pipeCapacity(double length, double insideDiameter) {
        return length * ((insideDiameter*insideDiameter)/1029.4);
    }
    //Calculates capacity of the annulus/open hole
    private static double annulusCapacity(double length, double insideDiameter, double outsideDiameter) {
        return length * (((insideDiameter*insideDiameter)-(outsideDiameter*outsideDiameter))/1029.4);
    } 

         ... //Other functions

    //Set the casing burst pressure
    public static void setPressureBeforeCasingBurstAndFormationFracture() {
        beforeCasingBurst = burstPressure*0.70;
        beforeFormationFracture = (0.052*casingShoeDepth)*(fracGradientMWEquivalent - currentMudWeight);
    }
    public static void bariteNeedAndVolumeIncrease() {
        bariteSacksRequired = (totalMudVolume/100)*((1099*(killMudWeight-currentMudWeight))/(28.35-killMudWeight));
        increaseInMudVolume = 0.091*bariteSacksRequired;
    }
    public static void pumpStrokes() {
        surfaceToBit = (mudInDrillString)/pumpFactor;
        bitToSurface = (mudInAnnulus)/pumpFactor;
        totalStrokes = surfaceToBit + bitToSurface;
    }
}//end class

1 Ответ

0 голосов
/ 29 апреля 2011

Некоторые пояснения ... Читая ваш код, я вижу только то, что ваш класс WellParameters реализует интерфейсы FocusListener и ActionListener (не статические классы). Насколько я могу понять из вашего кода, методы focusGained (FocusEvent e) и focusLost (FocusEvent e) реализованы из прежнего интерфейса и обновляют значения статического класса. и вы зависите от тех же вычисленных значений в событии ActionListener actionPerformed () . Проблема, с которой вы здесь сталкиваетесь, - это состояние гонки относительно статических значений экземпляров.

http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html А.3.4 Недоступен

Объект переходит в недоступное состояние когда нет более сильных ссылок на него существовать. Когда объект недоступен, это кандидат на сбор. Заметка формулировка: только потому, что объект кандидат на сбор не значит, это будет немедленно собрано. JVM может отложить сбор пока нет срочной необходимости память, используемая объект. Важно отметить, что не просто сильная ссылка держать объект в памяти. Эти должны быть ссылки на эту цепь из корень сборки мусора. Корни GC специальный класс переменных, который включает в себя

Временные переменные в стеке (любого потока) Статические переменные (из любого класса) Специальные ссылки из нативного кода JNI

Основываясь на этой документации по сборке мусора, я подозреваю, что ВСЕ статические ссылки вашего класса KillWellCalculations были пригодны для сбора мусора после вызова методов FocusEvent, и поэтому они недоступны к моменту запуска события actionPerformed () .

Вы все еще можете использовать статические методы класса KillWellCalculations в качестве служебного класса, только если этот класс используется другими классами. Если нет, вы можете преобразовать его в класс Value, который содержит вычисления для вас, БЕЗ статических ссылок. Поскольку вам нужно иметь ссылку на экземпляр класса, который содержит значения вычислений ... Например:

public Class CalculatedValues {
     private int measuredDepth;
     private double mudInActivePits;

     public static CalculatedValues makeNew() {
          return new CalculatedValues();
     }

     public void setMeasuredDepth(String measuredDepthTString) {
           if (measuredDepthTString == null) {
                throw new IllegalArgumentException("The measured depth must be provided.");
           }
           try {
                this.measuredDepth = Integer.parseInt(measuredDepthTString);
           } catch(NumberFormatException nfe) {
                throw new IllegalArgumentException("The value provided is not an interger.");
           }
     }
     public int getMeasuredDepth() {
          return measuredDepth;
     }

     public void setMudInActivePitsT(String mudInActivePitsTString) {
           if (mudInActivePitsTString == null) {
                throw new IllegalArgumentException("The measured mudInActivePits must be provided.");
           }
           try {
                this.mudInActivePits = Double.parseDouble(measuredDepthTString);
           } catch(NumberFormatException nfe) {
                throw new IllegalArgumentException("The value provided is not an double.");
           }
     }
     public double getMeasuredDepth() {
          return mudInActivePits;
     }

     //...
     //...
     // MORE THE OTHER VALUES/PROPERTIES IMPORTANT/NEEDED BY THE CALCULATION. 

     public void doAllCalculations() {
          // YOU HAVE TO IMPLEMENT THE LOGIC FOR THOSE ONES, OPTIONALLY USING THE SAME UTILITY/HELPER STATIC METHODS FROM 
          setPressureBeforeCasingBurstAndFormationFracture();
          setCirculatingPressures();
          setTriplexPumpCapacity();
     }
}

Затем измените конструктор класса, чтобы получить экземпляр объекта значения:

... 
...
// THE VALUE OBJECT REFERENCE WITH THE VALUES YOU NEED TO HOLD DURING THE FORM INTERACTION
private CalculatedValues calculatedValues;

WellParameters() {  
    super("Well Parameters", true, true, false, true);
    this.setBounds(0, 0, 600, 385);
    this.setVisible(true);
    this.setLayout(new BorderLayout());

    ...//GUI Stuff

    this.add(submitButtonPanel, BorderLayout.SOUTH);

    // THE VALUE OBJECT REFERENCE...
    calculatedValues = CalculatedValues.makeNew();
}

Затем обновите ссылку с расчетом:

@Override
public void focusLost(FocusEvent e) {
    try {
        if(e.getSource() == measuredDepthT) { 
            //KillWellCalculations.measuredDepth = Integer.parseInt(measuredDepthT.getText());
            // the exceptions thrown can be caught in the catch below and you can display the error message from the value class.
            calculatedValues.setMeasuredDepth(measuredDepthT.getText());

          ...//Others 

            // collect other values as well...

        } else if(e.getSource() == mudInActivePitsT) {
            //KillWellCalculations.mudInActivePits = Double.parseDouble(mudInActivePitsT.getText());
            // do try/catch for the possible runtime exception and display an error message
            calculatedValues.setMudInActivePitsT(mudInActivePitsT.getText());

        }
    } catch (Exception ignore) { 
    }

}

Обновления на последнем шаге также с использованием ссылки на экземпляр:

  @Override
    public void actionPerformed(ActionEvent e) {
      try {
        if(e.getSource() == submitButton) {
        System.out.println(KillWellCalculations.pumpEfficiency);
        // THE REFERENCES THAT THIS STATIC METHOD USE WERE ALL GARBAGE-COLLECTED AT THE TIME OF THE CALL... IF SHOULD HAVE THE CALCULATED METHODS IN THE VALUE CLASS. SOMETHING LIKE THE FOLLOWING:
        // KillWellCalculations.setPressureBeforeCasingBurstAndFormationFracture(); //Doesn't work
        //KillWellCalculations.setCirculatingPressures();
        //KillWellCalculations.setTriplexPumpCapacity();
        //System.out.println(KillWellCalculations.mudInActivePits);
        //System.out.println(KillWellCalculations.pumpFactor);
        //System.out.println(KillWellCalculations.finalCirculatingPressure);}

        // DO THE FINAL CALCULATION IN A SINGLE METHOD IN THE VALUE OBJECT.
        calculatedValues.doAllCalculations();

        // HERE ARE THE GETTERS FROM THE CALCULATED VALUES OF THE DO ALL CALCULATIONS YOU HAVE TO IMPLEMENT.
        System.out.println(calculatedValues.getMudInActivePits());
        System.out.println(calculatedValues.getPumpFactor());
        System.out.println(calculatedValues.getFinalCirculatingPressure());}

        // CONSIDERING YOU'RE DONE WITH THE VALUES, JUST CLEAR THE INSTANCE VALUES
        // AS THIS REFERENCE IS NOT STATIC AND IT WILL NOT BE GARBAGE-COLLECTED. 
        calculatedValues.clearValues();
    }
    catch(Exception ignore) {}
  }

Я проделал некоторую работу в обратном направлении, связанную с графическим интерфейсом ... Вы можете увидеть очень похожий пример на http://code.google.com/p/marcellodesales-cs-research/source/browse/trunk/grad-ste-ufpe-brazil/ptf-add-on-dev/src/br/ufpe/cin/stp/ptfaddon/view/swing/execution/JWizardInternalFrame.java

Удачи!

...