0

Why does this code not compile?

package sk.qpp.tmp.generics.simple;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.List;
import java.util.Optional;

@RequiredArgsConstructor
@Getter
// Why does simple commenting out of generics make code compilable? Intention is to use F generics for list of folders attribute
public class GSimpleFolder <F extends GSimpleFolder> {
    private final String folderName;
    private final List<GSimpleFolder> folders;
    //private final List<F> folders;


    public GSimpleFolder getParentAccordingPathToFileOrFolder(String path) {
        final String[] pathSegments = path.split("/");
        GSimpleFolder currentFolder = this;
        // first part is name of root folder
        for (int i = 1; i < pathSegments.length - 1; i++) {
            final int finalVersionOfI = i;
            currentFolder = currentFolder.getFolders().stream()
                    .filter(f -> 0 == pathSegments[finalVersionOfI].compareTo(f.getFolderName()))
                    .findFirst()
                    .orElse(null);
            if (null == currentFolder) {
                throw new RuntimeException("Folder \"" + pathSegments[finalVersionOfI] + "\" has not been found, when searching for parent folder for path \"" + path + "\". i=" + i);
            }
        }
        return currentFolder;
    }
}

Making GSimpleFolder not be generic (it is not using it now anywhere), compilation does work OK. Currently "f.getFolderName()" does claim, that f is of type Object and thus no method getFolderName can be called.

PS: Project with given problem can be found here: https://github.com/luvarqpp/InheritanceAndGenerics (it is playground for solving other problem too)

EDIT: Solution for this particular example is to not use RawType (i.e. class with generic, without specifying given generics). I have added all generics where needed, including in class definition.

package sk.qpp.tmp.generics.simple;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.List;

@RequiredArgsConstructor
@Getter
public class GSimpleFolder <F extends GSimpleFolder<F>> {
    private final String folderName;
    private final List<F> folders;


    public F getParentAccordingPathToFileOrFolder(String path) {
        final String[] pathSegments = path.split("/");
        F currentFolder = (F) this;
        // first part is name of root folder
        for (int i = 1; i < pathSegments.length - 1; i++) {
            final int finalVersionOfI = i;
            currentFolder = currentFolder.getFolders().stream()
                    .filter(f -> 0 == pathSegments[finalVersionOfI].compareTo(f.getFolderName()))
                    .findFirst()
                    .orElse(null);
            if (null == currentFolder) {
                throw new RuntimeException("Folder \"" + pathSegments[finalVersionOfI] + "\" has not been found, when searching for parent folder for path \"" + path + "\". i=" + i);
            }
        }
        return currentFolder;
    }
}
Lubo
  • 1,621
  • 14
  • 33
  • 2
    Because you are using `GSimpleFolder` as a *raw type* in various places (the type of `currentFolder` in particular). – Sweeper May 17 '22 at 11:28
  • I do not get it. Removing generics *F* (which is not used anywhere) will make code compile. `currentFolder.getFolders().stream()` should be stream of type `GSimpleFolder`, so why does filter method does not "see" it? edit: yes, raw type. I get it. thanks. – Lubo May 17 '22 at 11:34
  • 1
    Removing the generic type parameter makes `GSimpleFolder` a regular type, not a raw type. This has nothing to do with whether `F` is "used" or not, or whether `filter` "sees" it or not. See the second duplicate target. In short, if you use a raw type, no generic methods for you :) So don't use raw types. – Sweeper May 17 '22 at 11:39

0 Answers0