create constant object in Java - java

I wonder, In Java How can we create a constant object (but not-reference nor immutable since immutability is a feature to all objects of a class) ?
First:
final MyClass c = new MyClass();
creates a constant reference to non-constant object hence I can do:
c.setData(100);
Second:
String class is a class that all its instances should be constant (a.k.a immutable object). I need to have a kind that I can create from a constant objects and non-constanct objects.
In Other words, How to grant the constant-ness to some objects of a class and remove it from other objects. (without the need to wrap this object inside any wrapper).

I suppose that you want something along the lines of the const keyword in C++, which makes an instance of an otherwise mutable class immutable. However, no direct equivalent for this exists in Java.
If you control the class, you could define an interface that only exposes the getters and use that interface whenever you need a "const" reference - this would not require any wrapping, but it would be rather cumbersome if you need to do this for a lot of classes.

The closest you could do is to extend the base class and override its setter methods so they throw java.lang.UnsupportedOperationException , that way you can create object from the base class or the immutable subclass...

And what about an Enumeration containing only one element ? I think that comes pretty close to what he needs

Related

Will the use of Class as key for a HashMap cause undesireable effects?

Consider the following:
Map<Class<?>, Object> myMap = new HashMap<Class<?>, Object>();
Foo fooObject = New Foo();
myMap.put(fooObject.getClass(), fooObject)
Notice that java.lang.Class does not implement the hashCode() method itself, but inherits it from java.lang.Object implicitly. I verified this in JDK 1.8.
Is java.lang.Class safe to use as a key for a java.util.HashMap?
Will myMap.get(Foo.class) always return the values which I put like myMap.put(fooObject.getClass(), fooObject)? Consider the software to have various classloaders and serialization mechanisms. Will it still be the same result? If not... What would be an alternative?
Off the top of my head, would there be any reason to just not use the string class names? E.g. instead use:
myMap.put("Foo", fooObject);
If you are paranoid that maybe there could be more than one Foo class in scope, you could use the full canonical name:
myMap.put(Foo.class.getCanonicalName(), fooObject);
Is java.lang.Class safe to use as a key for a java.util.HashMap?
Yes.
Will myMap.get(Foo.class) always return the values which I put like myMap.put(fooObject.getClass(), fooObject)?
Yes.
Using a Class object as a key in a HashMap is safe. The Class class inherits the Object::equals and Object::hashCode methods. Thus equals for Class objects is testing object identity.
This is the correct semantics for type equality in Java. The implementation of the ClassLoader::defineClass method ensures that you can never get two different Class objects representing the same Java type.
However, there is a wrinkle. The Java Language specification (JLS 4.3.4) states this:
At run time, several reference types with the same binary name may be loaded simultaneously by different class loaders. These types may or may not represent the same type declaration. Even if two such types do represent the same type declaration, they are considered distinct.
(The binary name is related to the FQDN of a named type, and takes account of anonymous classes, and array types.)
What this means is that if you (successfully) call ClassLoader::defineClass for classes with the same fully qualified name in two different classloaders, you will get different Java types. Irrespective of the bytecodes you used. Furthermore, if you attempt to cast from one type to the other one, you will get a class cast exception.
Now the question is does this matter in your use-case?
Answer: probably not.
Unless you (or your framework) are doing tricky things with classloaders, the situation does not arise.
If it does, then you probably need the two types (with the same FQDN and different classloaders) to have the different entries in the HashMap. (Because the types are different!)
But if you need the two types to have the same entry, then you can use the FQDN for the class as the key, which you can obtain using Class::getCanonicalName. If you need to cope with array classes, etc, then use Class::getName which returns the binary name for the type.
What about serialization mechanisms?
A Class object cannot be serialized using Object serialization, since Class does not implement Serializable. If you implement / use some other serialization mechanism that does support the serialization of Class objects, then that mechanism needs to be compatible with JLS 4.3.4.
Instances of Class are unique per ClassLoader so it is not needed to override hashCode or equals.
There is a difference between run-time and compile-time type. It is possible to simultaneously load multiple classes of the same fully-qualified class name, if (and only if) they are loaded by different class loaders. Then such classes are distinct run-time types, and cannot be cast to one another, even if they are identical.
Hence the answer to your question depends simply on which effect you consider desirable:
If you desire to treat those separately loaded and incompatible classes as distinct in your map, use Class as the key. There will never be more than one live instance of Class with the same name and loader, so the Class class correctly does not override the hashCode and equals methods. So it is fine to use it as a HashMap key, although IdentityHashMap will give the same behavior, probably more efficiently.
If you desire to distinguish classes based only on their name, regardless of how (or whether) they were loaded, then use their string name as the map key.
#talex I tested it like below and you seem to be right:
public class ClassUnique {
public static void main(String [] args) throws ClassNotFoundException {
Class<?> c1 = Class.forName("java.util.Date");
Class<?> c2 = Class.forName("java.util.Date");
System.out.println(c1.equals(c2));
}
}
Output is true
EDIT: #Maarten I think you are right. Especially if you are running within an application container like Websphere or Weblogic there might be multiple class loaders in play which could screw this up. So in the end the simplest correct solution would be to just use the Class instance itself.
I would consider using IdentityHashMap. It does not rely on equals.
This class is designed for use only in the rare cases wherein reference-equality semantics are required.

