Home > Enterprise >  method in class cannot be applied to give types when using generic methods
method in class cannot be applied to give types when using generic methods

Time:08-04

I have this code that is meant to count all duplicates in any given generic type list

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] x = new int[]{1, 2, 3, 1, 4, 3};
        System.out.println(util.countAllDuplicates(x));
    }
}

class util {
    public static <T> int countAllDuplicates(T[] myLis){
//    public static int countAllDuplicates(int[] myLis){
        int duplicates = 0;
        for (int i = 0; i < myLis.length; i  ) {
            for (int j = i 1; j < myLis.length; j  ){
                if (myLis[i] == (myLis[j])) {
                    duplicates  ;
                }
            }
        }
        return duplicates;
    }
}

If I were to uncomment the header that takes int[] instead of T[], then it works perfectly fine.

However, once I try to use a generic type I get the error:

java: method countAllDuplicates in class util cannot be applied to given types;
  required: T[]
  found:    int[]

Why is this? Shouldn't int[] be considered as T[]?

I suspect the issue is in the method header but after looking at multiple resources I'm still unsure how to fix it.

Futhermore, I tried to instead use an ArrayList instead:

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> x = new ArrayList<>(Arrays.asList(1, 2, 3, 1, 4, 5, 4));
        System.out.println(util.countAllDuplicatesArrayList(x));
    }
}

class util {
    public static int countAllDuplicatesArrayList(ArrayList myLis){
        int duplicates = 0;
        for (int i = 0; i < myLis.size(); i  ) {
            for (int j = i 1; j < myLis.size(); j  ){
                if (myLis.get(i).equals(myLis.get(j))) {
                    duplicates  ;
                }
            }
        }
        return duplicates;
    }
}

and it magically works! (although I do get a warning that I am using a raw parameterized class which isn't ideal)

So three questions:

  1. how is using a raw parameterized class allowed but not using a generic list type- shouldn't it be fundamentally the same thing other than the slight caveat that one can't use primitive types?

  2. how would I get the method to work with generic list types?

  3. If I were to use the ArrayList method, how would I avoid the Raw use of parameterized class 'ArrayList' warning?

Any help would be greatly appreciated

CodePudding user response:

Well, a primitive array is kind of special. An int[] itself is an object (JLS § 10), but its component type (JLS § 10) is not. That's why assigning an int[] to T[] is not possible. If your occurrences of int[] were replaced by Integer[], it would also work.

It's better to use Lists alltogether instead of arrays: Lists are more flexible, as they can be resizable and give you more control over who can access its components, and in some cases, arrays don't work well with generics.

  1. First of all, raw types shouldn't be used. A lot of the aspects of raw types are discussed in this Stack Overflow post.

  2. Your countAllDuplicatesArrayList can be easily fixed by providing the type parameter: ArrayList<T>.

  3. Always provide the necessary type arguments.

In short, the method declaration should be like this:

public static <T> int countAllDuplicatesArrayList(List<T> myLis) {
    ...
}

Further notes:
  • You should follow the Java Naming Conventions: class names are written in PascalCase, so util should be Util.
  • I have used List<T> as parameter, instead of ArrayList<T>. This post discusses why you should do this.

CodePudding user response:

int is a primitive data type that cannot be used in this case. If you use Integer instead, your initial code works:

Integer[] x = new Integer[] { 1, 2, 3, 1, 4, 3 };

See https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#instantiate

  • Related