0

So a barebones example of what I have you can see below. This is what the compiler is telling me:

error: incompatible types
        for (PluginSnapshot snapshot : this.platform.getPlugins()) {
                                                               ^
  required: PluginSnapshot
  found:    Object

This error makes no sense because the type is specified as PluginSnapshot. Any ideas why this could be happening? The issue can be recreated with the following code.

public class Main {
    public static void main(String... args) {
        Platform platform = null;
        for (PluginSnapshot plugin : platform.getPlugins()) {
            // ...
        }
    }
}

public interface Platform<P extends Player> {
    List<P> getPlayers();
    List<PluginSnapshot> getPlugins();
}

public interface Player {
    UUID getUniqueId();
}

public interface PluginSnapshot {
    String name();
}
Evan Lindsay
  • 43
  • 1
  • 9
  • Have you checked what this.platform.getPlugins() returns? May be use a debugger or print statement. – Ashwinee K Jha Mar 27 '17 at 22:55
  • 2
    Other than the missing `class` keyword, this code should work fine. Please post a [mcve]. – shmosel Mar 27 '17 at 22:56
  • I can't debug the code at this time. It's a work in progress and will take quite some time before it will be testable. When I attempt to build with Gradle the error is what I get during the compile process. My ide also infers that the type should be what I specified, but seems to think that the type should be Object rather than PluginSnapshot even though the inferred type should be PluginSnapshot. – Evan Lindsay Mar 27 '17 at 23:00
  • You don't need to debug anything. We just need a reproducible problem. Otherwise, we're trying to deduce your code from the problem, which is much harder than trying to find a problem in your code. – shmosel Mar 28 '17 at 00:05
  • This sort of thing usually happens because raw types are being used. Fortunately the compiler will give warnings. Are there any warnings before the error? – Tom Hawtin - tackline Mar 28 '17 at 00:42
  • @shmosel You can view the project at https://bitbucket.org/enjineer/mp-api/overview I can't accurately reproduce this issue while minimizing it since I don't know the specific cause. The class in question where I'm seeing the issue is https://bitbucket.org/enjineer/mp-api/src/baa1fc3b2ecd35dfc27b726e48527c5074915446/src/main/java/com/enjin/api/platform/sync/RpcGameSync.java?at=master&fileviewer=file-view-default – Evan Lindsay Mar 28 '17 at 03:49
  • Can you add to your code the declaration of the 'platform' field, and the PluginSnapshot class?. Does it have any type-parameter? – Valentin Ruano Mar 28 '17 at 03:49
  • @TomHawtin-tackline I don't see any other related errors – Evan Lindsay Mar 28 '17 at 03:50
  • @ValentinRuano You can view the project files at the links above. As I mentioned I can't minimize the code and reproduce the issue since I don't know what is causing it exactly. Perhaps it's something else with the EnjinPlatform class causing issue, but it's not something that makes any sense to my knowledge. – Evan Lindsay Mar 28 '17 at 03:52
  • @Evan Lindsay, it does not help much that the name of the classes here and in your repo are not the same ones. is RpsSync actually RpsGameSync? is Platform EijinPlatform? – Valentin Ruano Mar 28 '17 at 04:01
  • I think questions should try to be as self-contained as possible but if you expect us to look at the code in a remote location the classes in the question extract should have matching names and and also the package line should be included for that matter. – Valentin Ruano Mar 28 '17 at 04:03
  • @ValentinRuano I have updated the question and corrected the class names so that people can identify what classes to view in the repository. – Evan Lindsay Mar 28 '17 at 04:10
  • @Evan Lindsay, I see now. You are actually omitting important details in you extract. The 'platform' field declaration in RpsGameSync uses the raw type: 'EnjinPlatform'. However 'EnjinPlatform' has type parameters: 'EnjinPlatform' So that is the problem. Please update your extract with these very important details. – Valentin Ruano Mar 28 '17 at 04:16
  • @EvanLindsay let me add that it seems to me that you might be using type-parameters for the wrong thing. They are not meant to be used as aliases for class names. Perhaps you simply need to undo that (replace the type-parameter acronyms in EnjinPlatform.java for the actual class names they extend, and perhaps your problems will go away. – Valentin Ruano Mar 28 '17 at 04:24
  • @ValentinRuano I have implementation specific classes for various platforms that use various subtypes. Shouldn't I still use generics for that? Also, why would the generics affect a method that doesn't rely on the generics? – Evan Lindsay Mar 28 '17 at 04:30
  • @EvanLindsay I guess your code is not that complete and that is the reason one cannot appreciate why using generics here is of any use; so far all reference to EnjinPlatform are to its raw version. I don't see any class that is a descent to EnjinPlatform. I guess you are referring here to some classes that are not available to the public? In anycase that was a side comment, disregard if it does not apply. – Valentin Ruano Mar 28 '17 at 04:40
  • @ValentinRuano Yes, there is a separate repo that is private. The implementations each have their own platform subclass. Classes in the API refer to the raw version while a the implementations have references to the respective platform class. – Evan Lindsay Mar 28 '17 at 04:47
  • What I'm still confused about is how the fact I'm using generics is affecting a method that should be strictly typed to List as the return type but instead returns List – Evan Lindsay Mar 28 '17 at 04:48
  • @EvanLindsay, I'm also puzzled... looking into it. – Valentin Ruano Mar 28 '17 at 04:56
  • @EvanLindsay, Intersting ... if you change the raw platform declaration into a "proper" one: "protected EnjinPlatform,?,?,?,?,?> platform" then the error goes away!!!. Perhaps a rather gray behavior of the compiler... if you don't use the type-parameters all the referred generics and its members behave like raw types even those that do not include type-parameters. – Valentin Ruano Mar 28 '17 at 05:01
  • @EvanLindsay, with that in mind you could compose a self-contained question with a more basic example that shows the odd behavior. I would appreciate if you keep me posted. – Valentin Ruano Mar 28 '17 at 05:03
  • @ValentinRuano That is very odd indeed. I wonder if that is a bug with the compiler perhaps? Seems like very odd behavior to say the least. I'll see if I can't put together a better example to replace the current one with. – Evan Lindsay Mar 28 '17 at 05:07

2 Answers2

0

After speaking with @ValentinRuano we discovered that the behavior is not present when using Platform<?> instead of Platform. I do not know if this is intended behavior or not so I have submitted a bug report to Oracle regarding this issue.

Evan Lindsay
  • 43
  • 1
  • 9
  • I have posted another question with a more simple self-contained code to reproduce this "issue" [here](http://stackoverflow.com/questions/43076830/why-does-using-raw-type-variables-affects-signatures-without-reference-to-type-p) – Valentin Ruano Mar 28 '17 at 18:15
0

Platform is a raw type. References to generic type Platform<P> should be parameterized.

The following code should work:

Platform<Player> platform = ...;

for (PluginSnapshot plugin : platform.getPlugins()) {
  // ...
}
G. Fiedler
  • 664
  • 4
  • 12