Does Java have a concept of reference ownership or noncopyable classes?

I would like to have some guarantee that instances of some particular class Content is only accessed by its "owner", and if another object wants the same Content it needs to take a deep copy. Coming from C++ I would achieve that using a unique_ptr, is there anything similar in Java?
Currently I am resolving this by just keeping the Content private everywhere I keep one and paying attention to creating a new Content (the constructor implements the deep copy mechanism) on a getContent. But I have no means of enforcing possible other users of the Content class to follow the same pattern, it's easy to forget. It would be nicer if it could take care of itself somehow, like not being copyable.
I realize that it goes somewhat against the spirit of the language, but in some cases I think it's justified. For example, if Content represents some stream of data that is modified even by reading it. I thought, if not in the core language, maybe there is some #interface for compile-time checking or a way of creating one?
Edit: The idea is that the owner can modify the object freely, before or after taking copies, and if someone takes a deep copy, they can modify theirs (not affecting the original), so making the Content immutable is a bit too harsh (unless I'm misunderstanding what that implies).
There are a couple of common strategies here:
Privacy with defensive copying
In this strategy, you'd have the owner have a private reference to the content, and if it's appropriate for it to give out copies of that content, to do so via a defensive copy:
class Owner {
private Content content;
// ...unnecessary detail omitted...
public Content getContent() {
return new Content(this.content);
}
}
The Cloneable interface can sometimes be useful here.
Immutable objects
The other common strategy is to use immutable objects (e.g., ensure that Content, once instantiated, cannot be modified). Then you don't care who has a reference to the content, since they cannot change it.
No there isn't.
Once you have established a reference to an object, there's absolutely nothing you can do to stop someone form assigning another reference to that object via that established reference.
Java programmers get round this by making objects immutable (see java.lang.String). Then you ought not give two hoots about who else is referring to a particular instance.
You can declare the class Content as Immutable by doing this:
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.
If the instance fields include references to mutable objects, don't allow those objects to be changed
Here is a java official doc: https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
Java does not have something like that. There are some language elements that can help with such requirements:
Enums that have only one constant; to be used as "built-in" singletons
Methods in Collections to create immutable copies of collections
And of course, you can make all fields in your class final; so they get initialized only during construction time; to prevent later changes
But as Java is also missing a const concept, you can partially work around such things. Like in:
class Foo {
private final List<Bar> bars = new ArrayList<>();
doesn't mean that instances of Foo will be immutable - as you still can add/remove elements to that list owned by Foo.
Similar; given
List<Foo> root = ...
List<Foo> immutableCopy = Collections.unmodifiableList(root);
one can still change that immutableCopy ... by messing up root.

State of Object, which don't has any attribute

We all know state of an Object is value of it's attributes (instance variables), but if class doesn't has any attribute (no inherited attributes), what would be the state of an Object of such class.
There is a word for such objects - stateless.
There is no such thing as a Java class without a parent class. The default parent would be used, e.g. java.lang.Object.
At a minimum every instance of a class has two attributes: a reference address and a Class type. Note, not every class can be instantiated. There is also some space used in the ClassLoader and any String(s) may (or may not) be interned. This actual implementation might vary slightly on the specific version of the JDK and run-time platform, and additional optimizations can be added by the JIT. However, as a Java developer you are not responsible for this memory management and I would be wary of premature optimization.
first thing
any class we write in java will extend Object class by default if there is no extends written by the developer.
so each and every class will definitely have a parent with no doubt atleast Object class.
second
if you dont put any attributes in your class , obviously it will get all the instance variables except private gets inherited to your class.
so it will have atleast object state but it will not serve any purpose
An object with no data members and links to other objects is a stateless object and in this form can hardly be of any use.
This kind of classes can nevertheless be usefull, because of its methods. It can be...
a base for a further inheritance. It declares/defines some methods, that could be inherited by derived classes. This class will probably be an abstract class, having no objects at all (although not a condition)
a service class. It can define some methods, which in nature do not belong to concrete objects but are used by other objects. Like some all-purpose mathematical operations, a service that returns a current time or similar. These methods can be static, so again no instances are needed.
We call those object stateless. As the name suggests, they have no state.
Referring to other answers/comments, even though every Java object implicitly extends Object, mind that Object has no fields. So even though every object has a runtime address and class attributes, for all practical purposes you can still consider some objects stateless.
Next, it is definitely not true that stateless objects serve no purpose! You can use stateless object for:
1) Grouping functions with similar functionality, similar to java.lang.Math, which groups mathematical functions.
2) Passing functionality as a parameter, e.g. Comparator<T> can be used to sort objects that do not implement Comparable<T>, and it definitely needs no state.
Stateless objects are somehow similar to immutable objects: their state can never be changed and therefore they are always thread-safe.
You may also want to see JEE Stateless Session Beans which differentiate between a converstional state and an instance state.

