Home > Software engineering >  why is this still need to cast in java?
why is this still need to cast in java?

Time:05-13

error

public class DefaultLiteProcessScopeFactory<S extends DefaultLiteProcessScope> implements LiteProcessScopeFactory<S> {
    @Override
    public S build() {
        return new DefaultLiteProcessScope();
    }
}

right

public class DefaultLiteProcessScopeFactory<S extends DefaultLiteProcessScope> implements LiteProcessScopeFactory<S> {
    @Override
    public S build() {
        return (S) new DefaultLiteProcessScope();
    }
}

DefaultLiteProcessScope extends DefaultLiteProcessScope,but it is till need to be cast?why?

CodePudding user response:

The reason is that the code is wrong.

public class MyOtherFactory<SubclassOfDefaultLiteProcessScope> {}

will break because DefaultLiteProcessScope is not a SubclassOfDefaultLiteProcessScope.

CodePudding user response:

S extends DefaultLiteProcessScope, so you're trying to return the parent class instance instead of child class instance.

CodePudding user response:

Your code would throw a ClassCastException in the following instance:

class CustomLiteProcessScope extends DefaultLiteProcessScope { ... }

final DefaultLiteProcessScopeFactory<CustomLiteProcessScope> factory = new ...;

And then:

factory.build(); <-- Exception trying to cast DefaultLiteProcessScope to CustomLiteProcessScope

CodePudding user response:

What you are doing here is wrong. You want to return some subtype of DefaultLiteProcessScope from the build method. However, you hard code the return type like this: new DefaultLiteProcessScope(). Now think of a slightly contrived example like this.

static class SubType extends DefaultLiteProcessScope {
        
}

And a client code that follows.

final LiteProcessScopeFactory<SubType> f = new DefaultLiteProcessScopeFactory<>();
final SubType result = f.build();

Now, since you have hard-coded the return type your compiler can't vouch for the type safety of the code. I wanted it to return the sub type, however you have hard-coded the super-type instead. So, it asks you to add an explicit cast, which is fair, isn't it? In fact, this cast fails at runtime throwing a java.lang.ClassCastException since super type DefaultLiteProcessScope cannot be cast to the subtype SubType.

How to fix.

A much better approach would be to pass in a supplier to your build method as an argument like so.

static class DefaultLiteProcessScopeFactory<S extends DefaultLiteProcessScope> implements LiteProcessScopeFactory<S> {
    @Override
    public S build(Supplier<S> s) {
        return s.get();
    }
}

static interface LiteProcessScopeFactory<S> {
    S build(Supplier<S> s);
}

Here's the new client code.

final LiteProcessScopeFactory<SubType> f = new DefaultLiteProcessScopeFactory<>();
final SubType result = f.build(SubType::new);
  • Related