Which java classes are immutable

Immutable Classes in Java

In Java, an immutable object is one whose state can not be changed once created. Immutable objects are persistent views of their data without a direct option to change it. To change the state, we must create a new copy of such an object with the intended changes.

In this post, we will learn immutability in detail, creating an immutable object and its advantages.

Immutability is a characteristic of Java objects that makes them immutable to future changes once they have been initialized. Its internal state cannot be changed in any way.

Take the example of java.lang.String class which is an immutable class. Once a String is created, there is no way we can change the content of that String. Every public API in String class returns a new String with the modified content. The original String always remains the same.

String string = "test"; String newString = string.toLowerCase(); //Creates a new String

2. Immutability in Collections

Similarly, for Collections, Java provides a certain degree of immutability with three options:

  • Unmodifiable collections
  • Immutable collection factory methods (Java 9+)
  • Immutable copies (Java 10+)
Collections.unmodifiableList(recordList); //Unmodifiable list List.of(new Record(1, "test")); //Factory methods in Java 9 List.copyOf(recordList); //Java 10

Note that such collections are only shallowly immutable, meaning that we can not add or remove any elements, but the collection elements themselves aren’t guaranteed to be immutable. If we hold the reference of a collection element, then we can change the element’s state without affecting the collection.

Читайте также:  Windows java latest version of

In the following example, we cannot add or remove the list items, but we can change the state of an existing item in the list.

List list = List.of(new Record(1, "value")); System.out.println(list); //[Record(id=1, name=value)] //list.add(new Record()); //UnsupportedOperationException list.get(0).setName("modified-value"); System.out.println(list); //[Record(id=1, name=modified-value)]
@Data @NoArgsConstructor @AllArgsConstructor class Record

To ensure complete immutability, we must make sure that we only add immutable instances in the collections. This way, even if somebody gets a reference to an item in the collection, it cannot change anything.

3. How to Create an Immutable Class?

Java documentation itself has some guidelines identified to write immutable classes in this link. We will understand what these guidelines actually mean.

  • Do not provide setter methods. Setter methods are meant to change an object’s state, which we want to prevent here.
  • Make all fields final and private. Fields declared private will not be accessible outside the class, and making them final will ensure that we can not change them even accidentally.
  • Do not allow subclasses to override methods. The easiest way is to declare the class as final. Final classes in Java can not be extended.
  • Special attention to “immutable classes with mutable fields“. Always remember that member fields will be either mutable or immutable. Values of immutable members (primitives, wrapper classes, String etc) can be returned safely from the getter methods. For mutable members (POJO, collections etc), we must copy the content into a new Object before returning from the getter method.

Let us apply all the above rules to create an immutable custom class. Notice that we are returning a new copy of ArrayList from the getTokens() method. By doing so, we are hiding the original tokens list so no one can even get a reference of it and change it.

final class Record < private final long id; private final String name; private final Listtokens; public Record(long id, String name, List tokens) < this.id = id; this.name = name; this.tokens = tokens; >public long getId() < return id; >public String getName() < return name; >public List getTokens() < return new ArrayList<>(tokens); > @Override public String toString() < return "RecordArrayList tokens = new ArrayList<>(); tokens.add("active"); Record record = new Record(1, "value", tokens); System.out.println(record); //Record record.getTokens().add("new token"); System.out.println(record); //Record

4. Immutability with Java Records

Java records help reduce the boilerplate code by generating the constructors and getters at compile time. They can also help create immutable classes with very few lines of code.

For example, we can rewrite the above Record class as follows. Note that records generate the standard getters, so if we want to return a new copy of a mutable reference, we must override the corresponding method.

record Record(long id, String name, List tokens) < public Listtokens() < return new ArrayList<>(tokens); > >

Now let us test the immutability again.

ArrayList tokens = new ArrayList<>(); tokens.add("active"); Record record = new Record(1, "value", tokens); System.out.println(record); //Record record.tokens().add("new token"); System.out.println(record); ////Record

5. Immutable Classes in JDK

Apart from your written classes, JDK itself has lots of immutable classes. Given is such a list of immutable classes in Java.

  • java.lang.String
  • Wrapper classes such as Integer, Long, Double etc
  • java.math.BigInteger and java.math.BigDecimal
  • Unmodifiable collections such as Collections.singletonMap()
  • java.lang.StackTraceElement
  • Java enums
  • java.util.Locale
  • java.util.UUID
  • Java 8 Date Time API – LocalDate, LocalTime etc.
  • record types

Immutable objects provide a lot of advantages over mutable objects. Let us discuss them.

  • Predictability: guarantees that objects won’t change due to coding mistakes or by 3rd party libraries. As long as we reference a data structure, we know it is the same as at the time of its creation.
  • Validity: is not needed to be tested again and again. Once we create the immutable object and test its validity once, we know that it will be valid indefinitely.
  • Thread-safety: is achieved in the program as no thread can change immutable objects. It helps in writing code in a simple manner without accidentally corrupting the shared data objects.
  • Cacheability: can be applied to immutable objects without worrying about state changes in the future. Optimization techniques, like memoization, are only possible with immutable data structures.

This tutorial taught us to create an immutable java class with mutable objects and immutable fields.

