How do I identify immutable objects in Java

后端 未结 15 1222
小蘑菇
小蘑菇 2020-11-30 22:40

In my code, I am creating a collection of objects which will be accessed by various threads in a fashion that is only safe if the objects are immutable. When an attempt is m

相关标签:
15条回答
  • You can use AOP and @Immutable annotation from jcabi-aspects:

    @Immutable
    public class Foo {
      private String data;
    }
    // this line will throw a runtime exception since class Foo
    // is actually mutable, despite the annotation
    Object object = new Foo();
    
    0 讨论(0)
  • 2020-11-30 23:03

    Check out joe-e, a implementation of capabilities for java.

    0 讨论(0)
  • 2020-11-30 23:04

    Like the other answerers already said, IMHO there is no reliable way to find out if an object is really immutable.

    I would just introduce an interface "Immutable" to check against when appending. This works as a hint that only immutable objects should be inserted for whatever reason you're doing it.

    interface Immutable {}
    
    class MyImmutable implements Immutable{...}
    
    public void add(Object o) {
      if (!(o instanceof Immutable) && !checkIsImmutableBasePrimitive(o))
        throw new IllegalArgumentException("o is not immutable!");
      ...
    }
    
    0 讨论(0)
  • 2020-11-30 23:05

    There is no reliable way to detect if a class is immutable. This is because there are so many ways a property of a class might be altered and you can't detect all of them via reflection.

    The only way to get close to this is:

    • Only allow final properties of types that are immutable (primitive types and classes you know are immutable),
    • Require the class to be final itself
    • Require that they inherit from a base class you provide (which is guaranteed to be immutable)

    Then you can check with the following code if the object you have is immutable:

    static boolean isImmutable(Object obj) {
        Class<?> objClass = obj.getClass();
    
        // Class of the object must be a direct child class of the required class
        Class<?> superClass = objClass.getSuperclass();
        if (!Immutable.class.equals(superClass)) {
            return false;
        }
    
        // Class must be final
        if (!Modifier.isFinal(objClass.getModifiers())) {
            return false;
        }
    
        // Check all fields defined in the class for type and if they are final
        Field[] objFields = objClass.getDeclaredFields();
        for (int i = 0; i < objFields.length; i++) {
            if (!Modifier.isFinal(objFields[i].getModifiers())
                    || !isValidFieldType(objFields[i].getType())) {
                return false;
            }
        }
    
        // Lets hope we didn't forget something
        return true;
    }
    
    static boolean isValidFieldType(Class<?> type) {
        // Check for all allowed property types...
        return type.isPrimitive() || String.class.equals(type);
    }
    

    Update: As suggested in the comments, it could be extended to recurse on the superclass instead of checking for a certain class. It was also suggested to recursively use isImmutable in the isValidFieldType Method. This could probably work and I have also done some testing. But this is not trivial. You can't just check all field types with a call to isImmutable, because String already fails this test (its field hash is not final!). Also you are easily running into endless recursions, causing StackOverflowErrors ;) Other problems might be caused by generics, where you also have to check their types for immutablity.

    I think with some work, these potential problems might be solved somehow. But then, you have to ask yourself first if it really is worth it (also performance wise).

    0 讨论(0)
  • 2020-11-30 23:06

    At my company we've defined an Attribute called @Immutable. If you choose to attach that to a class, it means you promise you're immutable.

    It works for documentation, and in your case it would work as a filter.

    Of course you're still depending on the author keeping his word about being immutable, but since the author explicitly added the annotation it's a reasonable assumption.

    0 讨论(0)
  • 2020-11-30 23:08

    Something which works for a high percentage of builtin classes is test for instanceof Comparable. For the classes which are not immutable like Date, they are often treated as immutable in most cases.

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