使用静态字段使用Getter和Setter以及声明为公共的静态字段之间的区别

时间:2015-08-08 16:26:22

标签: java memory-leaks shared-memory static-variables

我搜索了保存/共享全局使用数据的最佳方法,并且按照预期我找到了很多答案。引起我注意的方法之一是使用静态字段。然而,那里所说的静态场方式是这样的:

public class DataHolder
{
   private static String dataString;

   public static String getDataString
   {
      return dataString;
   }

   public static void setString(String dataString)
   {
      this.dataString = dataString;
   }
}

但我总是这样做:

public class DataHolder
{
   public static String dataString;
}

我只是想知道后者不比第一个容易得多吗?因为我不必设置任何getter和setter方法。我认为这两者之间没有任何区别。那么为什么不推荐第二个?

之前我也被告知,按照我的方式行事会导致内存泄漏问题。但第一种解决方案不会导致内存泄漏问题吗?

3 个答案:

答案 0 :(得分:1)

对内存泄漏不太了解。

但是:多个并行请求 - 多个线程,你肯定有一个线程问题 - 这不是线程安全的除非你照顾(例如使用 synchronized

答案 1 :(得分:1)

我更喜欢getter / setter,而不是公共领域。

这种封装允许您修改属性类型,而不会破坏使用它的代码。

如果您决定创建Data类型,而不是将其存储为String,该怎么办? (为了增加类型安全性)。

有了公共领域,这是不可能的。但是使用getter / setter,您可以执行允许此操作所需的解析:

class SomeClass {
    private static Data data;

    public static void setData(String data) {
        data = new Data(data);
    }

    public static String getData() {
        return data.toString();
    }
}

class Data {
    private String data;

    public Data(String data) {
        this.data = data;
    }

    public String toString() {
        return data;
    }
}

这不是内存泄漏问题,因为它与分配内存无关。使用该数据时,线程之间可能存在一些不一致,因为它不是线程安全的,但任何泄漏都不是使用静态而非正确多线程的结果。

您应该将依赖项传递到所需的位置,而不是全局访问。例如,使用全局变量的方法。通过参数将值传递给它。这称为依赖注入。

答案 2 :(得分:1)

关于内存泄漏的问题

我想先说这里没有内存泄漏问题。事实上,在两种情况下,它都与内存泄漏完全相反(它们在这方面是相同的)。对于DataHolder类,您只能有一个String实例(因为它是静态的,它不属于任何DataHolder实例)。

想象一下它不是静态的:

public class DataHolder
{
   String dataString;
}

这意味着每次执行new DataHolder()时,您将拥有一个单独的String实例。使用静态dataString,只会有一个实例。

获取和设置和同步

你的实施不好的原因是因为它不是线程安全的,正如Piyush Mittal指出的那样。虽然他没有详细说明,所以我想加两分钱。

你不能说这只是因为你只希望它在单个线程中使用,它只会在一个线程中使用。 Swing线程就是一个很好的例子,其中只有一个线程可以处理UI。在这种情况下,您可能希望只存在一个线程,并且可以执行此操作。但是,任何后台工作必须在SwingWorker线程中完成,因此在此处创建SwingWorker线程将提供数据竞争机会,因为现在有两个线程。出于这个原因,你应该总是有静态变量的getter和setter。

话虽如此,您提供的代码片段在两个示例之间完全相同(因为没有为新函数生成新的堆栈帧,因为没有同步)。你想这样做:

public class DataHolder{
  private static String dataString;
  public static String getDataString(){
    synchronized(DataHolder.class){
      return DataHolder.dataString;
    }
  }

  public static void setString(String dataString){
    synchronized(DataHolder.class){
      DataHolder.dataString = dataString;
    }
  }
}

我确实更改了有关您代码的一些内容。第一个也是最明显的是没有这个关键字用于静态变量。正如我之前所暗示的,因为它的静态不属于任何实例。 '这'在静态环境中不是一件事。

我做的另一件事是把方法同步到内部。我这样做有两个原因。首先是偏好;有些人喜欢从函数签名中保持同步,因此它会被调用者混淆,因此他们不会做出假设,因为函数是同步的。这是偏好。我这样做的另一个原因是因为我想明确表示,当你在签名中同步一个函数时,这就是它实际上看起来的样子'。如上所述,由于没有'这个',它实际上会在类本身上同步。

我想你可能会使用一些关于static关键字的阅读。我认为你的困惑来自于你不理解它,并且在理解静态变量之前,你试图回答关于静态变量的getter和setter的问题。以下是我发现的快速谷歌搜索链接,可能会让您入门: http://www.javatpoint.com/static-keyword-in-java