In Java, immutable classes are:

  • are simple to construct, test, and use
  • are automatically thread-safe and have no synchronization issues
  • do not need a copy constructor
  • do not need an implementation of clone()
  • allow hashCode() to use lazy initialization, and to cache its return value
  • do not need to be copied defensively when used as a field
  • make good Map keys and Set elements (these objects must not change state while in the collection)
  • have their class invariant established once upon construction, and it never needs to be checked again
  • always have “failure atomicity” (a term used by Joshua Bloch) : if an immutable object throws an exception, it’s never left in an undesirable or indeterminate state

We also saw the benefits which immutable classes bring in an application. As a design best practice, always aim to make your application Java classes to be immutable. In this way, you can always worry less about concurrency related defects in your program.

Источник

Complete List of immutable JDK classes?

is there a list of de-facto immutable classes in the jdk? technically Immutable classes include the obvious Integer, Double etc.. de-facto immutable will include for example java.lang.String — it might technically be mutable but de-facto it is not. Also, are there Interfaces/Abstract classes which are required (as stated in the javadoc) to be immutable? if you cannot provide a complete List, i would already be happy if you know a bunch of classes which state immutability in its javadoc..

not a de facto list but some immutable classes are discussed here: stackoverflow.com/questions/5124012/immutable-classes

i would download the javadocs html archive and grep them for «immutable» and proceed.. but thats just me.

de facto: as stated in the javadoc; technically: final classes, all fields final, do not contain arrays or interfaces/abstract classes as fields, all fields technically immutable.

3 Answers 3

I try to compile the list as much as I can:

  1. java.lang.String The wrapper classes for the primitive types:
  2. java.lang.Integer
  3. java.lang.Byte
  4. java.lang.Character
  5. java.lang.Short
  6. java.lang.Boolean
  7. java.lang.Long
  8. java.lang.Double
  9. java.lang.Float
  10. java.lang.StackTraceElement (used in building exception stacktraces)
  11. Most of the enum classes
  12. java.math.BigInteger
  13. java.math.BigDecimal
  14. java.io.File
  15. java.awt.Font
  16. java.awt.BasicStroke
  17. java.awt.Color
  18. java.awt.GradientPaint,
  19. java.awt.LinearGradientPaint
  20. java.awt.RadialGradientPaint,
  21. java.awt.Cursor
  22. java.util.Locale
  23. java.util.UUID
  24. java.util.Collections
  25. java.net.URL
  26. java.net.URI
  27. java.net.Inet4Address
  28. java.net.Inet6Address
  29. java.net.InetSocketAddress
  30. most subclasses of java.security.Permission

This is a useful list. I think it would make sense to exclude non-instantiable classes, like Collections .

You can use MutabilityDetector and feed it JARs from the JDK to enumerate most immutable classes. It’s «most» because it’s so strict that even the tiny bit of state change in java.lang.String is enough to make it considered mutable, but the goal is to account for this by 1.0 release.

Here’s an example of it’s use. This is what I used to get most of the immutable JDK 1.7 classes on OSX:

java -jar MutabilityDetector-0.9.5.jar -r IMMUTABLE -cp /Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/jre/lib/rt.jar

Источник

Examples of immutable classes

All answers below (expect one or two) explains how to create Immutable class or says what is immutable rather than answering the actual question asked.

10 Answers 10

Some famous immutable classes in the Standard API:

  • java.lang.String (already mentioned)
  • The wrapper classes for the primitive types: java.lang.Integer, java.lang.Byte, java.lang.Character, java.lang.Short, java.lang.Boolean, java.lang.Long, java.lang.Double, java.lang.Float
  • java.lang.StackTraceElement (used in building exception stacktraces)
  • Most enum classes are immutable, but this in fact depends on the concrete case. (Don’t implement mutable enums, this will screw you up somewhen.) I think that at least all enum classes in the standard API are in fact immutable.
  • java.math.BigInteger and java.math.BigDecimal (at least objects of those classes themselves, subclasses could introduce mutability, though this is not a good idea)
  • java.io.File. Note that this represents an object external to the VM (a file on the local system), which may or may not exist, and has some methods modifying and querying the state of this external object. But the File object itself stays immutable. (All other classes in java.io are mutable.)
  • java.awt.Font — representing a font for drawing text on the screen (there may be some mutable subclasses, but this would certainly not be useful)
  • java.awt.BasicStroke — a helper object for drawing lines on graphic contexts
  • java.awt.Color — (at least objects of this class, some subclasses may be mutable or depending on some external factors (like system colors)), and most other implementations of java.awt.Paint like
    • java.awt.GradientPaint,
    • java.awt.LinearGradientPaint
    • java.awt.RadialGradientPaint,
    • (I’m not sure about java.awt.TexturePaint)

    One could say the primitive types are immutable, too — you can’t change the value of 42, can you?

    is Class AccessControlContext a immutable class

    AccessControlContext does not have any mutating methods. And its state consists of a list of ProtectionDomains (which is an immutable class) and a DomainCombiner. DomainCombiner is an interface, so in principle the implementation could do something different on each call.

    In fact, also the behaviour of the ProtectionDomain could depend on the current policy in force — it is disputable whether to call such an object immutable.

    There are no objects of type AccessController, since this is a final class with no accessible constructor. All methods are static. One could say AccessController is neither mutable nor immutable, or both.

    The same is valid for all other classes which can’t have objects (instances), most famously:

    • java.lang.Void
    • java.lang.System (but this has some mutable static state — in , out , err )
    • java.lang.Math (this too — the random number generator)
    • java.lang.reflect.Array
    • java.util.Collections
    • java.util.Arrays

    Источник

Оцените статью