Carloshf
Carloshf

Reputation: 539

Method not applicable for arguments with generics

I am no expert with generics and as I am trying to do a reengineering of some classes to avoid code repetition, I am forcing myself to use generics in order to do it the best way possible.

I am getting the next error in the lines I marked:

The method delete(Long) in the type CrudRepository is not applicable for the arguments (capture#5-of ? extends KeyProfileEntity)

Here my class:

public abstract class KeyProfileService {

    protected CrudRepository<? extends KeyProfileEntity, Long> myRepository;

    public List<KeyProfileEntity> getList() {
        List<KeyProfileEntity> result = new ArrayList<>();
        this.myRepository.findAll().forEach(result::add);
        return result;
    }

    public KeyProfileEntity create(KeyProfileEntity entity) {
        return this.myRepository.save(entity);                      //error
    }

    public boolean delete(long id) {
        if (this.myRepository.exists(id)) {
            this.myRepository.delete(this.myRepository.findOne(id));//error
            return true;
        }
        return false;
    }

    public void update(KeyProfileEntity entity) {
        this.myRepository.save(entity);                             //error
    }

    public KeyProfileEntity getEmployee(long id) throws NotFoundEntryException {
        if (this.myRepository.exists(id))
            return this.myRepository.findOne(id);
        throw new NotFoundEntryException();
    }

}

I think this is all the info you guys need, otherwise comment and I will attach more.

Thanks in advance!

Upvotes: 0

Views: 1261

Answers (1)

Tamas Rev
Tamas Rev

Reputation: 7166

You can fix it by removing the <? extends ...> bound wildcard from myRepository:

protected CrudRepository<KeyProfileEntity, Long> myRepository;

As far as I can see, your class will be still usable, even with subclasses of KeyProfileEntity:

    KeyProfileService service = new KeyProfileServiceImpl();
    service.update(new ChildKeyProfileEntity());

There will be only one limitation: getList() will always return a List<KeyProfileEntity>, not a List<ChildKeyProfileEntity>.

Alternatively, you can make the KeyProfileService generic and make sure you use a bound, known subtype:

public abstract class KeyProfileService<K extends KeyProfileEntity> {

    protected CrudRepository<K, Long> myRepository;

    public List<K> getList() { // using K
        List<K> result = new ArrayList<>(); // here too
        this.myRepository.findAll().forEach(result::add);
        return result;
    }

    public K create(K entity) { // using K
        return this.myRepository.save(entity);
    }
...
}

Upvotes: 2

Related Questions