Java中的无状态对象是什么?


69

目前,我正在阅读“ Java并发实践”,其中包含以下语句:

由于线程访问无状态对象的操作不会影响其他线程上操作的正确性,因此无状态对象是线程安全的。

那么,什么是无状态对象?

Answers:


97

无状态对象是没有实例字段(实例变量)的类的实例。该类可能具有字段,但是它们是编译时常量(静态final)。

一个非常相关的术语是不可变的。不可变的对象可能具有状态,但是在调用方法时状态不会改变(方法调用不会为字段分配新值)。这些对象也是线程安全的。


22
如果对象具有字段(非静态),则它具有状态。如果它是不可变的,则它仅具有一种状态,但不是无状态的。
assylias 2012年

@ om-nom-nom的答案涉及得很深。
user2351818 '16

77

如果对象没有任何实例字段,则它是无状态的。如果它具有某些字段,则它也可以是无状态的,但是它们的值是已知的并且不会更改。

这是一个无状态的对象:

class Stateless {
    void test() {
        System.out.println("Test!");
    }
}

这也是一个无状态的对象:

class Stateless {
    //No static modifier because we're talking about the object itself
    final String TEST = "Test!";

    void test() {
        System.out.println(TEST);
    }
}

该对象具有状态,因此它不是无状态的。但是,它的状态仅设置一次,以后不会更改,这种类型的对象称为不可变的

class Immutable {
    final String testString;

    Immutable(String testString) {
        this.testString = testString;
    }

    void test() {
        System.out.println(testString);
    }
}

1
“它有一些领域,但众所周知它们从未改变。” 那将是一成不变的,而不是无状态的
亚述

1
@assylias不一定。如果这些字段是常量,并且它们是在编译时设置的,那么我们总是知道它们的值。这实际上意味着该对象不携带任何状态信息。
马尔科姆

1
无状态对象没有状态。具有字段的不可变对象不能转换到与其创建时所处的状态不同的状态,因此它们仅具有一种状态。
assylias 2012年

@assylias是的,但是我说的是对象的状态创建之前就已经知道。不是那些只设置了一次状态的状态。
马尔科姆

在您学习的同时,您还可以提供一个有状态对象的示例,但是有一个很好的解释。
VolkanGüven18年

3

无状态对象的概念与副作用的概念高度相关。简而言之,该对象在其下方没有字段,该字段可能具有不同的值,具体取决于方法调用的顺序。


2

没有状态的对象,例如实例变量,可以根据对象已经发生的变化而变化



1

只是澄清一下。您可以按照前面所述的方式将您的类视为无状态的,即使该类具有实例变量,并且该变量是final并且不可变的。

如果实例变量只是最终变量但是可变的(例如字符串列表),是的,不能更改变量的引用,但可以更改列表的内容以及类的状态。


0

一个对象绝对没有状态,那么此时重用它们就没有问题了,问题是:如果它们绝对没有状态,为什么不将所有方法设为静态,而从不创建一个方法呢?


“如果它们绝对没有状态,为什么不使所有方法静态化而根本不创建方法呢?” ----我们应该考虑多态性。或仅考虑OO的规则-“将实现与抽象分离”。在OO设计中很常见,我们有一个代表抽象的接口,而我们可以有多个实现-实现我们接口的类。在这种情况下,即使实现类是无状态的,但是仅具有静态方法的类也不起作用,因为它无法实现我们的接口。
user2351818 '16

0

如果不能在创建对象后更改其任何参数或值等,则该对象是线程安全的。


0

简单来说,对象的状态是指该对象中内部变量的值。

有状态-可以更改对象的状态,这意味着可以更改该对象的成员变量内部的值

如何更改值?

通过设置值。

什么时候可以设置该值?当变量不是最终值时。

因此,要使类变为无状态,请将变量定为final,以使该变量的值不能在setter中或在其他方法中都不能更改。它只能用于计算。


0
Stateless: it has no fields and references no fields from other classes.

特定计算的状态仅存在于局部变量中,这些局部变量存储在线程的堆栈中,并且只有执行线程才能访问。

一个线程访问方法/类不能影响另一线程访问相同方法/类的结果;因为两个线程不共享状态,所以好像它们正在访问不同的实例。

Since the actions of a thread accessing a stateless object cannot
affect the correctness of operations in other threads, Stateless objects are threadsafe.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.