0

Specifically, if I return a filled ArrayList do I have to return the type with it such as ArrayList<modNode>? To add onto this, if i'm using a generic typing for a custom link list that uses the <T> tag would I have to return ArrayList<modNode<T>>? Just a little curious on the properties of ArrayLists containing generic objects... Thanks in advance!

Chase Allen
  • 23
  • 1
  • 7
  • It's not quite clear what you're asking. Can you offer an example of what you mean? – Kevin Anderson Aug 10 '18 at 03:21
  • Can you please share the code and the problem you are facing? – Dinesh Aug 10 '18 at 03:22
  • If you turn on all compiler warnings, the compiler will tell you when you are improperly returning a raw type or any other unsafe type. It’s good practice in general to turn on all the warnings. – VGR Aug 10 '18 at 04:55

2 Answers2

4

Let's say you have a method that returns an ArrayList of String objects:

public ArrayList<String> foo() {
    ArrayList<String> list = new ArrayList<>();
    // ... fill list ...
    return list;
}

This is how you would normally1 declare the method in Java 5+ (since the addition of generics). But you don't have to do this. You could declare the method as:

public ArrayList foo() {
    // ... code ...
    return list;
}

This would mean you are using raw types. Unless you are interacting with a legacy (pre Java 5) library/application you never want to use raw types. The reason is because a raw type is (nearly?) equivalent to returning ArrayList<Object>. You've just lost all type safety given by generics. The reason for generics is to provide compile-time2 type checks so you don't accidentally use the wrong types. For instance, you could now add a Dog to the ArrayList returned by foo even though you intended it to only contain String objects. Also, code using the returned ArrayList has no guarantee that there will only be String objects inside the ArrayList which can result in all sorts of headaches.

You could get around raw types by casting:

String element = (String) foo().get(0);

However, that's basically what generic code compiles down to anyway; except you no longer have compile-time safety.

If the element type is also generic then yes you would want to return that information as well. Let's say you return an ArrayList of Supplier objects instead. It will be each Supplier that returns the needed String objects.

public ArrayList<Supplier<String>> foo() {
    // ... code ...
}

It's important you give the Supplier's generic signature here so you can do things like:

for (Supplier<String> sup : foo()) {
    String str = sup.get();
    // .. do something with "str" ...
}

If you returned ArrayList<Supplier> then each Supplier.get() would return an Object. You've lost all type safety again.


1. You would actually, in virtually all cases, want to return List rather than ArrayList. It's best to program to an interface.

2. It only works at compile-time due to type erasure. Also see this.

Slaw
  • 25,955
  • 5
  • 33
  • 58
0

The type parameter <T> depends on the actual Type Parameter you supply to Generic Type. For example:-

   List<String> names = new ArrayList<>();

String is the actual type parameter of parameterized type List<String>. Behind the scene compiler did casting on each elements automatically. So you can safely expect get method will return String type.

The modNode class is generic type. Then caller has to declare what is the actual type parameter. It could be String, type that extends Node or whatever. Example below:-

   List<modeNode<String>> modeNodes = new ArrayList<>();

However your ArrayList<modNode<T>> actual type parameter is already modeNode. Hence get method will probably returns some kind parameterized type modeNode<T>. Ex:-

   List<modeNode<String>> modeNodes = new ArrayList<>();
   ....
   modeNode<String> mn = modeNodes.get(0);

Notes:-

** Rename modNode type class name to ModNode to follow Java convention. Class name must start with Capital letter.

   ModeNode<Node> mn = ModeNode.getInstance();
   //More readable due to following naming convention.
   List<ModeNode<Node>> mns = new ArrayList<>();

** It is preferable to declare as interface type Listthan concrete type ArrayList. Unless if you want to use specific ArrayList behaviour implementation.

Awan Biru
  • 363
  • 2
  • 9