Home > Mobile >  Java Unchecked Cast from List containing wildcard to List of a specific type
Java Unchecked Cast from List containing wildcard to List of a specific type

Time:11-17

I have the following classes

public class PathPart {
    private final String pathPart;

    public PathPart(String pathPart) {
        this.pathPart = pathPart;
    }

    public String getPathPart() {
        return pathPart;
    }
}

public class Path {
    private final List<? extends PathPart> pathParts;

    public Path(String path) {
        this.pathParts = getPathParts(path);
    }

    public List<? extends PathPart> getPathParts() {
        return this.pathParts;
    }

    protected List<? extends PathPart> getPathParts(String path) {
        return Arrays.stream(path.split("/")).map(PathPart::new).collect(Collectors.toList());
    }
}

public class FooBarPathPart extends PathPart {
    public FooBarPathPart(String pathPart) {
        super(isFoo(pathPart) ? "bar" : pathPart);
    }

    private static boolean isFoo(String pathPart) {
        return "foo".equals(pathPart);
    }
}


public class FooBarPath extends Path {
    public FooBarPath(String path) {
        super(path);
    }

    @Override
    public List<FooBarPathPart> getPathParts() {
        // UNCHECKED CAST HERE
        return (List<FooBarPathPart>) super.getPathParts();
    }

    @Override
    protected List<FooBarPathPart> getPathParts(String path) {
        return Arrays.stream(path.split("/")).map(FooBarPathPart::new).collect(Collectors.toList());
    }
}

where I'd like to capture the structure of a filesystem path /my/path/to/a/directory in my Path object, which stores my, path, to, a, directory each as a PathPart object.

Now, I have a subclass of PathPart called FooBarPathPart, where if the path part is equal to foo, then I want it to change it to bar. And, I also have FooBarPath which is a subclass of Path, which stores a list of FooBarPathPart. So /my/path/to/foo/directory will essentially become /my/path/to/bar/directory

My issue is that I get an Unchecked cast warning from List<? extends PathPart> to List<FooBarPath> in my getPathParts() method in the FooBarPath class.

Is there a way to get rid of this unchecked cast warning properly? Is my usage of the wildcard correct here? Or is there a better way to approach this problem that doesn't involve the wildcard? I'm not very familiar with generics

CodePudding user response:

Thanks for the help Thomas

I have solved the problem using generics and using a creator function. Here's the full solution:

public class PathPart {
    private final String pathPart;

    public PathPart(String pathPart) {
        this.pathPart = pathPart;
    }

    public String getPathPart() {
        return pathPart;
    }
}

public class FooBarPathPart extends PathPart {
    public FooBarPathPart(String pathPart) {
        super(isFoo(pathPart) ? "bar" : pathPart);
    }

    private static boolean isFoo(String pathPart) {
        return "foo".equals(pathPart);
    }
}

public abstract class AbstractPath<T extends PathPart> {
    private final List<T> pathParts;
    private final Function<String, T> factory;

    public AbstractPath(Function<String, T> factory, String path) {
        this.factory = factory;
        this.pathParts = createPathParts(path);
    }

    public List<T> createPathParts() {
        return this.pathParts;
    }

    private List<T> createPathParts(String path) {
        return Arrays.stream(path.split("/")).map(factory).collect(Collectors.toList());
    }
}

public class Path extends AbstractPath<PathPart> {
    public Path(String path) {
        super(PathPart::new, path);
    }
}

public class FooBarPath extends AbstractPath<FooBarPathPart> {
    public FooBarPath(String path) {
        super(FooBarPathPart::new, path);
    }
}
  • Related