morteza khosravi
morteza khosravi

Reputation: 1619

java instanceof and getClass() don't work as expected

I have the following code:

protected LogEvent toLogEvent(LogRecord element) {
    ......
    System.out.println("element.getClass():"+element.getClass());
    System.out.println("element.getClass() == org.jboss.logmanager.ExtLogRecord.class:" + (element.getClass() == org.jboss.logmanager.ExtLogRecord.class));
    System.out.println("element instanceof org.jboss.logmanager.ExtLogRecord:" + (element instanceof org.jboss.logmanager.ExtLogRecord));
    System.out.println("element instanceof java.util.logging.LogRecord:"+(element instanceof java.util.logging.LogRecord));
    System.out.println("element.toString():"+element.toString());

The output is:

09:20:51,544 INFO  stdout element.getClass():class org.jboss.logmanager.ExtLogRecord
09:20:51,545 INFO  stdout element.getClass() ==org.jboss.logmanager.ExtLogRecord.class:false
09:20:51,547 INFO  stdout element instanceof org.jboss.logmanager.ExtLogRecord:false
09:20:51,548 INFO  stdout element instanceof java.util.logging.LogRecord:true
09:20:51,549 INFO  stdout element.toString():org.jboss.logmanager.ExtLogRecord@2657c0ad

ExtLogRecord is subclass of LogRecord.

My problem is:

  1. In the second line why the output is false? clearly element is an instance of ExtLogRecord.

  2. In the third line element instanceof ExtLogRecord returns false and in the fourth line element instanceof LogRecord returns true. So element is a LogRecord but it's not an ExtLogRecord. How is that happening?

UPDATE:

I have added some additional code about classloading. The output is:

10:32:48,372 INFO  stdout (new ExtLogRecord()) instanceof  ExtLogRecord:true
10:32:48,374 INFO  stdout new ExtLogRecord(org.jboss.logmanager.Level.ALL,"","").getClass():class org.jboss.logmanager.ExtLogRecord
10:32:48,376 INFO  stdout LogRecord.class.getClassLoader():null
10:32:48,377 INFO  stdout ExtLogRecord.class.getClassLoader():"ModuleClassLoader for Module "org.tamin.tiba.logging.jboss.handlers:main" from local module loader@416a8198(roots: D:\java\jbossas\modules)
10:32:48,378 INFO  stdout LogRecord.class.getClassLoader() == ExtLogRecord.class.getClassLoader():false

UPDATE 2:

Additional classloading comparisons:

10:43:14,113 INFO  stdout element.getClass().getClassLoader() == ExtLogRecord.class.getClassLoader():false
10:43:14,115 INFO  stdout element.getClass().getClassLoader():ModuleClassLoader for Module "org.jboss.logmanager:main" from local module loader @576fb9a5 (roots: D:\java\jbossas\modules)

Upvotes: 2

Views: 600

Answers (2)

Keerthivasan
Keerthivasan

Reputation: 12880

  • Your second line output is false since LogRecord.class is not equal to ExtLogRecord.class. You are passing the LogRecord instance and doing the equality check on its subclass

  • Your third line output is false since parent class instance cannot be an instance of it's subclass

  • Your fourth line output is true, since it's an instance of LogRecord class

Hope it helps

Upvotes: 1

Rohit Jain
Rohit Jain

Reputation: 213243

You are getting those outputs for when you pass a LogRecord instance, and not the subclass instance. Considering the two classes, and assuming they have a 0-arg constructor, below is the result of invoking the method with 2 instances:

toLogEvent(new LogRecord());     // passing superclass instance
System.out.println();
toLogEvent(new ExtLogRecord());  // passing subclass instance

Output:

element.getClass():class LogRecord
element.getClass() == ExtLogRecord.class:false
element instanceof ExtLogRecord:false
element instanceof LogRecord:true
element.toString():LogRecord@182f0db

element.getClass():class ExtLogRecord
element.getClass() == ExtLogRecord.class:true  
element instanceof ExtLogRecord:true  
element instanceof LogRecord:true
element.toString():ExtLogRecord@192d342

The output is obvious. An instance of superclass is not and can not be an instance of any of its subclasses. Similarly, LogRecord.class cannot be equal to ExtLogRecord.class.

Upvotes: 6

Related Questions