Why are Java wrapper classes immutable?

前端 未结 9 1672
日久生厌
日久生厌 2020-12-02 17:25

I know the usual reasons that apply to general immutable classes, viz

  1. can not change as a side effect
  2. easy to reason about their state
  3. inhe
相关标签:
9条回答
  • 2020-12-02 17:56

    For example, consider the following java program:

    class WhyMutable 
    {
        public static void main(String[] args) 
        {
            String name = "Vipin";
            Double sal = 60000.00;
            displayTax(name, sal);
        }
    
        static void displayTax(String name, Double num) {
            name = "Hello " + name.concat("!");
            num = num * 30 / 100;
            System.out.println(name + " You have to pay tax $" + num);
        }
    }
    
    Result: Hello Vipin! You have to pay tax $18000.0
    

    This is the case with pass by reference of wrapper class parameters as well. And, if strings and wrapper classes are non-final, anybody can extend those classes and write their own code to modify the wrapped primitive data. So, in order to maintain Data Integrity, the variables which we are using for data storage must be read-only,

    i.e., Strings and Wrapper classes must be final & immutable and “pass by reference” feature should not be provided.

    0 讨论(0)
  • 2020-12-02 18:00

    There are mutable, thread safe wrappers as well for some types.

    AtomicBoolean
    AtomicInteger
    AtomicIntegerArray
    AtomicLong
    AtomicLongArray
    AtomicReference - can wrap a String.
    AtomicReferenceArray
    

    Plus some exotic wrappers

    AtomicMarkableReference - A reference and boolean
    AtomicStampedReference - A reference and int
    
    0 讨论(0)
  • 2020-12-02 18:06

    However, wrapper classes represent primitive types, and primitive types (except String) are mutable.

    Firstly, String isn't a primitive type.

    Secondly, it makes no sense to talk about the primitive types being mutable. If you change the value of a variable like this:

    int x = 5;
    x = 6;
    

    That's not changing the number 5 - it's changing the value of x.

    While the wrapper types could have been made mutable, it would have been annoying to do so, in my view. I frequently use readonly collections of these types, and wouldn't want them to be changeable. Very occasionally I want a mutable equivalent, but in that case it's easy enough to come up with one, or use the Atomic* classes.

    I find myself wishing that Date and Calendar were immutable far more often than I find myself wanting Integer to be mutable... (Of course I normally reach for Joda Time instead, but one of the benefits of Joda Time is immutability.)

    0 讨论(0)
  • 2020-12-02 18:06

    For your info: if you want mutable holder classes, you can use the Atomic* classes in the java.util.concurrent package, e.g. AtomicInteger, AtomicLong

    0 讨论(0)
  • 2020-12-02 18:07

    The primitive types are mutable, but they are not shareable - that is no two sections of code will ever be referring to the same int variable (they are always passed by value). So you can change your copy and no one else sees the change, and vice versa. As Phillip shows in his answer, that would not be the case with mutable wrapper classes. So my guess is that they had a choice when the wrapped the primitive data types between:

    matching the fact that you can change the value of a primitive type,

    versus

    matching the fact that primitive types can be passed around and no changes by a user will be seen by any other user of the data.

    And they chose the latter, which required immutability.

    0 讨论(0)
  • 2020-12-02 18:14

    Here is an example where it would be quite bad when Integer would be mutable

    class Foo{
        private Integer value;
        public set(Integer value) { this.value = value; }
    }
    
    /* ... */
    
    Foo foo1 = new Foo();
    Foo foo2 = new Foo();
    Foo foo3 = new Foo();
    Integer i = new Integer(1);
    foo1.set(i);
    ++i;
    foo2.set(i);
    ++i;
    foo3.set(i);
    

    Which are the values of foo1, foo2 and foo3 now? You would expect them to be 1, 2 and 3. But when Integer would be mutable, they would now all be 3 because Foo.value would all point to the same Integer object.

    0 讨论(0)
提交回复
热议问题