Java classes and constructors

I hope this won't sound like a stupid question.
I have a class A and a class B. Now the only thing B has is a String ID.
Now I can have multiple objects A that each can have 0 or more objects of type B.
These are contained in a HashMap(ID,someData) each class A has.
What I want to do is each time I add a new ID in class A to check whether there already
is a on object of Type B with the same ID in any of the other class A objects I have, and if not, create a new B object.
Hope this makes sense. If what I ask is wrong is some way, please be kind enough to explain
how is this a bad practice or conceptualy wrong.
Thanks a lot.
EDIT:To be more clear,in my case, it is not desireable to share the HashMap(ID,someData) for all my objects as for example let's say A is a Course class,Or Catalogue, or Bank etc. Each A class may share some students/clients but each A class may contain different class B objects.
It's not bad practice, it seems like you're implementing the Instance Manager Pattern.
Ability to look up one or more instances (via a key) of the managed object(s). If only one managed object, then a key is not necessary.
The thing you need to do this is to have a collection of all A objects so you can check them all. As you get more A objects this will become more inefficient. A diiferent was to structure this might be to use the ID as you collection.
Map<ID,/* class with A and someData *> map = ...
This allows you to ensure uniqueness of ID across all A.
To achieve your purpose, you can make the HashMap a static variable, instead of an instance variable. Therefore, it will be shared among all instance of Class A.
If I were you I would have created a B_Factory class. This class would be responsible for creating the B objects. A class objects would call B_Factory methods to add or delete a B object. Inside B_Factory, you could use a Map to store the instances of B objects.
There should be only one instance of B_Factory class, which will be injected in all A instances.
You should loop through all your A instances and use Hashmaps containsKey method to check that the new B value is already stored or not. If you only need to store all the B values to every A class only once, you can add a static modifier for your HashMap field.

Possible ways of making an Object immutable

I am looking for some efficient way for building a immutable class, just like Java's String class.
All the fields must be
private and preferably final
Ensure the class cannot be
overridden - make the class final,
or use static factories and keep
constructors private
Fields must be populated from the
Constructor/Factory
Don't provide any setters for the
fields
Watch out for collections. Use
Collections.unmodifiable*. Also, collections should contain only immutable Objects
All the getters must provide
immutable objects or use defensive copying
Don't provide any methods that
change the internal state of the
Object.
Tom Hawtin pointed out that final can be optional. String class has a cache hash var that is only assigned when the hash function is called.
If you populate all fields using the constructor and make the fields final - you are partway there.
If the fields use custom types - you may need to make them immutable as well.
Any fields that are collections should use the unmodifiable collections - to be on the safe side.
You need to worry about the object graph!
Any methods on the object need to take care with non-final fields. E.g. String.add creates a new String. If you need to mutate one field - do so via a copy constructor.
Finally make the object final.
An object is immutable if none of its fields can be modified, so those fields must be final. If you don't want your object to be subclassed, you can make the class itself final as well, just like String is.
To easily construct an immutable object with a lot of information, you should look at the Factory Pattern
For more information, see Wikipedia

Categories

Resources