Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler error instance of final class [duplicate]

Tags:

java

The following code compiles fine:

interface Flyer{ }
class Bat { }

public class App {

    public static void main(String[] args) { 
        Bat b = new Bat();
        if(b instanceof Flyer) System.out.println("b is a Bird");
    }

} 

If we make the Bat class final, the code doesn't compile:

final class Bat { } 

If the final class implements Flyer, it compiles fine:

final class Bat implements Flyer { } 

Anyone care to explain the logic behind this?

like image 374
html_programmer Avatar asked Jan 03 '16 15:01

html_programmer


People also ask

What is the error duplicate class?

This may be due to an unsuccessfull name change of the module. In such a case, the module is copied in the javasource folder in the app directory with a new name and the old folder is kept, resulting in two identical folders with different names.

What is duplicate class in Java?

The "duplicate class" error can also occur when the class is named the same with the same package naming hierarchy, even if one of the classes exists in a directory structure with directory names different than the package names. This is shown in the next screen snapshot.

Can a class have same name as field?

Yes, It is allowed to define a method with the same name as that of a class.


2 Answers

When you make class Bat final, you're saying that this class can't be sub-classed. Since Bat does not implement the interface Flyer, the compiler is able to determine that b instanceof Flyer can never be true and raises an error.

This is specified in JLS section 15.20.2:

If a cast (§15.16) 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.

Additionally, from section 15.16 about cast expressions:

It is a compile-time error if the compile-time type of the operand may never be cast to the type specified by the cast operator according to the rules of casting conversion (§5.5).

In this case, Bat can never be cast to Flyer: it doesn't implement it and final ensures that there can't be sub-classes that would implement it.


As you found out, the fixes are:

  • Make Bat implement Flyer: in this case, the instanceof operator would always return true.
  • Remove the final identifier, implying that there could be sub-classes of Bat implementing Flyer.
like image 196
Tunaki Avatar answered Oct 13 '22 10:10

Tunaki


Well, if Bat is a final class and it doesn't implement Flyer, it can't have any sub-class that would implement Flyer either, so instanceof can never return true. In such cases the compiler doesn't allow this expression (i.e. (x instanceof Y) is only allowed if there's a chance that x would contain a reference to an instance that implements or extends Y).

In your second snippet Bat already implements Flyer, so b instanceof Flyer would always return true, regardless of whether Bat is final or not.

like image 40
Eran Avatar answered Oct 13 '22 09:10

Eran