I have several final properties defined in a Java class with constructor which has all the information to initialize the properties.
public final class A {
private final Object prop1;
private final Object prop2;
public A(Object someObj, String prop1Str, String prop2Str) {
//initialize prop1 and prop2 based on information provided from someObj, prop1Str and prop2Str parameter (1)
}
}
I would like to introduce a new constructor in class A with following signature and semantic
public A(Object obj1, Object obj2, String prop1Str, String prop2Str) {
//use obj1 and obj2 to initialize the someObj
//initialize prop1 and prop2 based on information provided from someObj, prop1Str and prop2Str parameter (1)
}
How can I reuse the code in (1)? I tried with helper private methods but Java6 gives me a compilation error since the properties of the class are final and they may not have been initialized.
EDIT:
Note that I can not call the first constructor from the second one in the first line since first I need to do some calculations and then reuse the code in question.
You've found a shortcoming of final :-)
Java must make sure that all final fields are initialized when the constructor is finished. Because of various other limitations, that means the fields must be assigned inside the code block of the constructor.
Workarounds:
Use static helper methods (which, by design, don't depend on the state of the class and therefore any final fields).
Use a builder pattern (put all parameters in a helper class which has a build() method that returns the desired result).
Don't use final. You can get the same event by omitting setters. If you are afraid that code in the class might change the fields, move them to a new base class.
Firstly, are you sure your constructors are not getting out of hand?
If you are determined (for now) on going for many constructor root, then you can call one constructor from another. Needs to be first line of constructor usig this(); syntax, which replaces implicit or explicit super();.
public A(Object obj, String prop1Str, String prop2Str) {
this(obj, obj, prop1Str, prop2Str);
}
public A(Object obj1, Object obj2, String prop1Str, String prop2Str) {
// ...
}
You can, of course, transform arguments by using more complicated expressions instead of just the plain passed-in argument. For instance:
public A(Object obj, Object prop1Obj, String prop2Str) {
this(obj, maskNull(obj), String.valueOf(prop1Str), prop2Str);
}
Constructors are there to initialise an object into a valid state. For more complex processing, you might want to add a static creation method. The method might even have a meaning name to indicate what it is doing.
you should call this(obj1, prop1Str, prop2Str). This must be the first executable line in the second constructor.
Related
How to create immutable objects in Java?
Which objects should be called immutable?
If I have class with all static members is it immutable?
Below are the hard requirements of an immutable object.
Make the class final
make all members final, set them
explicitly, in a static block, or in the constructor
Make all members private
No Methods that modify state
Be extremely careful to limit access to mutable members(remember the field may be final but the object can still be mutable. ie private final Date imStillMutable). You should make defensive copies in these cases.
The reasoning behind making the class final is very subtle and often overlooked. If its not final people can freely extend your class, override public or protected behavior, add mutable properties, then supply their subclass as a substitute. By declaring the class final you can ensure this won't happen.
To see the problem in action consider the example below:
public class MyApp{
/**
* #param args
*/
public static void main(String[] args){
System.out.println("Hello World!");
OhNoMutable mutable = new OhNoMutable(1, 2);
ImSoImmutable immutable = mutable;
/*
* Ahhhh Prints out 3 just like I always wanted
* and I can rely on this super immutable class
* never changing. So its thread safe and perfect
*/
System.out.println(immutable.add());
/* Some sneak programmer changes a mutable field on the subclass */
mutable.field3=4;
/*
* Ahhh let me just print my immutable
* reference again because I can trust it
* so much.
*
*/
System.out.println(immutable.add());
/* Why is this buggy piece of crap printing 7 and not 3
It couldn't have changed its IMMUTABLE!!!!
*/
}
}
/* This class adheres to all the principles of
* good immutable classes. All the members are private final
* the add() method doesn't modify any state. This class is
* just a thing of beauty. Its only missing one thing
* I didn't declare the class final. Let the chaos ensue
*/
public class ImSoImmutable{
private final int field1;
private final int field2;
public ImSoImmutable(int field1, int field2){
this.field1 = field1;
this.field2 = field2;
}
public int add(){
return field1+field2;
}
}
/*
This class is the problem. The problem is the
overridden method add(). Because it uses a mutable
member it means that I can't guarantee that all instances
of ImSoImmutable are actually immutable.
*/
public class OhNoMutable extends ImSoImmutable{
public int field3 = 0;
public OhNoMutable(int field1, int field2){
super(field1, field2);
}
public int add(){
return super.add()+field3;
}
}
In practice it is very common to encounter the above problem in Dependency Injection environments. You are not explicitly instantiating things and the super class reference you are given may actually be a subclass.
The take away is that to make hard guarantees about immutability you have to mark the class as final. This is covered in depth in Joshua Bloch's Effective Java and referenced explicitly in the specification for the Java memory model.
Just don't add public mutator (setter) methods to the class.
Classes are not immutable, objects are.
Immutable means: my public visible state cannot change after initialization.
Fields do not have to be declared final, though it can help tremendously to ensure thread safety
If you class has only static members, then objects of this class are immutable, because you cannot change the state of that object ( you probably cannot create it either :) )
To make a class immutable in Java , you can keep note of the following points :
1. Do not provide setter methods to modify values of any of the instance variables of the class.
2. Declare the class as 'final' . This would prevent any other class from extending it and hence from overriding any method from it which could modify instance variable values.
3. Declare the instance variables as private and final.
4. You can also declare the constructor of the class as private and add a factory method to create an instance of the class when required.
These points should help!!
From oracle site, how to create immutable objects in Java.
Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
If the instance fields include references to mutable objects, don't allow those objects to be changed:
I. Don't provide methods that modify the mutable objects.
II. Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
An immutable object is an object that will not change its internal state after creation. They are very useful in multithreaded applications because they can be shared between threads without synchronization.
To create an immutable object you need to follow some simple rules:
1. Don't add any setter method
If you are building an immutable object its internal state will never change. Task of a setter method is to change the internal value of a field, so you can't add it.
2. Declare all fields final and private
A private field is not visible from outside the class so no manual changes can't be applied to it.
Declaring a field final will guarantee that if it references a primitive value the value will never change if it references an object the reference can't be changed. This is not enough to ensure that an object with only private final fields is not mutable.
3. If a field is a mutable object create defensive copies of it for
getter methods
We have seen before that defining a field final and private is not enough because it is possible to change its internal state. To solve this problem we need to create a defensive copy of that field and return that field every time it is requested.
4. If a mutable object passed to the constructor must be assigned to a
field create a defensive copy of it
The same problem happens if you hold a reference passed to the constructor because it is possible to change it. So holding a reference to an object passed to the constructor can create mutable objects. To solve this problem it is necessary to create a defensive copy of the parameter if they are mutable objects.
Note that if a field is a reference to an immutable object is not necessary to create defensive copies of it in the constructor and in the getter methods it is enough to define the field as final and private.
5. Don't allow subclasses to override methods
If a subclass override a method it can return the original value of a mutable field instead of a defensive copy of it.
To solve this problem it is possible to do one of the following:
Declare the immutable class as final so it can't be extended
Declare all methods of the immutable class final so they can't be overriden
Create a private constructor and a factory to create instances of the immutable class because a class with private constructors can't be extended
If you follow those simple rules you can freely share your immutable objects between threads because they are thread safe!
Below are few notable points:
Immutable objects do indeed make life simpler in many cases. They are especially applicable for value types, where objects don't have an identity so they can be easily replaced and they can make concurrent programming way safer and cleaner (most of the notoriously hard to find concurrency bugs are ultimately caused by mutable state shared between threads).
However, for large and/or complex objects, creating a new copy of the object for every single change can be very costly and/or tedious. And for objects with a distinct identity, changing an existing objects is much more simple and intuitive than creating a new, modified copy of it.
There are some things you simply can't do with immutable objects, like have bidirectional relationships. Once you set an association value on one object, it's identity changes. So, you set the new value on the other object and it changes as well. The problem is the first object's reference is no longer valid, because a new instance has been created to represent the object with the reference. Continuing this would just result in infinite regressions.
To implement a binary search tree, you have to return a new tree every time: Your new tree will have had to make a copy of each node that has been modified (the un-modified branches are shared). For your insert function this isn't too bad, but for me, things got fairly inefficient quickly when I started to work on delete and re-balance.
Hibernate and JPA essentially dictate that your system uses mutable objects, because the whole premise of them is that they detect and save changes to your data objects.
Depending on the language a compiler can make a bunch of optimizations when dealing with immutable data because it knows the data will never change. All sorts of stuff is skipped over, which gives you tremendous performance benefits.
If you look at other known JVM languages (Scala, Clojure), mutable objects are seen rarely in the code and that's why people start using them in scenarios where single threading is not enough.
There's no right or wrong, it just depends what you prefer. It just depends on your preference, and on what you want to achieve (and being able to easily use both approaches without alienating die-hard fans of one side or another is a holy grail some languages are seeking after).
Don't provide "setter" methods — methods that modify fields or
objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
If the instance fields include references to mutable objects, don't allow those objects to be changed:
Don't provide methods that modify the mutable objects.
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
First of all, you know why you need to create immutable object, and what are the advantages of immutable object.
Advantages of an Immutable object
Concurrency and multithreading
It automatically Thread-safe so synchronization issue....etc
Don't need to copy constructor
Don't need to implementation of clone.
Class cannot be override
Make the field as a private and final
Force callers to construct an object completely in a single step, instead of using a no-Argument constructor
Immutable objects are simply objects whose state means object's data can't change after the
immutable object are constructed.
please see the below code.
public final class ImmutableReminder{
private final Date remindingDate;
public ImmutableReminder (Date remindingDate) {
if(remindingDate.getTime() < System.currentTimeMillis()){
throw new IllegalArgumentException("Can not set reminder" +
" for past time: " + remindingDate);
}
this.remindingDate = new Date(remindingDate.getTime());
}
public Date getRemindingDate() {
return (Date) remindingDate.clone();
}
}
Minimize mutability
An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is provided when it is created and is fixed for the lifetime of the object.
JDK immutable classes: String, the boxed primitive classes(wrapper classes), BigInteger and BigDecimal etc.
How to make a class immutable?
Don’t provide any methods that modify the object’s state (known as mutators).
Ensure that the class can’t be extended.
Make all fields final.
Make all fields private.
This prevents clients from obtaining access to mutable objects referred to by fields and modifying these objects directly.
Make defensive copies.
Ensure exclusive access to any mutable components.
public List getList() {
return Collections.unmodifiableList(list); <=== defensive copy of the mutable
field before returning it to caller
}
If your class has any fields that refer to mutable objects, ensure that clients of the class cannot obtain references to these objects. Never initialize such a field to a client-provided object reference or return the object reference from an accessor.
import java.util.Date;
public final class ImmutableClass {
public ImmutableClass(int id, String name, Date doj) {
this.id = id;
this.name = name;
this.doj = doj;
}
private final int id;
private final String name;
private final Date doj;
public int getId() {
return id;
}
public String getName() {
return name;
}
/**
* Date class is mutable so we need a little care here.
* We should not return the reference of original instance variable.
* Instead a new Date object, with content copied to it, should be returned.
* */
public Date getDoj() {
return new Date(doj.getTime()); // For mutable fields
}
}
import java.util.Date;
public class TestImmutable {
public static void main(String[] args) {
String name = "raj";
int id = 1;
Date doj = new Date();
ImmutableClass class1 = new ImmutableClass(id, name, doj);
ImmutableClass class2 = new ImmutableClass(id, name, doj);
// every time will get a new reference for same object. Modification in reference will not affect the immutability because it is temporary reference.
Date date = class1.getDoj();
date.setTime(date.getTime()+122435);
System.out.println(class1.getDoj()==class2.getDoj());
}
}
For more information, see my blog:
http://javaexplorer03.blogspot.in/2015/07/minimize-mutability.html
an object is called immutable if its state can not be changed once created. One of the most simple way of creating immutable class in Java is by setting all of it’s fields are final.If you need to write immutable class which includes mutable classes like "java.util.Date". In order to preserve immutability in such cases, its advised to return copy of original object,
Immutable Objects are those objects whose state can not be changed once they are created, for example the String class is an immutable class. Immutable objects can not be modified so they are also thread safe in concurrent execution.
Features of immutable classes:
simple to construct
automatically thread safe
good candidate for Map keys and Set as their internal state would not change while processing
don't need implementation of clone as they always represent same state
Keys to write immutable class:
make sure class can not be overridden
make all member variable private & final
do not give their setter methods
object reference should not be leaked during construction phase
The following few steps must be considered, when you want any class as an immutable class.
Class should be marked as final
All fields must be private and final
Replace setters with constructor(for assigning a value to a
variable).
Lets have a glance what we have typed above:
//ImmutableClass
package younus.attari;
public final class ImmutableExample {
private final String name;
private final String address;
public ImmutableExample(String name,String address){
this.name=name;
this.address=address;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
//MainClass from where an ImmutableClass will be called
package younus.attari;
public class MainClass {
public static void main(String[] args) {
ImmutableExample example=new ImmutableExample("Muhammed", "Hyderabad");
System.out.println(example.getName());
}
}
Commonly ignored but important properties on immutable objects
Adding over to the answer provided by #nsfyn55, the following aspects also need to be considered for object immutability, which are of prime importance
Consider the following classes:
public final class ImmutableClass {
private final MutableClass mc;
public ImmutableClass(MutableClass mc) {
this.mc = mc;
}
public MutableClass getMutClass() {
return this.mc;
}
}
public class MutableClass {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class MutabilityCheck {
public static void main(String[] args) {
MutableClass mc = new MutableClass();
mc.setName("Foo");
ImmutableClass iMC = new ImmutableClass(mc);
System.out.println(iMC.getMutClass().getName());
mc.setName("Bar");
System.out.println(iMC.getMutClass().getName());
}
}
Following will be the output from MutabilityCheck :
Foo
Bar
It is important to note that,
Constructing mutable objects on an immutable object ( through the constructor ), either by 'copying' or 'cloing' to instance variables of the immutable described by the following changes:
public final class ImmutableClass {
private final MutableClass mc;
public ImmutableClass(MutableClass mc) {
this.mc = new MutableClass(mc);
}
public MutableClass getMutClass() {
return this.mc;
}
}
public class MutableClass {
private String name;
public MutableClass() {
}
//copy constructor
public MutableClass(MutableClass mc) {
this.name = mc.getName();
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
still does not ensure complete immutability since the following is still valid from the class MutabilityCheck:
iMC.getMutClass().setName("Blaa");
However, running MutabilityCheck with the changes made in 1. will result in the output being:
Foo
Foo
In order to achieve complete immutability on an object, all its dependent objects must also be immutable
From JDK 14+ which has JEP 359, we can use "records". It is the simplest and hustle free way of creating Immutable class.
A record class is a shallowly immutable, transparent carrier for a fixed set of fields known as the record components that provides a state description for the record. Each component gives rise to a final field that holds the provided value and an accessor method to retrieve the value. The field name and the accessor name match the name of the component.
Let consider the example of creating an immutable rectangle
record Rectangle(double length, double width) {}
No need to declare any constructor, no need to implement equals & hashCode methods. Just any Records need a name and a state description.
var rectangle = new Rectangle(7.1, 8.9);
System.out.print(rectangle.length()); // prints 7.1
If you want to validate the value during object creation, we have to explicitly declare the constructor.
public Rectangle {
if (length <= 0.0) {
throw new IllegalArgumentException();
}
}
The record's body may declare static methods, static fields, static initializers, constructors, instance methods, and nested types.
Instance Methods
record Rectangle(double length, double width) {
public double area() {
return this.length * this.width;
}
}
static fields, methods
Since state should be part of the components we cannot add instance fields to records. But, we can add static fields and methods:
record Rectangle(double length, double width) {
static double aStaticField;
static void aStaticMethod() {
System.out.println("Hello Static");
}
}
I have the following two classes:
public class A{
private String s;
public A(String s){
this.s = s;
}
}
public class B{
private static final String STR = "String";
public void doAction(){
A a = new A(STR); //Does it look really wierd?
}
}
I've never passed the static final field as a constructor parameter, so can it lead to potential bugs? Should we avoid it or we can do that if it seems concise.
I've never passed the static final field as a constructor parameter, so can it lead to potential bugs?
This cannot lead to a bug, because doAction is an instance method. All static fields with initializers will be initialized before the first instance method is called, so you are safe.
Should we avoid it or we can do that if it seems concise?
Using a static final field, which is effectively a String constant, inside an instance method, is а perfectly valid choice.
You shouldn't worry if the field is immutable (like in your case: String is immutable data structure). With mutable objects (for example arrays) you should consider that all changes to this field in one object will be visible to other objects with the same field whether it is static or not. These code doesn't look weird.
String is a reference type, but it works like a primitive type sometimes. If you use a String object as an argument, it will be copied, like other primitive variables. I don't understand the reason you pass a class variable as an argument of other object. But it will not occur any problem caused by sharing of an attribute between objects of this class.
I'm having difficulty understanding the concept of the new keyword. I know its used to instantiate objects; e.g. If I had a class called Superclass, I could create a object of that class by writing:
Superclass supeclassobject = new Superclass();
I understand that but what I dont understand is that this is also acceptable:
E.g. if your were passing a Superclass object to a method which takes it as an argument, then the following would still work:
public void MethodTakingSuperClassObjectAsArugment (new Superclass()){
*CODE HERE*
}
I cant understand how that works. You haven't given a name to the object so how could you refer to it in the method? This makes sense to me:
Superclass sobject = new Superclass();
public void MethodTakingSuperClassObjectAsArugment (sobject){
*CODE HERE*
}
You have a few misconceptions there.
First, there is a method definition, and then there is a method invocation.
Method definition is where you declare your method. You give it modifiers such as public/private/protected, a return type, a name, a list of parameters, an optional throws and a body:
public static int myInt( double myParameter ) {
return (int)myParameter;
}
Here, the parameters must have names. Otherwise, you would not be able to refer to them in the body.
And then there is the method invocation. Within some other method, like main, you call your method:
int a = myInt( 15.7 );
You passed 15.7 without giving it a name. The value that you actually pass in a method invocation is called an argument as opposed to a parameter, which is the formal name and type given in the method definition.
If your method definition included a parameter of the type SuperClass, it would look something like:
public static void myMethod( SuperClass myParameter ) {
...
}
You can't use new in a parameter declaration. But when you invoke the method, and you have to pass an argument to it, you can use:
myMethod( new SuperClass() );
In the same way that you didn't need to give a name to your 15.7 before, you don't need to give a name to your new object now. When Java passes it to the method, the method sees it as the value of myParameter.
Your second misconception is about names of objects. Objects don't actually have names. But they do have references. You can refer to an object from a local variable, from a field or from inside another object. In those cases, you give the reference a name, not the object. So you can do something like this:
Superclass myVar = new SuperClass();
Superclass anotherVar = myVar;
What you have here is two reference variables. You assign a reference to a new object to myVar. And then you assign a reference to the same object to anotherVar. Both myVar and anotherVar refer to the same object. The object does not have a name. You can now do something like myVar = null. But the object will still exist, and you'll be able to access it through anotherVar.
Think of reference variables as arrows. You give the arrow a name, and you can point the arrow at any object of the appropriate type. Or you can assign null to it which means the arrow is not pointing at anything.
Back to the issue of parameters, sometimes you can see something like this:
myMethod( new SuperClass() {
// Code here
} );
This is exactly the same as we did before. It's a method invocation. The code you see in the braces is not the code for myMethod. It is in fact the code for the new object. It's an anonymous class, which extends SuperClass, and has some of its own code in those braces. So the class is defined and an instance is created of it, and that instance - of an anonymous class extending SuperClass is what's being passed as an argument to myMethod. Inside myMethod, it can be accessed with myParameter. It's the same as writing this somewhere in the same file:
private class SomeClass extends SuperClass() {
// Code here
}
And then calling `myMethod` like this:
myMethod( new SomeClass() );
Suppose I have a class ObjectInfo which contains Object name & Object type as String.(I am just cooking up something for the sake of asking the question.)
class ObjectInfo {
String objectName;
String objectType;
private ObjectInfo(String objectName, String objectType) {
this.objectName = objectName;
this.objectType = objectType;
}
}
And If I want to provide a static factory method to creating instances of this class, which of the following two methods is better & why?
public static ObjectInfo newInstance(String objectName, String objectType) {
return new ObjectInfo(objectName, objectType)
}
public static ObjectInfo valueOf(String objectName, String objectType) {
return new ObjectInfo(objectName, objectType)
}
Basically, what I want to ask is when we should use valueOf() & when newInstance()? Is there any conventions among the programmer's community?
There is no official standard, but this is my opinion,
valueOf or acquire implies that you will get any instance which holds the same information.
newInstance or create implies you will get a different instance every time.
get implies you will get an instance if it exist, or null if it does not.
In your case newInstance or create is appropriate.
c.f.
Integer.valueOf(1) == Integer.valueOf(1) // you get the same object
Integer.valueOf(-200) != Integer.valueOf(-200) // you get a different object.
public static ObjectInfo newObjectInfo(String objectName, String objectType)
For a static factory method, I would use the above naming convention. This is useful if the method consumers want to use static imports:
import static foo.ObjectInfo.newObjectInfo;
//....
ObjectInfo info = newObjectInfo(foo, bar);
You can see this pattern in the Guava API.
In general, in java, String.valueOf() is called when a string representation of some other type of data is needed. In the case of primitive wrappers (Integer, Double), valueOf() takes a String ("12") and creates an instance of that wrapper.
In your case, you try to create a new object using a number of parameters. That is a factory method. It makes more sense to call it newInstance.
You answered your own question when you said And If I want to provide a static factory method to creating instances of this class
new Instance makes sense in this context (even if both valueOf and new do the same). To me valueOf (as the name suggests )makes sense when you want to retrieve some meaningful state information from an existing object (not necessarily the entire object state) where as new is creating brand new instance.
How do I create a reference to a constant object?
final Myclass obj = new Myclass();
does not work, it says obj(the reference) should not be re-assigned but we can still change the object referred. I want to ensure that the object itself does not change once constructed.
Just make it immutable (like String is). Or wrap it in another object which restricts access to mutators of the object in question (like Collections.unmodifiableList() and consorts do).
You are mixing two things: final and immutable.
A variable can be final, so you can't change it's a value (or object reference) after it is initialized (but of course you can change the reference's objects attributes)
An object can be immutable (not a keyword but a property), so you can't change it's value after it is created. The string is a good example - you can not change the backing char[] inside a String object.
What you want is an Immutable Object. There are no keywords in Java that can instantly make an object immutable. You have to design the object's logic, so that its state cannot be changed. As BalusC put, you can wrap it in another object which restricts access to its mutators.
I don't think there's any built in keyword to make that possible in Java. Even if the reference is constant/final, the internals of the object could still be changed.
Your best options is to have a ReadOnly implementation version of your class.
You can read more about this here: http://en.wikipedia.org/wiki/Const-correctness#final_in_Java
In Java, an immutable class is generally means that it doesn't have "setters" and any field that can be accessed with a "getter" should also be immutable. In order to get your data into the class to start, you'll need to have a constructor that takes the values as arguments:
public class MyClass {
String something;
int somethingElse;
// The class can only be modified by the constructor
public MyClass(String something, int somethingElse) {
this.something = something;
this.somethingElse = somethingElse;
}
// Access "something". Note that it is a String, which is immutable.
public String getSomething() {
return something;
}
// Access "somethingElse". Note that it is an int, which is immutable.
public int getSomethingElse() {
return somethingElse;
}
}
Yes it does you seem to have forgotten to set the type.
final MyClass obj = new Myclass();
That means that obj can only be assigned once. Java does not have a const keyword like C++ does. If MyClass is not declared final (final class MyClass { ... }) it can still change.
final variables should be assigned in the moment of declaration.
final MyClass obj = new MyClass();
In java object constant means you cannot change its reference but you can change the values of its state variables untill they are not final. if all the member variables are final then its a perfect constant, where you cannot change anything.
Here is a way to wrap any object to make it "roughly" immutable.
All method calls that are not 'getters' will throw an Exception. This code defines a getter as a method that meets these criteria:
name of the method starts with get or is
it takes no arguments
it returns a value (not void return type)
Yes, getter methods could mutate an object. But if your code (or code you are using) is doing that, you have some bigger problems, please go get some help :)
the code:
class ImmutableWrapper
public static <T> T wrap(T thing) {
return (T) Proxy.newProxyInstance(thing.getClass().getClassLoader(), new Class[]{thing.getClass()}, OnlyGettersInvocationHandler.instance);
}
private static class OnlyGettersInvocationHandler implements InvocationHandler {
public static InvocationHandler instance;
#Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String name = method.getName();
if ((args == null || args.length == 0)
&& (name.startsWith("get") || name.startsWith("is")
&& !method.getReturnType().equals(Void.class))) {
return method.invoke(proxy, args);
} else {
throw new UnsupportedOperationException("immutable object: " + proxy + ", cannot call " + name);
}
}
}
}
SomeClass myThing = ... create and populate some object ...
SomeClass myImmutableThing = ImmutableWrapper.wrap(myThing);
myImmutableThing.setValue('foo'); // throws Exception
myImmutableThing.whatever(); // throws Exception
myImmutableThing.getSomething(); // returns something
myImmutableThing.isHappy(); // returns something
Mayby you can create class with final attributes. So, you can't change it: object == const.
At least "String" immutable because of it:
public final class String implements Serializable, Comparable<String>, CharSequence {
private final char[] value;
//...
}