Java generics and wildcards are compiled in eclipse, but not in javac

As a follow-up Java genetics compile in eclipse, but not in javac, I released another code segment compiled and running well in eclipse, but caused a compilation error in javac (this prevents the project from extracting the code snippet from the Maven build.)

Self contained fragments:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class Main {
  public static void main(String[] args) {
    Set<Foo<?>> setOfFoos = new HashSet<Foo<?>>();
    List<Foo<?>> sortedListOfFoos = asSortedList(setOfFoos);
  }


  public static <T extends Comparable<T>> List<T> asSortedList(Collection<T> c) {
    List<T> list = new ArrayList<T>(c);
    java.util.Collections.sort(list);
    return list;
  }


  public static class Foo<T> implements Comparable<Foo<T>> {
    @Override
    public int compareTo(Foo<T> o) {
      return 0;
    }
  }
}

Compilation return in javac:

Main.java:11: <T>asSortedList(java.util.Collection<T>) in Main cannot be applied to (java.util.Set<Main.Foo<?>>)
    List<Foo<?>> sortedListOfFoos = asSortedList(setOfFoos);
                                    ^

Replacing foo  and foo < string >, the code snippet above will be compiled in javac, which means that the problem is related to the wildcard used Since the eclipse compiler should be more tolerant, code snippets may not be valid Java?

(I use javac 1.6.0_37 and eclipse indigo, compiler compliance level 1.6)

(Edit1: include another example deleted in edit2)

Edit2: ireputable hint: it may be conceptually wrong to compare foo A and foo B. It is inspired by the answer of sEH. A working assortedfoolist can be written as follows:

public static <T extends Foo<?>> List<T> asSortedFooList(Collection<T> c) {
    List<T> list = new ArrayList<T>(c);
    java.util.Collections.sort(list);
    return list;
}

(in the above method definition, foo < T > is simply used to replace the comparable < T >) so it seems safe for javac and IMHO. Conceptually, compare any foo < a > and foo B. However, if the type parameter is parameterized with wildcards, the general method assortedlist cannot be written, which returns the sorted list representation of a general set I tried to replace foo "Spoofing" javac can compare < s > in assortedfoolist through s extension, but this doesn't work

Edit3: rafaelle later pointed out that there were defects in the design, because the implementation of comparable < foo > > was not necessary, and the implementation of comparable < foo > > provided the same function to solve the initial problem through careful design

(the initial reason and advantage is that foo & T may not care about its specific type for some purposes, but still use the instance of specific type T. for other purposes, it is instantiated. This situation does not have to be used to determine the order between other foos, because it may be used in other parts of the API

Specific example: suppose that each foo is instantiated with different type parameters of T Each instance of foo has an incremental ID of type int, which is used to implement the CompareTo method We can now sort these different types of foos, and we don't care about the specific type T (represented by foo), and there is an instance of specific type T for subsequent processing.)

Solution

For me, this is another javac bug When you try to send collection < < foo > Method with signature:

public static <T extends Comparable<T>> List<T> asSortedList(Collection<T> c)

The compiler notes that the formal parameter t has an upper bound, so it checks whether the bound is respected by the caller The type parameter is a (wildcard) instantiation of the parameterized type foo < T >, so if foo < > is-a comparable < foo < > Based on common definitions:

class Foo<T> implements Comparable<Foo<T>>

I would say this is true, so eclipse is right and javac has an error This Angelika Langer's entry has never had enough contact See also the relevant JLS

Do you ask if the type is safe? My answer is that it is type safe, which indicates that your design is flawed Considering the comparable < T > interface of your virtual implementation, I added two fields:

public static class Foo<T> implements Comparable<Foo<T>> {

  private T pState;
  private String state;

  @Override
  public int compareTo(Foo<T> other) {
    return 0;
  }
}

You always return 0, so you don't find a problem But when you try to make it useful, you have two choices:

>Compare string Fields > compare t members

The string field is always a string, so you won't benefit from the type variable t On the other hand, t has no other types of information available, so in CompareTo (), you can only deal with an ordinary object, and again, the type parameter is useless You can implement comparable < < foo > > Achieve the same precise function

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>