2015-08-08 89 views
3

我搜索了最佳方式来保存/共享要在全局和预期使用的数据,我发现了很多答案。引起我注意的一个方法是使用静态字段。然而,静态字段的方式表示有这样的:使用静态字段,使用Getter和Setter和静态字段之间的差异公开

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方法。我没有看到两者之间的区别。那么为什么不推荐第二个?

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

+0

'静态'方法很少用于这些尝试('get'或'set')。 – Andrew

+1

您正在隐藏实现细节(如所有封装)。这使您可以修改它而不会破坏代码。如果你想以“Data”类型存储数据,你可以改变字段变量,然后在'setString'方法(我建议改变名字)和'Data'中将'String'解析为'Data' ''getString'方法中的'String'。 –

+1

你可能想要阅读这个链接,主要讨论需要首先获取/设置方法! http://stackoverflow.com/questions/1568091/why-use-getters-and-setters?lq=1 – AADProgramming

回答

2

您对内存泄漏问题

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

想象一下,这是不是静态的:

public class DataHolder 
{ 
    String dataString; 
} 

这意味着,每一次这样做new DataHolder(),你将有一个字符串的一个单独的实例。用你的静态dataString,只会有一个实例。

getter和setter和同步

之所以你的实现是坏的,因为它不是线程安全的,因为米塔尔的Piyush指出。尽管他没有涉及任何细节,所以我想补充两分钱。

你不能说这仅仅是因为你只希望它在一个线程中使用,它只会在一个线程中使用。 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”,它实际上将在类本身上进行同步。

我想你大概可以使用一些关于static关键字的阅读。我认为你的困惑来自于你不了解它的事实,并且在理解静态本身之前,你试图回答关于静态变量的getter和setter的问题。这里有一个链接,我找到一个快速的谷歌搜索,可能让你开始: http://www.javatpoint.com/static-keyword-in-java

1

不知道内存泄漏。

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

1

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

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

如果您决定创建一个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; 
    } 
} 

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

而不是全局访问某些东西,您应该将依赖关系传递到需要的地方。例如,使用全局变量的方法。通过参数将值传递给它。这被称为依赖注入。