简体   繁体   中英

How to initialize array in Generics with mix data types

I am going through the Java Arrays and additionally, I am looking into generics. Below are the two methods of initializing an array

int[] data = {1,2,3,4,5,6,7,8,9};

// or

int[] data;
data = new int[] {1,2,3,4,5,6,7,8,9};

But when I am using generics, I have mixture of data types for example,

String[] outcome = {"0 wins", "Tie" , "X wins"};

Above array has a single data type of String. What if in an array I have something like below

outcome = {7, "Tie" , 9.0};

now I have a mixture of data types in an array. How I can write it or if it is possible to do with generics? Can I do it with ArrayList?

Thank you

I'd like to correct this:

But when I am using generics, I have mixture of data types

Generics require homogeneous data types. For instance, a List<Integer> is a list that can only ever hold an Integer , and a List<? extends Number> List<? extends Number> can only ever hold Number s, which covers other number types like Long , Short , Double , etc...but are referred to by the single type Number .

Anyway, what you're looking for is a Bag - a collection which can hold any arbitrary object. You can implement this with an Object[] or a List<Object> , and you're going to have to check the type of each element you pull out when you want to use it, since there's no way in Java to have a heterogeneous data type, which is what you're looking for.

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 int s, the results always String s. If we were, for example, change the type of the getReultforFirstTeam() from String to, eg, 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.

1 way to handle this is that you create an array of Object , that can accommodate all of data types

Object[] outcome = {7, "Tie" , 9.0};

And later you can access objects like:

if(outcome[0] instanceof Integer){
   Integer i = (Integer) outcome[0];
}

and vice versa..

outcome = {7, "Tie" , 9.0};

is simply not legal.

You can only use this syntax - an array initializer , where the element type is omitted after the equals - in a variable declaration, eg

Object[] outcome = {7, "Tie" , 9.0};

As mentioned earlier, you could use an Object array. Alternatively, you can use a generic class. Here's an example:

public class Queue<E> {

    private ArrayList<E> queue;

    /**Unparametrized constructor**/
    public Queue() {
        queue = new ArrayList<E>();
    }

    /**Enqueues an element into the queue.**/
    public void enqueue(E val) {
        queue.add(val);
    }

    /**Dequeues an element from the queue.**/
    public E dequeue() {
        E output = queue.get(0);
        queue.remove(0);
        return output;
    }

    /**Gets the current size of the queue.**/
    public int size() {
        return queue.size();
    }
}

Read up on generics and how to use them.

You're going to have to create an array of objects, since all objects in java extends Object :

Object[] arr = new Object[3];
//to add objects to it:

arr[0]=new String("element at index 0");
arr[1]=new Integer(1);
arr[2]=new Character('2');

And to find if the object at index x is (for example) an Integer then your going to have to use a cast:

int x = (Integer)arr[x]; //x could be 0 or 1 or 2

Also you can do it with an ArrayList :

List<Object> listObjects = new ArrayList<Objects>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM