Constraining generic parameters to be different types in Java

DGoiko :

I don't remember the correct name of this, that's why I can't Google it, so I'll ask this using an example, so it will inmediatly ring a bell.

This is for Java.

I'm using abstract classes and interfaces with bounded type parameters, just like this:

public interface DBInterface<T, E> {
    public int delete(T element);
}

My problem is that when I try to overload a function like this:

public interface DBInterface<T, E> {
    public int delete(T element);
    public int delete(E example);
}

The IDE complains about T may beign the same than E, so it thinks I'm declaring the exact same method twice (because, in fact, T could be the same than E in that declaration).

My questiosn are:

  1. How is this called? I want to rewrite the question using proper terminology so it becomes more usefull for others in the future
  2. How can I declase T and E in the interface to guarantee they will not be the same type?

Something like this:

public interface DBInterface<T, E != T> {
    public int delete(T element);
}

The way I'm doing it right now is by delimiting the legal types like this. Is it the correct way? Is there a way to allow ANY object EXCEPT the other one provided?:

public interface DBInterface<T extends DatabaseObject, E> {
}
ernest_k :

There's a problem because the compiler has to use erasures of parameterized types for your methods. As T and E don't make it to the runtime, the compiler replaces your method parameter types in a systematic way.

As per the tutorial (check this and this), unbounded type parameters are replaced with Object, and bounds are enforced for bounded type parameters. This is to say that your compiled interface method signatures are like this:

public interface DBInterface {
    public int delete(Object element);
    public int delete(Object example);
}

And your second version:

public interface DBInterface<T extends DatabaseObject, E> {
    public int delete(DatabaseObject element);
    public int delete(Object example);
}

I believe this makes the problem obvious for your first code snippet.

How can I declare T and E in the interface to guarantee they will not be the same type?

This question can't accept an unqualified answer. The actual answer depends on the meaning of T and E. For example, it wouldn't make sense to suggest that these type parameters be bounded differently, because that may make no sense in some cases.

With that said, one thing that you should consider is renaming methods: I can't think of a DBInterface with two similarly typed parameters that don't play different roles. For example, the methods can be:

public int deleteById(T element);
public int deleteByKey(E key);

In other words, if we were to forget about single-letter generic type names convention, what would you name your type parameters?

public interface DBInterface<IdColumnType, PKColumnType> {}

I don't see why this shouldn't be applied to your method names, you have to acknowledge that you've allowed your users to pass the same class for both type arguments, after all... (that's to say that you'd technically still have a problem even if the compiler didn't do type erasure)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=80844&siteId=1