tl;dr: In my opinion, arrays are not a good fit for the problem, you should use objects instead.
This is not a direct answer to your question, but an answer in the form of a redesign.
First of, let us tackle your statement about generics and arrays. Arrays are covariant and retained, while generics are invariant and erased.
- Covariant means that when
B extends A, you can Write A[] aArray = new B[someSize];. Invariant means that this is not possible: ArrayList<A> aList = new ArrayList<B>(); will lead to a compile time error.
- Retained means that the information about the type is retained at runtime: an array always "knows* what type its elements has. Erased means that the type information is gone after compilation. This is also called Type Erasure.
The mixture of covaraint and retained vs. invariant and erased has good potential to get you into trouble. That is the reason why ArrayList uses an Object[] instead of a T[] as its backing datastructure.
Now to the actual question. As was already said by others, we could go down the road ande create an Object[]. I would strongly advice against this since we loose all type information. The only way to get back that information is a instanceof check, which makes your code rigid. Imagine you change the type of an entry. In this case, the instanceof will return false, possibly leading to unwanted behavior and (best case) some test turning red or (worst case) we may not notice it.
Now how to get around this? We create a class representing (what I infer are) match results:
public class MatchResult {
private final int firstTeamScore;
private final int secondTeamScore;
public MatchResult(final int firstTeamScore, final int secondTeamScore) {
this.firstTeamScore = firstTeamScore;
this.secondTeamScore = secondTeamScore;
}
public int getFirstTeamScore() {
return firstTeamScore;
}
public int getSecondTeamScore() {
return secondTeamScore;
}
public String getResultForFirstTeam() {
if (firstTeamScore > secondTeamScore) {
return "Win"; // In an actual implementation, I would replace this with an enum
} else if(firstTeamScore = secondTeamScore) {
return "Tie";
} else {
return "Lose";
}
}
// You can add a method public String getResultForSecondTeam(), I omitted it for brevity
}
What have we won? We have types. The scores are always ints, the results always Strings. If we were, for example, change the type of the getReultforFirstTeam() from String to, e.g., an Enum, we would get compiler errors for all locations where the type does not match anymore. Thus, we hone the fail-fast design and are forced to modify the code where necessary. And thus, we do not even have the chance to get the sneaky, unwanted behaviour we had before.