【问题标题】:Static class updates static variables, but static methods do not update static variables静态类更新静态变量,但静态方法不更新静态变量
【发布时间】:2011-04-29 00:11:04
【问题描述】:

我搜索了几页,但大多数似乎只是对静态的含义有理解问题。我遇到的问题在于我们使用的是静态类、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

【问题讨论】:

  • 我使用这些线条打印作为故障排除。他们告诉我这些方法是否有效。
  • 为什么这里的变量和方法都是静态的?静态内部类只是意味着内部类不需要外部类的实例存在。
  • 是的,正如 Hovercraft 所说,这里完全没有理由使用静态方法和静态变量。它只会使一切复杂化。
  • 它们是两个独立的类。这些文件是 KillWellCalculations.java 和 WellParameters.java
  • 您可能希望打印出堆栈跟踪以在您的 catch 子句中进行调试。忽略异常会使代码行为难以遵循。

标签: java static-methods


【解决方案1】:

一些澄清...通过阅读您的代码,我唯一看到的是您的类 WellParameters 实现了接口 FocusListener 和 ActionListener(不是静态类)。据我从您的代码中可以看出,方法 focusGained(FocusEvent e)focusLost(FocusEvent e) 是从前一个接口实现的,并更新了静态类,您将依赖于 ActionListener 事件 actionPerformed() 中的相同计算值。您在这里面临的问题是关于静态实例值的竞争条件。

http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html A.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) {}
      }
    

    我做了一些与 GUI 相关的工作...您可以在 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 看到一个非常相似的示例

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-30
      • 2015-07-22
      • 2012-06-29
      相关资源
      最近更新 更多