在Java中使用静态变量的优势

在Java中使用静态变量的优势,java,random,static,Java,Random,Static,假设我有两个这样的课程: class A{ private static Random random = new Random(); public A(){ // Do something. } public Integer methodGetsCalledQuiteOften(){ return random.nextInt(); } } class B{ private Random ra

假设我有两个这样的课程:

class A{  
    private static Random random = new Random();  

    public A(){  
        // Do something.
    }

    public Integer methodGetsCalledQuiteOften(){
        return random.nextInt();
    }
}

class B{  
     private Random random;  

     public A(){  
         random = new Random();
         // Do something.
     }

     public Integer methodGetsCalledQuiteOften(){
         return random.nextInt();
     }
}
在两个类都被多次实例化,并且这两个类的“实例”方法
methodGetsCalledQuiteOften
都被多次调用的场景中,与创建新的
Random()相比,在类a中使用包含
Random()
的静态变量有什么真正的优势/劣势(时间、内存)
对象在每个实例中,比如在类B中

该应用程序是多线程的,更高级别的随机性是如此,因此我认为我将使用静态
SecureRandom
。如果在评测之后这将是一个真正的速度因素,我可能会选择其他东西。

真正的优势/劣势取决于真正的代码。换句话说,它取决于创建
B
的频率与调用方法的频率等。您应该分析应用程序,看看它是否产生合理的差异

A的表现会比B好吗?当然但你是否会注意到这一点取决于你的使用习惯。A会比B使用更少的内存吗?当然可以,但您是否在意取决于您保留了多少个A/B实例


实际上,唯一需要考虑的是决定论。因为您没有为随机实例指定种子,所以我认为您并不关心是否可以从随机实例中复制数字序列。但值得注意的是……如果您有一个共享的随机数,那么为a的某个实例保证一个确定的数字序列要比为B的每个实例保证一个数字序列困难得多。

访问静态资源不是线程安全的。在线程化环境中,您可能会得到奇怪的/不可预测的结果。

当实例不需要更改或希望在实例之间共享时,请使用静态变量

private final static int SOME_CONSTANT=1;
这就是一个例子

public class USA {
    private final static Map statesOfTheUnion = new HashMap();
    // etc
}

可能是另一个。在后一种情况下,我们不希望状态在实例之间发生变化。因此,每个实例都有自己的副本是没有意义的。

好吧,因为
Random
类采取了必要的步骤来确保线程安全,所以我认为将其设置为静态没有问题

而且由于它的状态包含单个
原子长
对象(8字节),所以不会浪费太多内存(除非您计划创建大量
B
实例)


所以,我想说,这两种方式都没有什么区别。

如果你的程序是单线程的,你的
Random
应该是类成员(
static
)。这会更有效率。当使用
SecureRandom
时,这一点更为重要,这可能需要相对较长的时间进行初始种子设定

如果多个线程最终将调用
methodGetScalledQuiteOffen()
,那么问题就要复杂一些。该类是线程安全的,但在并发更改期间保护其状态所需的开销可能相当于创建新的独立的
随机
实例


我可能会一直使用
静态
成员,直到我注意到线程之间对于随机数生成器的大量争用,这可能永远不会发生。

就时间和内存而言,我想不出有什么大的优势(静态变量将是类定义的一部分,而不是堆上的)。但是,当您知道将从多个位置访问对象时,静态变量非常有用。hvgotcodes是正确的,尽管使用静态资源不是线程安全的。但是如果您只读取静态值,那么使用线程进行读取就可以了


它将使您不必为了使用
随机

而将对已启动对象(A或B)的引用传递到其他对象。如果您正在使用,请注意,它是一个与相关性相关的已知问题。对我来说,真正的问题是应用程序应该从单个系列中选择,还是从多个具有不同种子的系列中选择。

尽管实例化类a的速度比类B快很多(10倍),但这只有在每秒执行100.000次时才重要

关于线程安全,我的理解是.nextInt()基于.next(),它应该是线程安全的。因此,多线程在这里不应该出现任何问题

但更重要的是,这两类人的行为可能有所不同。类A的实例将为每个类提供某种程度上随机的数字序列,但类B的实例可能会为每个类提供相同的“随机”数字序列(这种行为在不同的平台上可能不同!)。规范规定:

如果创建了两个随机变量实例 用同样的种子,同样的 方法调用的顺序是为 每一次,他们都会生成并返回 相同的数字序列


因此,如果随机性很重要,你可能会考虑给随机构造函数提供一个唯一的种子,或者更好地用较慢的java .Security。SecurErr.O/P> > P>随机地对可变的静态MyKay.</P>说“不”。 这是个糟糕的设计。通常引用的结果是可测试性失败。如果不重新加载类,则很难复制。糟糕的设计也有很多其他原因。仅举一例,默认情况下,类应该是线程无关的。添加一个可变的静态变量,你就会对线程怀有敌意——这是一个不好的地方

每次创建一个新实例似乎都是浪费。当然,不要过早地进行优化(如果进行优化,就不会使用
java.util.Random
)。初始see递增也可能导致问题


最好的方法是传入一个实例(“从上面参数化”或“正确使用构造函数”)。然后,您可以测试、复制、模拟等。您的效率很高,可以在不同的实现中翻转。

静态变量的好处(要点):

  • 可以在不占用额外内存的情况下定义常量(每个类一个)

  • 常数可以在无需立即访问的情况下访问