If class B and class C extend class A and I have an object of type B or C, how can I determine of which type it is an instance?
if (obj instanceof C) {
//your code
}
Use Object.getClass. It returns the runtime type of the object. Here's how to call it using your example:
class A {}
class B extends A {}
class C extends A {}
class Main {
public static void main(String args[]) {
C c = new C();
Class clazz = c.getClass();
System.out.println(clazz);
}
}
Output:
class C
You can also compare two Class instances to see if two objects are the same type.
class A {}
class B extends A {}
class C extends A {}
class Main {
public static void main(String args[]) {
B b = new B();
Class c1 = b.getClass();
C c = new C();
Class c2 = c.getClass();
System.out.println(c1 == c2);
}
}
Multiple right answers were presented, but there are still more methods: Class.isAssignableFrom() and simply attempting to cast the object (which might throw a ClassCastException).
Possible ways summarized
Let's summarize the possible ways to test if an object obj is an instance of type C:
// Method #1
if (obj instanceof C)
;
// Method #2
if (C.class.isInstance(obj))
;
// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
;
// Method #4
try {
C c = (C) obj;
// No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}
// Method #5
try {
C c = C.class.cast(obj);
// No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}
Differences in null handling
There is a difference in null handling though:
In the first 2 methods expressions evaluate to false if obj is null (null is not instance of anything).
The 3rd method would throw a NullPointerException obviously.
The 4th and 5th methods on the contrary accept null because null can be cast to any type!
To remember: null is not an instance of any type but it can be cast to any type.
Notes
Class.getName() should not be used to perform an "is-instance-of" test becase if the object is not of type C but a subclass of it, it may have a completely different name and package (therefore class names will obviously not match) but it is still of type C.
For the same inheritance reason Class.isAssignableFrom() is not symmetric:
obj.getClass().isAssignableFrom(C.class) would return false if the type of obj is a subclass of C.
You can use:
Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object
HTH. But I think most of the time it is no good practice to use that for control flow or something similar...
Any use of any of the methods suggested is considered a code smell which is based in a bad OO design.
If your design is good, you should not find yourself needing to use getClass() or instanceof.
Any of the suggested methods will do, but just something to keep in mind, design-wise.
We can use reflection in this case
objectName.getClass().getName();
Example:-
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getClass().getName();
}
In this case you will get name of the class which object pass to HttpServletRequest interface refference variable.
There is also an .isInstance method on the "Class" class. if you get an object's class via myBanana.getClass() you can see if your object myApple is an instance of the same class as myBanana via
myBanana.getClass().isInstance(myApple)
checking with isinstance() would not be enough if you want to know in run time.
use:
if(someObject.getClass().equals(C.class){
// do something
}
I Used Java 8 generics to get what is the object instance at runtime rather than having to use switch case
public <T> void print(T data) {
System.out.println(data.getClass().getName()+" => The data is " + data);
}
pass any type of data and the method will print the type of data you passed while calling it. eg
String str = "Hello World";
int number = 10;
double decimal = 10.0;
float f = 10F;
long l = 10L;
List list = new ArrayList();
print(str);
print(number);
print(decimal);
print(f);
print(l);
print(list);
Following is the output
java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []
You can use getSimpleName().
Let's say we have a object: Dog d = new Dog(),
The we can use below statement to get the class name: Dog. E.g.:
d.getClass().getSimpleName(); // return String 'Dog'.
PS: d.getClass() will give you the full name of your object.
use instanceof operator to find weather a object is of particular class or not.
booleanValue = (object instanceof class)
JDK 14 extends the instanceof operator: you can specify a binding
variable; if the result of the instanceof operator is true, then the
object being tested is assigned to the binding variable.
please visit official Java documentation for more reference.
Sample program to illustrate usage of instanceof operator :
import java.util.*;
class Foo{
#Override
public String toString(){
return "Bar";
}
}
class Bar{
public Object reference;
#Override
public String toString(){
return "Foo";
}
}
public class InstanceofUsage{
public static void main(final String ... $){
final List<Object> list = new ArrayList<>();
var out = System.out;
list.add(new String("Foo Loves Bar"));
list.add(33.3);
list.add(404_404);
list.add(new Foo());
list.add(new Bar());
for(final var o : list){
if(o instanceof Bar b && b.reference == null){
out.println("Bar : Null");
}
if(o instanceof String s){
out.println("String : "+s);
}
if(o instanceof Foo f){
out.println("Foo : "+f);
}
}
}
}
output:
$ javac InstanceofUsage.java && java InstanceofUsage
String : Foo Loves Bar
Foo : Bar
Bar : Null
your_instance.getClass().getSimpleName() will gives type name for example: String, Integer, Double, Boolean...
I use the blow function in my GeneralUtils class, check it may be useful
public String getFieldType(Object o) {
if (o == null) {
return "Unable to identify the class name";
}
return o.getClass().getName();
}
Related
Why Java cannot cast MyObject to ? ?
This is the error I get:
java.util.List<MyMessage<MyObject>> cannot be converted to java.util.List<MyMessage<?>>
when I try to pass:
List<MyMessage<MyObject>> x = ...
to method:
void foo (List<MyMessage<?>> x) {
...
}
Let's say your MyMessage class looked like:
class MyMessage<T> {
T object;
}
You are currently able to add things to x inside the method:
void foo (List<MyMessage<?>> x) {
MyMessage<String> myMessage = ...;
x.add(myMessage);
}
If you were allowed to pass a List<MyMessage<MyObject>>, then you'd be able to do this:
List<MyMessage<MyObject>> list = new ArrayList<>();
foo(list); // Pretend this isn't a compiler error.
MyObject message = list.get(0).object;
And now you'd get a ClassCastException, because list.get(0).object is a String, not a MyObject.
"But my class doesn't look like that", you might say: the compiler doesn't know there are no fields or provider methods that could return a T (or something involving T; so it errs on the side of caution, and prevents you from doing it.
In order to avoid the problem, make it so you can't add to the list in foo:
void foo (List<? extends MyMessage<?>> x) {
MyMessage<String> myMessage = ...;
// x.add(myMessage); // Would be a compiler error!
}
I read few stack overflow responses of questions similar to this but could not get satisfying answer. I want to create a generic method which accepts a graph object of type E. I want to pass this object alongwith a class name. In that method, I want to read an input from user and check if that is an instance of given class and throw some error message if it is not. I tried to use following code for the same:
public void readDependencyPair(Scanner scanner, String prompt, MyGraph<E> graph, String clazz) {
System.out.println(prompt);
Object obj = scanner.next();
Class<?> c = Class.forName(clazz);
if(obj instanceof c) {...
}
}
The above code gives error at line "if obj is instance of c" saying "c cannot be resolved to a type. Create class 'c' or interface 'c' or enum 'c'".
I even tried to pass Class clazz instead of String parameter. And it still shows the same error that 'clazz' cannot be resolved to a type.
You can use
if (c.isInstance(obj))
....
see the docs here
You can use Class for parameter type, for example, to declare a function like:
public boolean isInstance(Class<?> c,Object obj){
return obj.getClass().equals( c);
}
Then use it in this way:
#Test
public void testIsInstance(){
User u = new User();
Assert.assertTrue(isInstance( User.class, u));
}
There's already an existing method for what you're trying to do, Class#isAssignableFrom:
public void readDependencyPair(Scanner scanner, String prompt, MyGraph<E> graph, String clazz) {
System.out.println(prompt);
String obj = scanner.next();
Class<?> c = Class.forName(clazz);
if(Class.forName(obj).isAssignableFrom(c)) {
...
}
}
Upcasting is allowed in Java, however downcasting gives a compile error.
The compile error can be removed by adding a cast but would anyway break at the runtime.
In this case why Java allows downcasting if it cannot be executed at the runtime?
Is there any practical use for this concept?
public class demo {
public static void main(String a[]) {
B b = (B) new A(); // compiles with the cast,
// but runtime exception - java.lang.ClassCastException
}
}
class A {
public void draw() {
System.out.println("1");
}
public void draw1() {
System.out.println("2");
}
}
class B extends A {
public void draw() {
System.out.println("3");
}
public void draw2() {
System.out.println("4");
}
}
Downcasting is allowed when there is a possibility that it succeeds at run time:
Object o = getSomeObject(),
String s = (String) o; // this is allowed because o could reference a String
In some cases this will not succeed:
Object o = new Object();
String s = (String) o; // this will fail at runtime, because o doesn't reference a String
When a cast (such as this last one) fails at runtime a ClassCastException will be thrown.
In other cases it will work:
Object o = "a String";
String s = (String) o; // this will work, since o references a String
Note that some casts will be disallowed at compile time, because they will never succeed at all:
Integer i = getSomeInteger();
String s = (String) i; // the compiler will not allow this, since i can never reference a String.
Using your example, you could do:
public void doit(A a) {
if(a instanceof B) {
// needs to cast to B to access draw2 which isn't present in A
// note that this is probably not a good OO-design, but that would
// be out-of-scope for this discussion :)
((B)a).draw2();
}
a.draw();
}
I believe this applies to all statically typed languages:
String s = "some string";
Object o = s; // ok
String x = o; // gives compile-time error, o is not neccessarily a string
String x = (String)o; // ok compile-time, but might give a runtime exception if o is not infact a String
The typecast effectively says: assume this is a reference to the cast class and use it as such. Now, lets say o is really an Integer, assuming this is a String makes no sense and will give unexpected results, thus there needs to be a runtime check and an exception to notify the runtime environment that something is wrong.
In practical use, you can write code working on a more general class, but cast it to a subclass if you know what subclass it is and need to treat it as such. A typical example is overriding Object.equals(). Assume we have a class for Car:
#Override
boolean equals(Object o) {
if(!(o instanceof Car)) return false;
Car other = (Car)o;
// compare this to other and return
}
We can all see that the code you provided won't work at run time. That's because we know that the expression new A() can never be an object of type B.
But that's not how the compiler sees it. By the time the compiler is checking whether the cast is allowed, it just sees this:
variable_of_type_B = (B)expression_of_type_A;
And as others have demonstrated, that sort of cast is perfectly legal. The expression on the right could very well evaluate to an object of type B. The compiler sees that A and B have a subtype relation, so with the "expression" view of the code, the cast might work.
The compiler does not consider the special case when it knows exactly what object type expression_of_type_A will really have. It just sees the static type as A and considers the dynamic type could be A or any descendant of A, including B.
In this case why Java allows downcasting if it cannot be executed at the runtime?
I believe this is because there is no way for the compiler to know at compile-time if the cast will succeed or not. For your example, it's simple to see that the cast will fail, but there are other times where it is not so clear.
For instance, imagine that types B, C, and D all extend type A, and then a method public A getSomeA() returns an instance of either B, C or D depending on a randomly generated number. The compiler cannot know which exact run-time type will be returned by this method, so if you later cast the results to B, there is no way to know if the cast will succeed (or fail). Therefore the compiler has to assume casts will succeed.
# Original Poster - see inline comments.
public class demo
{
public static void main(String a[])
{
B b = (B) new A(); // compiles with the cast, but runtime exception - java.lang.ClassCastException
//- A subclass variable cannot hold a reference to a superclass variable. so, the above statement will not work.
//For downcast, what you need is a superclass ref containing a subclass object.
A superClassRef = new B();//just for the sake of illustration
B subClassRef = (B)superClassRef; // Valid downcast.
}
}
class A
{
public void draw()
{
System.out.println("1");
}
public void draw1()
{
System.out.println("2");
}
}
class B extends A
{
public void draw()
{
System.out.println("3");
}
public void draw2()
{
System.out.println("4");
}
}
Downcast works in the case when we are dealing with an upcasted object.
Upcasting:
int intValue = 10;
Object objValue = (Object) intvalue;
So now this objValue variable can always be downcasted to int because the object which was cast is an Integer,
int oldIntValue = (Integer) objValue;
// can be done
but because objValue is an Object it cannot be cast to String because int cannot be cast to String.
Downcasting is very useful in the following code snippet I use this all the time. Thus proving that downcasting is useful.
private static String printAll(LinkedList c)
{
Object arr[]=c.toArray();
String list_string="";
for(int i=0;i<c.size();i++)
{
String mn=(String)arr[i];
list_string+=(mn);
}
return list_string;
}
I store String in the Linked List.
When I retrieve the elements of Linked List, Objects are returned. To access the elements as Strings(or any other Class Objects), downcasting helps me.
Java allows us to compile downcast code trusting us that we are doing the wrong thing.
Still if humans make a mistake, it is caught at runtime.
Consider the below example
public class ClastingDemo {
/**
* #param args
*/
public static void main(String[] args) {
AOne obj = new Bone();
((Bone) obj).method2();
}
}
class AOne {
public void method1() {
System.out.println("this is superclass");
}
}
class Bone extends AOne {
public void method2() {
System.out.println("this is subclass");
}
}
here we create the object of subclass Bone and assigned it to super class AOne reference and now superclass reference does not know
about the method method2 in the subclass i.e Bone during compile time.therefore we need to downcast this reference of superclass to subclass reference so as the resultant reference can know about the presence of methods in the subclass i.e Bone
To do downcasting in Java, and avoid run-time exceptions, take a reference of the following code:
if (animal instanceof Dog) {
Dog dogObject = (Dog) animal;
}
Here, Animal is the parent class and Dog is the child class.
instanceof is a keyword that is used for checking if a reference variable is containing a given type of object reference or not.
Downcasting transformation of objects is not possible.
Only
DownCasting1 _downCasting1 = (DownCasting1)((DownCasting2)downCasting1);
is posible
class DownCasting0 {
public int qwe() {
System.out.println("DownCasting0");
return -0;
}
}
class DownCasting1 extends DownCasting0 {
public int qwe1() {
System.out.println("DownCasting1");
return -1;
}
}
class DownCasting2 extends DownCasting1 {
public int qwe2() {
System.out.println("DownCasting2");
return -2;
}
}
public class DownCasting {
public static void main(String[] args) {
try {
DownCasting0 downCasting0 = new DownCasting0();
DownCasting1 downCasting1 = new DownCasting1();
DownCasting2 downCasting2 = new DownCasting2();
DownCasting0 a1 = (DownCasting0) downCasting2;
a1.qwe(); //good
System.out.println(downCasting0 instanceof DownCasting2); //false
System.out.println(downCasting1 instanceof DownCasting2); //false
System.out.println(downCasting0 instanceof DownCasting1); //false
DownCasting2 _downCasting1= (DownCasting2)downCasting1; //good
DownCasting1 __downCasting1 = (DownCasting1)_downCasting1; //good
DownCasting2 a3 = (DownCasting2) downCasting0; // java.lang.ClassCastException
if(downCasting0 instanceof DownCasting2){ //false
DownCasting2 a2 = (DownCasting2) downCasting0;
a2.qwe(); //error
}
byte b1 = 127;
short b2 =32_767;
int b3 = 2_147_483_647;
// long _b4 = 9_223_372_036_854_775_807; //int large number max 2_147_483_647
long b4 = 9_223_372_036_854_775_807L;
// float _b5 = 3.4e+038; //double default
float b5 = 3.4e+038F; //Sufficient for storing 6 to 7 decimal digits
double b6 = 1.7e+038;
double b7 = 1.7e+038D; //Sufficient for storing 15 decimal digits
long c1 = b3;
int c2 = (int)b4;
//int 4 bytes Stores whole numbers from -2_147_483_648 to 2_147_483_647
//float 4 bytes Stores fractional numbers from 3.4e−038 to 3.4e+038. Sufficient for storing 6 to 7 decimal digits
float c3 = b3; //logic error
double c4 = b4; //logic error
} catch (Throwable e) {
e.printStackTrace();
}
}
}
I will tell you why this happened. First of all you have to understand how JVM supports when we assign parent class into the child class using downcasting, because of reference . For example consider in the following code.
A is the super type any class that extends from it and can store the reference B class.
A a =new B();
When you assign a reference variable into the child class jvm will understand that since A can store the reference of B class that is why you can do it.
B b=(B)b;
The reason which is called compile time error and why you couldn't directly assign Parent class into the Child class because there is not any extends relationship. Note that casting only occurring with the key which is called extends, that is why you receive the compile time error.
Another reason which is called ClassCastException by the runtime because of jvm it directly accept the rule which is okay I accept that it is true but jvm after that will understand that by the runtime it is not store any referance of Child class when code was writing by the programmer who write coding in the syntax .
I recently came across a strange compilation error for my following code snippet :
class A {
}
class B extends A {
}
class Example {
}
class Demo {
public static void main (String args[]){
B b = new B();
if(b instanceof Example) {
System.out.println("Yes it is");
}
}
}
Now I am getting a compilation error on my predicate indicating that B and Example are incompatible operands. I searched for a while and found that the Eclipse environment shows such an error if the right hand operand is not imported. But in my case all the classes are in the same file. So I am unable to figure out the issue. Is it that instanceof only works for the hierarchies and the example I have been trying an invalid one?
b is defined as B, it can never be Example as there is no inheritance relationship between the two. You would rather do:
class Demo {
public static void main (String args[]){
A a = new B();
if(a instanceof B) {
System.out.println("Yes it is");
}
}
}
or if you insist on a type which can hold Example it would be:
class Demo {
public static void main (String args[]){
Object o = new Example();
if(o instanceof Example) {
System.out.println("Yes it is");
}
}
}
The compilier can and must check, if the type can be the given instance, see JLS 15.20.2
If a cast of the RelationalExpression to the ReferenceType would be rejected as a
compile-time error, then the instanceof relational expression likewise produces a
compile-time error. In such a situation, the result of the instanceof expression
could never be true.
There is absolutely no way that the object referenced by b can be an instance of Example. This is known at compile time.
A reference of type B exists in this hierarchy
class B extends A {
}
while Example is in
class Example {}
There is no way a variable of type B can be referencing an object of type Example. For example, an instance of type B is already, obviously, not a subtype of Example. Furthermore, any subtype of B would be a subclass of B. Since Java doesn't support multiple inheritance, then it could not also be a subtype of Example. (The same could not be said if Example was an interface.)
The instanceof operator is used for runtime type checking. It would make sense, for example, to check if a reference of type A actually holds a B instance. However, Example and B are completely disjoint types - a reference to B can never hold an instance of type Example, therefore checking it is pointless, and can be failed at compile time.
instanceof is operator only work of inheritance and implementation . If object you are checking of is not from inheritance hierarchies then you will get compilation error . Do this below is the code
class Demo {
public static void main (String args[]){
A obj = new B();
if(obj instanceof B) {
System.out.println("Yes it is");
}
}
}
Here you cannot check obj instanceof Example , its wrong as is not from hierarchies.
Say, there is a following example:
class Super {
public int i = 3;
public void m(Object o) {
System.out.println("Object " + i);
}
public void m(String o) {
System.out.println("String " + i);
}
}
public class Sub extends Super {
public Sub() {
i = 5;
}
public static void main(String[] args) {
Super s = new Sub();
Object o = "";
s.m(o);
s.m("");
}
}
The result of this code is:
Object 5
String 5
But I thought it would be:
String 5
String 5
Don't quotes set String as this object's type? There are definitely some cases of casting to String with a help of quotes, so I'm a little confused about this basic example. Thanks in advance.
The type of the method is determined in compile time, and not in run time. The dynamic dispatch exists only for the "parameter" this - there is no dynamic dispatch for parameters in static typing languages such as java.
The compiler "choses" which method should be invoked, and since o is of type Object - it choses m(Object) - it has no way to know that the dynamic type of o is actually a String.
If you are interested - a common way to overcome this issue in some cases is using the visitor design pattern.
In your specific case, in order to "force" the activation of m(String) you should use m(o.toString())
In sb.m(o), you're calling m() with an Object reference, so Java chooses that overload. Java will not choose a more specific overload than the reference type you pass it. It will go up the inheritance chain though. Say you didn't have m(String o), calling sb.m("Hello") would still be legal, but it would call the object version.
If you were to do sb.m((String) o), you would get your expected behavior.
You declared the object as Object so its type is Object. Types in Java are strong and static so when you declare an object as type Type that is what its type will be for life.
If you want it to be a string you'll have to use a toString method or a cast (String)o
You are downcasting the String to an Object. What you are doing is similar to this.
public class Sub extends Super {
public Sub() {
i = 5;
}
public static void main(String[] args) {
Super s = new Sub();
Object o = "";
System.out.println("Object Type = " + o.getClass().getName());
s.m(o);
s.m((Object)"");
}
}