java - 使用使用 getter 和 setter 的静态字段与声明为公共(public)的静态字段之间的区别

标签 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 方法。而且我看不出两者有什么区别。那么为什么不推荐第二个呢?

我之前也被告知按照我的方式有时会导致内存泄漏问题。但是第一个解决方案不会导致内存泄漏问题吗?

最佳答案

关于内存泄漏的问题

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

假设它不是静态的:

public class DataHolder
{
   String dataString;
}

这意味着每次执行 new DataHolder() 时,您都会有一个单独的 String 实例。使用静态数据字符串,将永远只有一个实例。

Getters 和 Setters 以及同步

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

我确实更改了您的代码的一些内容。第一个也是最明显的是没有用于静态变量的 this 关键字。正如我之前暗示的那样,因为它是静态的,所以它不属于任何实例。 “this”不是静态上下文中的事物。

我做的另一件事是将 synchronized 放在方法中。我这样做有两个原因。首先是偏好;有些人更喜欢在函数签名之外保持同步,这样它就被调用者混淆了,所以他们不做假设,因为函数是同步的。那就是偏好。我这样做的另一个原因是因为我想让它很明显,当你在签名中同步一个函数时,这就是它在“幕后”的实际样子。如前所述,由于没有“this”,它实际上会在类本身上进行同步。

我认为您可能需要阅读一些有关 static 关键字的资料。我认为您的困惑来自您不理解它的事实,并且您试图在理解静态本身之前回答有关静态变量的 getter 和 setter 的问题。这是我通过快速谷歌搜索找到的链接,可以帮助您入门: http://www.javatpoint.com/static-keyword-in-java

关于java - 使用使用 getter 和 setter 的静态字段与声明为公共(public)的静态字段之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31896094/

相关文章:

c - 如何在 C 语言的 Linux POSIX 模型中共享现有的动态数组?

java - 为什么@BeforeSuite和@AfterSuite在单独的线程中运行?

java - 从另一个列表中删除一个列表中的值

c - 为什么 char *T = "hello";不给内存泄漏?

perl - 为什么 IPC::SysV->shmget 以 EINVAL 响应?

c - shm_server 在执行同一程序时为其他用户给出打开错误

java - Java 方法中的最终变量

java - 自动解析自定义 jar 的依赖关系层次结构

IOSurface 在 iOS 12 及以上版本逐渐增加内存

程序异常终止导致的 C 潜在内存泄漏