If you are only going to use it for instanceOf i think you should think about using this structure:
CopyObject someObject = new Book(...);
if(someObject instanceOf Book book) {
//use book as variable
book.read();
}
To my knowledge this is called Pattern Matching is is possible in Java 14.
Answer from DaveLTC on Stack OverflowIf you are only going to use it for instanceOf i think you should think about using this structure:
CopyObject someObject = new Book(...);
if(someObject instanceOf Book book) {
//use book as variable
book.read();
}
To my knowledge this is called Pattern Matching is is possible in Java 14.
The closest to what you originally asked1 for is something like this:
Copy Class<?> clazz = Book.class;
Object someObject = new Book(...);
if (clazz.isInstance(someObject)) {
Object instanceOfClazz = clazz.cast(someObject);
// ...
}
(Note that this Q&A - Is there something like instanceOf(Class<?> c) in Java? - directly answers the question in the your question title.)
But you objected that the result of the cast call:
"would lose all the methods of the
Bookclass".
First of all that is not technically correct. The object that instanceOfClazz refers to is still and will always remain a Book. It still has and will always have all of the methods of a Book.
But you do have a point (I think). You cannot use the cast call's result effectively in the above code because you assigned it to a variable whose type is Object. And you cannot call Book methods via a variable / value whose static type is Object.
If instead we had written this:
Copy Class<Book> clazz = Book.class;
Object someObject = new Book(...);
if (clazz.isInstance(someObject)) {
Book book = clazz.cast(someObject);
// call some `Book` methods.
}
Now you can call Book methods on book. But the gotcha is that we had to write Class<Book> instead of Class<?> (or Class) to make that work. So we have ended up wiring the class name Book into the code anyway. Ooops!
The fundamental problem is that Java code cannot make regular method calls on an object unless the compiler knows what its type is ... and that it has those methods. If you want to invoke Book methods in cases where the static type of the variable is (say) Object, then you have to use reflection to do it. Something like this:
Copy if (clazz.isInstance(someObject)) {
Method method = clazz.getMethod("setNosPages", int.class);
method.invoke(someObject, 99);
}
and deal with the various exceptions that that might throw.
Basically, you refer to the class and methods by name in the code, or you use reflection.
"I need to assign the object/value parsed from a json to a field of type Book (or other types accordingly) of another class."
It won't work. Java is a statically typed language2. Think of another way to solve the problem. For example, use reflection to assign to the field.
1 - That is ... what the words of your question originally asked!
2 - OK ... that is over-simplifying.
Finalizing in JDK 16 - Pattern matching for instanceof
Pattern matching for instanceof
You have two options.
(1) You can enable the preview feature in Java 14, by compiling with
javac MainClass.java --enable-preview --release 14
and running with
java MainClass --enable-preview
(2) The line you wrote is equivalent to this.
if (this.areas.get(i) instanceof Habitat) {
Habitat area = (Habitat) this.areas.get(i);
// ... more here
Assuming, of course, that this get method doesn't have any nasty side-effects. This is how you do it if you don't want to enable the preview feature.
The old way is to test instanceof and them cast to the desired type:
if(this.areas.get(i) instanceof Habitat) {
Habitat area = (Habitat) this.areas.get(i);
// rest of the if block