Are instances of Class immutable? - java

I was wondering whether Class instances are immutable. The declared methods names do not suggest that the instance state is changed when they are invoked, but I found no explicit guarantee on the javadoc.
Scenario: I need to store unique class names in a Set. Ideally, I would like to populate the set with Class instances to avoid unnecessary calls to Class.forName() when I need to access the classe via reflection. However, it preferable to use immutable objects as keys of sets. Hence I was wondering if I could use Class instances right away.

First, The generics part Class<?> really doesn't matter here. Sure, no raw types, so Class<?> is better than Class, but for your question, the wildcard doesn't matter.
So in essence, you are asking whether Class objects are immutable. And for all practical purposes, they are.
Class objects come into existence when a class loader loads a class, and they stay put unless the whole class loader is unloaded, and everything it loaded with it.
Which can't happen when such class objects are still used in a map somewhere.
On the other hand: Class.forName() shouldn't be too expensive for classes already loaded. And when things such as serialization come into play, people suggest to go with String instead of Class objects for example (see here).
One has to distinguish between the immutable identity of a class object, and the actual "code" belonging to the class. That code can be changed at runtime (by instrumentation, think hot swap of code). But the class name, and its each code, and equals() equality should not be affected by that. Because the "identity" stays the same.
Final note: as the interesting comments below lay out, there are certain ways to alter Class objects to a certain degree. But all of these activities are definitely "out of the norm". Therefore: theoretically, you might prefer Strings over Class objects, but practically, in "normal" applications, using Class should work fine, too.

As I don’t really agree with other answer I decided to write this one,
Classes are not immutable, but they are unique - only one instance of Class object can exist for one class.
BUT class it not defined by its name, as classes might be from different class loaders, and different class loaders might have classes with same names - but that will be different classes, you would get ClassCastException if you would pass some object between code handled by 2 different class loaders if that object type would exist in both of them (as separate one, not inherited).
Class instances can be still safely used in Set, as they use default implementation of hashset/equals so only same instances of Class will be considered equals.
But to decide if you should use String or Class you need to know how exactly your app is supposed to work, as like I said, multiple classes with same name can exist between different class loaders.
And by just storing class name you can’t be sure that Class.forName will return same instance as expected it might even load some other class with same name from current class loader instead of using expected one.

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.

Prevent Serialization of parent class Java

Is there a way where I can prevent the parent class to be serialized?
When we do a serialization of the subclass all the way up till the parent class the serialization is performed.
Can I restrict the serialization of the parent classes and serialize the only sub class I am working on?
It is possible. Just declare your class as implements Externalizable and write exactly what you need in the writeExternal() method, taking care not to serialize anything from the superclass, and read exactly that back in the readExternal() method.
Or, just implement Serializable and provide your own readObject()/writeObject() methods, again taking care not to serialize anything from the superclass, and in this case also not calling defaultWriteObject() or defaultReadObject().
In both cases the actual serialization of the current class's data is entirely up to you.
Whilst it is technically possible to fine tune each level of inheritance on its own - even to the extent of excluding super class fields - you might want to step back here.
Basically there are two cases:
The super class does not have any fields / state. Then you have nothing to exclude anyway.
The super class has state, represented by fields of that class.
So how do you think to meaningfully address the second part? You see when you allow deserialisation without the data for the super class fields - that means that you might have to do a lot of additional testing. To make sure that super class methods don't throw exceptions - because all of a sudden fields are null instead of being initialized.
In other words: it is possible that "leaving out" all these values - you are creating objects which behave completely different. Are you prepared for handling all the effects of that?
Meanung: skipping super class fields requires you to interfere with serialization code. It might require a lot of additional testing effort. And what do you gain? A few bytes less of data transfer at runtime.
Beyond that: what is the purpose of an inheretance hierarchy that has 4 levels - but where the super class state is irrelevant?
So my non-answer: carefully consider if your idea is really the best OO design to solve the underlying requirements.

Is it mandatory utility class should be final and private constructor?

By making private constructor, we can avoid instantiating class from anywhere outside. and by making class final, no other class can extend it. Why is it necessary for Util class to have private constructor and final class ?
This is not a mandate from a functional point of view or java complication or runtime. However, it's a coding standard accepted by the wider community. Even most static code review tools, like checkstyle, check that such classes have this convention followed.
Why this convention is followed is already explained in other answers and even OP covered that, but I'd like to explain it a little further.
Mostly utility classes are a collection of methods/functions which are independent of an object instance. Those are kind of like aggregate functions as they depend only on parameters for return values and are not associated with class variables of the utility class. So, these functions/methods are mostly kept static. As a result, utility classes are, ideally, classes with only static methods. Therefore, any programmer calling these methods doesn't need to instantiate the class. However, some robo-coders (maybe with less experience or interest) will tend to create the object as they believe they need to before calling its method. To avoid that, we have 3 options:
Keep educating people to not instantiate it. (No sane person can keep doing it.)
Mark the utility class as abstract: Now robo-coders will not create the object. However, reviewers and the wider java community will argue that marking the class as abstract means you want someone to extend it. So, this is also not a good option.
Private constructor: Not protected because it'll allow a child class to instantiate the object.
Now, if someone wants to add a new method for some functionality to the utility class, they don't need to extend it: they can add a new method as each method is independent and has no chance of breaking other functionalities. So, no need to override it. Also, you are not going to instantiate it, so no need to subclass it. Better to mark it final.
In summary, instantiating a utility class (new MyUtilityClass()) does not make sense. Hence the constructors should be private. And you never want to override or extend it, so mark it final.
It's not necessary, but it is convenient. A utility class is just a namespace holder of related functions and is not meant to be instantiated or subclassed. So preventing instantiation and extension sends a correct message to the user of the class.
There is an important distinction between the Java Language, and the Java Runtime.
When the java class is compiled to bytecode, there is no concept of access restriction, public, package, protected, private are equivalent. It is always possible via reflection or bytecode manipulation to invoke the private constructor, so the jvm cannot rely on that ability.
final on the other hand, is something that persists through to the bytecode, and the guarantees it provides can be used by javac to generate more efficient bytecode, and by the jvm to generate more efficient machine instructions.
Most of the optimisations this enabled are no longer relevant, as the jvm now applies the same optimisations to all classes that are monomorphic at runtime—and these were always the most important.
By default this kind of class normally is used to aggregate functions who do different this, in that case we didn't need to create a new object

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.

AbstractClass.getInstance() method is this an anti-pattern

In some places where a class hierarchy is present and the top most base class is an abstract class there is a static getInstance() method in the abstract class. This will be responsible for creating the correct sub-class and returning it to the caller. For example consider the below code.
public class abstract Product {
public static Product getInstance(String aCode) {
if ("a".equals(aCode) {
return new ProductA();
}
return ProductDefault();
}
// product behaviour methods
}
public class ProductA extends Product {}
public class ProductDefault extends Product {}
In Java, java.util.Calendar.getInstance() is one place this pattern has been followed. However this means each time a new subclass is introduced one has to modify the base class. i.e: Product class has to be modified in the above example. This seems to violate the ocp principle. Also the base class is aware about the sub class details which is again questionable.
My question is...
is the above pattern an anti-pattern ?
what are the draw-backs of using the above pattern ?
what alternatives can be followed instead ?
The interface is not an anti-pattern. But the way you've implemented it is rather poor ... for the reason you identified. A better idea would be to have some mechanism for registering factory objects for each code:
The Java class libraries do this kind of thing using SPIs and code that looks reflectively for "provider" classes to be dynamically loaded.
A simpler approach is to have a "registry" object, and populate it using dependency injection, or static initializers in the factory object classes, or a startup method that reads class names from a properties file, etcetera.
No it's not. It's more like factory method pattern http://en.wikipedia.org/wiki/Factory_method_pattern. E.g. Calendar.getInstance();. JDK is full of such examples. Also reminds of Effective Java Item 1: Consider static factory methods instead of constructors
There are a number of separate issues here.
getInstance is probably going to be a bad name. You explicitly want a new object you can play around with. "Create", "make", "new" or just leave that word out. "Instance" is also a pretty vacuous word in this context. If there is sufficient context from the class name leave it out, otherwise say what it is even if that is just a type name. If the method returns an immutable object, of is the convention (valueOf in olden times).
Putting it in an abstract base class (or in an interface if that were possible) is, as identified, not the best idea. In some cases an enumeration of all possible subtypes is appropriate - an enum obviously and really not that bad if you are going to use visitors anyway. Better to put it in a new file.
Anything to do with mutable statics is wrong. Whether it is reusing the same mutable instance, registration or doing something disgusting with the current thread. Don't do it or depend (direct or indirectly) on anything that does.
Based on the feedback i introduced a new ProductFactory class that took care of creating the correct Product. In my case the creation of the correct product instance depends on an external context (i've put the product code for the purpose of simplicity.. in the actual case it might be based on several parameters.. these could change over time). So having a Product.getInstance() method is not that suited because of the reasons outlined in the question. Also having a different ProductFactory means in the future.. Product class can become an interface if required. It just gives more extensibility.
I think when the creation of the object doesn't depend on an external context.. like in the case of Calendar.getInstance() it's perfectly ok to have such a method. In these situations the logic of finding the correct instance is internal to that particular module/class and doesn't depend on any externally provided information..

Categories

Resources