How do I create a constant object in Java? - java

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;
//...
}

Related

Why the cast is necessary in this case?

class MyClass {
private String str;
public MyClass(String str){
this.str = str;
}
public int compare(Object o) {
return str.compareTo(((MyClass)o).str); //line No.8
}
}
class Client {
public static void main(String[] args) {
MyClass m = new MyClass("abc");
MyClass n = new MyClass("bcd");
System.out.println(m.compare(n));
}
}
Why in this snippet of code the cast (MyClass)o in line number 8 is necessary, despite the fact that the Client invokes a compare method with arguments which are instances of MyClass class?
When I modify the compare method in MyClass class to form like below:
public int compare(Object o) {
System.out.println(o.getClass());
System.out.println(((MyClass)o).getClass());
return str.compareTo(((MyClass)o).str);
}
Then, the Client will produce the following result:
class MyClass
class MyClass
Thus I don't understand why the cast above is required and why I can't just do like that (without cast to MyClass):
public int compare(Object o) {
return str.compareTo(o.str);
}
Because when I do that, I get the compile time error:
str cannot be resolved or is not a field
This comes down to what the compiler knows at compile time. At compile time it knows that what is going to be passed into this method is of type Object. That means that it can guarantee the methods that are associated with the class Object, but not the methods of type MyClass.
Because that compare method takes any argument of type Object, or a subclass, you could pass anything in. What if I make a class MyOtherClass like this..
public class MyOtherClass {
public String notStr;
}
And I do something like..
MyOtherClass myOtherClass = new MyOtherClass();
MyClass myClass = new MyClass();
myClass.compare(myOtherClass);
Without the cast, you've now got a situation where at runtime, it attempts to access a field that is not there. The cast is put in place to guarantee that the object is of the correct type, or it will fail before it attempts to access that field.
Just as an Aside
I've been working extensively with a language called Groovy. It is a language that essentially sits on top of Java, but it supports things like dynamic binding and loose typing (which is what you're after here). If this kind of functionality is a must have for you, then I would recommend checking out the documentation.
o's type in compare is an Object. This means the parameter it could be a MyClass instance, but it also could not. Object doesn't have any field called str (as that one belongs to MyClass), so there's no way to get that field from it, and so the code can't compile. If you cast to MyClass, however, it will have a field called str, and so it will be able to access it.

Is it possible to get the type of an uninstantiated variable in Java?

Is it possible to get the type of a variable that is declared (but not instantiated) in Java?
for example:
public class Foo {
FooTwo foo2;
FooTwo foo3;
FooThree foo4;
public static void main(String[] args) {
if (foo2.getClass() == foo3.getClass()) {
System.out.println("foo2 is the same type as foo3");
}
if (foo3.getClass() == foo4.getClass()) {
System.out.println("foo3 is the same class as foo4");
}
}
}
With output:
foo2 is the same type as foo3
obviously the method getClass() does not work on an uninstantiated variable, so this code does not function. I am assuming that the information I am looking for is stored somewhere in the variable (pointer?) for type safety, and that it may be accessible. Is it possible to Achieve this comparison?
the reason:
I have a class with several declared variables. These variables are supposed to point to objects stored in an ArrayList in another class. I am trying to create a method that will take an initialized (but uninstantiated) variable as a parameter, scan the arraylist for an object matching the type of the initialized variable, and set the variable to the object (Make the variable point to the object).
ALSO: The point of the system is to remove coupling in the constructor of the class. The objects cannot be instantiated immediately or in the constructor.
To start with, you need to be aware of the difference between the type of an expression and the runtime-type of a value. Consider, for example, the following code:
List<String> list = new ArrayList<String>();
System.out.println(list.getClass());
The above code prints class java.util.ArrayList, not java.util.List<java.lang.String>, because getClass() returns the runtime-type of the object that list refers to, not the type of list itself.
So it doesn't make sense to call getClass() on an uninitialized variable, because there's no value for it to return the runtime-type of.
I am trying to create a method that will that will take an initialized (but uninstantiated) variable as a parameter, […] and set the variable to the object (Make the variable point to the object).
Since Java is a pass-by-value language, it doesn't expose a way to modify a variable that is passed in as a parameter. For example, consider this method:
public void doNothing(Object obj) {
obj = "obj";
}
The above method does absolutely nothing. It has a local variable obj, which originally contains whatever reference is passed in, and then is changed to refer to the string "obj" instead; but this change has no effect, because nothing actually uses the local variable obj after that point. In particular, this method does not have any effect on whatever reference was passed in.
The closest you can get is to use reflection; if your method takes an instance of type Field, it can both examine the declared type of the field, and set the field to a value of its choosing.
You can do something similar using reflection. Here is an example code snippet. But may be there is a better way to solve your problem if you explain your use case in a bit more in detail.
import java.lang.reflect.Field;
public class Foo {
static FooTwo foo2;
static FooTwo foo3;
static FooThree foo4;
public static void main(String[] args) {
try {
Field foo2Field = Foo.class.getDeclaredField("foo2");
Field foo3Field = Foo.class.getDeclaredField("foo3");
Field foo4Field = Foo.class.getDeclaredField("foo4");
if (foo2Field.getType().equals(foo2Field.getType())) {
System.out.println("foo2 is the same type as foo3");
}
if (foo3Field.getType().equals(foo4Field.getType())) {
System.out.println("foo3 is the same class as foo4");
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
// TODO handle this if this can happen
} catch (SecurityException e) {
e.printStackTrace();
// TODO handle this appropriately
}
}
}
class FooTwo {
}
class FooThree {
}

Changing the value of an object in a method changes it globally?

Here's my Code
Class A
public class A {
private int a;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
Class Change
public class Change {
public void changeSomething(A a){
a.setA(13);
}
}
Class Learn
public class Learn {
public static void main(String[] args) {
A a = new A();
Change change = new Change();
change.changeSomething(a);
System.out.println(a.getA());
}
}
The output is 13. Now when i am passing an object to the changeSomething method, internally the value of Object A has been changed but why do i see this effect outside that function?
Is not this equivalent to passing by value in C where unless you return that variable/Object you dont get the updated value.
i.e. dont i need to do a=changeSomething(a); and set the return type of this method to be as A?
Thanks
You're passing a reference to the original object around. When you write a method
void someMethod(A param) { ... }
param is a reference to the original object. The original object isn't being copied. Consequently when you change this object, the change is visible wherever that object is observed.
When you write:
private A a = new A();
it's important to realise that the variable is a reference to object type A, not an actual object type A. It's a fine distinction, granted.
The above behaviour can cause unexpected effects across your system, and it's an argument for immutability, especially in threaded environments where changes can be triggered from multiple threads.
Short:
changeSomething() will update the value for object so if you refer to same instance you will get the same value back
Bit long explanation:
//an Object of A created and its reference is set to a
A a = new A();
//instance of Change is created and its reference is set to change
Change change = new Change();
//it passes reference's (a) 's value to the changeSomething method
//which invokes `setA()` on instance referred by a (which is the same instance that waas crated in line 1
change.changeSomething(a);
//so you will get the changed value here
System.out.println(a.getA());
Well the code you provided works directly on an instance of A. This instance is changed, no matter if you return it or not. Its still the same instance of your object. And this instances variable reflects the new value.
This is because you pass the Object, and objects in Java are always passed by reference. Only primitive (int, double, char, long...) are passed by value.
In C it could be:
public void changeSomething(A& a){
a.setA(13);
}

What is the criteria to choose between valueOf() and newInstance()?

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.

Initializing final properties using helper private methods

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.

Categories

Resources