Return an array from a common class. How to print data from an array in the main method?

I cannot figure out how I should use the returned array from returnItems() in the main method. I'm a little intimidated by the generic types. I lose confidence if I continue my dream of becoming a Java developer. When I read some code by professionals, it seems like they like to use generics, but I find it very intimidating. I would appreciate it if I could get a good reference to generics that I can easily understand.

 public class Generic<T> { private int pos; private final int size; private T[] arrayOfItems; public Generic(int size) { this.size = size; pos = 0; arrayOfItems = (T[]) new Object[size]; } public void addItem(T item) { arrayOfItems[pos] = item; pos++; } public void displayItems() { for(int i = 0;i<pos;i++){ System.out.println(arrayOfItems[i]); } } public T[] returnItems() { return arrayOfItems; } } public class GenericTesting { public static void main(String[] args) { Generic<String> animals = new Generic<String>(5); Generic<Integer> numbers = new Generic<Integer>(5); animals.addItem("Dog"); animals.addItem("Cat"); animals.addItem("Bird"); animals.addItem("Mouse"); animals.addItem("Elephant"); animals.displayItems(); numbers.addItem(1); numbers.addItem(2); numbers.addItem(3); numbers.displayItems(); for(int i=0; i < animals.returnItems().length;i++) { System.out.println(animals.returnItems[i]); } } } 
+3
source share
5 answers

returnItems() is a method that returns an array, not the array itself, so you cannot try to reference the index on it, as you are trying to do here:

  System.out.println(animals.returnItems[i]); 

What you need to do is reference the index of the array returned from the method as follows:

  System.out.println(animals.returnItems()[i]); 

Edit

You also had a problem with how you store your data and return it. In your constructor, you create arrayOfItems as an Object array:

  arrayOfItems = (T[]) new Object[size]; 

... but you are trying to return it as an array of T in returnItems() :

 public T[] returnItems() { return arrayOfItems; } 

When you try to run your code, you will get an exception:

 java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String; 

This is due to what is called type erasure . Basically, the Java compiler will replace all of your generic types with regular classes ( Object in this case) and insert throws to maintain type safety.

So this line from your main() method:

  for(int i=0; i < animals.returnItems().length;i++) 

will see that animals is a Generic<String> and turns into this:

  for(int i=0; i < ((String[])animals.returnItems()).length;i++) 

But the array you are returning was created as new Object[] , not a new String[] , and you cannot omit it unless the object actually has a child type, therefore an exception.

To eliminate ClassCastException , you can change returnItems() to declare its actual return type as follows:

  public Object[] returnItems() { return arrayOfItems; } 

This will not allow the compiler to try to insert an illegal listing of the array, but then you will need to manually translate each element into the corresponding type manually, which will defeat the purpose of using generics in the first place.

As pointed out by JBNizet in the comments above, arrays and generics β€œdon't mix well,” so you better use ArrayList<T> instead of T[] to store your data.

+3
source

The code you wrote does not work because T[] initialized as Object[] . When you return T[] to the returnItems() function, you actually return Object[] , and therefore you cannot treat it like String[] .

Use ArrayList<T> instead of T[] (actually this is Object[] ). Using the diamond interface ( new ArrayList<>() ) it automatically displays the type of your items variable:

 import java.util.ArrayList; public class Generic<T> { private final int size; private ArrayList<T> items; private int pos; public Generic(int size) { this.size = size; items = new ArrayList<>(size); pos = 0; } public void addItem(T item) { items.add(item); pos++; } public void displayItems() { for(int i = 0; i < pos; i++) System.out.println(items.get(i)); } public ArrayList<T> returnItems() { return items; } } 

And then use foreach :

 public class Main { public static void main(String[] args) { Generic<String> animals = new Generic<String>(5); animals.addItem("Dog"); animals.addItem("Cat"); animals.addItem("Bird"); animals.addItem("Mouse"); animals.addItem("Elephant"); animals.displayItems(); Generic<Integer> numbers = new Generic<Integer>(5); numbers.addItem(1); numbers.addItem(2); numbers.addItem(3); numbers.displayItems(); for(String animal : animals.returnItems()) System.out.println(animal); } } 
+1
source
 import java.util.Arrays; // ... // in your main: System.println(Arrays.toString(returnItems)); 

which works if you define the toString () method for the printable class (if it's not a primitive type).

+1
source

The reason your code doesn't work has little to do with Generics. Consider the following example:

 public static void main(String[] args) { Object[] objArr = new Object[]{"1", "2", "3"}; String[] strArr = new String[]{"1", "2", "3"}; //the line below doesn't work, it has nothing to do with Generics String[] castedStr = (String[])objArr; //These lines do work Object[] castedObj = (Object[]) strArr; String[] newCastStr = (String[]) castedObj; } 

Core Java 2 Fundamentals says:

"The Java array remembers the type of its records, that is, the element type used in the new expression [] that created it. It is legal to pour Employee [] temporarily to the object [] and discard it, but the array that began its life as an object [] can never be Employee []. "

Now consider what the Java compiler does with your code. It turns your Generic<T> class into this:

 public class Generic { private int pos; private final int size; private Object[] arrayOfItems; public Generic(int size) { this.size = size; pos = 0; arrayOfItems = (Object[]) new Object[size]; } public void addItem(Object item) { arrayOfItems[pos] = item; pos++; } public void displayItems() { for(int i = 0;i<pos;i++){ System.out.println(arrayOfItems[i]); } } public Object[] returnItems() { return arrayOfItems; } } 

As you can see, when you call the returnItems() method, it actually returns Object[] . In your code you did:

 Generic<String> animals = new Generic<String>(5); Generic<Integer> numbers = new Generic<Integer>(5); animals.addItem("Dog"); for(int i=0; i < animals.returnItems().length;i++) { } 

Your code actually takes what was originally Object [], and tries to pass it to String [] (which, I assume, inserts as a Java compiler, as part of type checking). Therefore, the Java compiler translates your loop above:

 for(int i=0; i < ((String[])animals.returnItems()).length;i++) { } 

If you combine these concepts, you will see that what you have come to is a bad situation. You can resolve it without doing anything that other answers have suggested. You can insert the explicit cast in Object[] in your loop above (where I wrote String[] ) and your problems will disappear.

+1
source

You cannot send your object [] back to the string []. Instead, return the array once in Object [], and then depend on the inheritance of the objects to use the correct toString () string.

  Object[] s = animals.returnItems(); for(int i=0; i < s.length;i++) { System.out.println(s[i]); } 
0
source

Source: https://habr.com/ru/post/981123/


All Articles