Win a copy of Learn Spring Security (video course) this week in the Spring forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Java Generics Problem

 
leroy tsruya
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all!
I have a question about generics.
I am trying to create a generic state machine.
so these are the classes:


The problem is with SampleChild1 class.
whenever I try to pass a SampleChild1State1 Object into the setState method of BaseClass I get the following error:
The method setState(State<capture#2-of ? extends BaseClass>) in the type StateMachine<capture#2-of ? extends BaseClass> is not applicable for the arguments (SampleChild1State1)


Is there anyway to solve this problem? to make my StateMachine class generic so I can declare it only in BaseClass?
Or I will have to have a new specific Object of StateMachine class in any subclass of Baseclass?

Thanks!
 
Rob Spoor
Sheriff
Pie
Posts: 20492
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Shouldn't SampleChild1 extend BaseClass?
 
leroy tsruya
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow.. what a dumb mistake..
Thanks a lot Rob Prime.
it should extend it.



It was a mistake when I typed the post into the site..
I edited the original post as well
Thanks..
 
Virendrasinh Gohil
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
leroy tsruya wrote:

Many problems with this sample.

1. SampleChild1State1 is interface? If so, it must extend State interface if not, must defined as class
2. SampleChild1 must extend BaseClass (as State interface can only accept <T extends BaseClass>)


3. The setState method is expected to accept object of StateMachine of type T which extends BaseClass only. Whereas, you are trying to pass SampleChild1State1 which is (if a class) implementation of State itself.
 
Rob Spoor
Sheriff
Pie
Posts: 20492
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Leroy, please PostRealCode. You may choose to omit parts that aren't necessary, but with your current code I have to fix too many compiler errors before I get to the error you get (actually I'm not even there yet).
 
leroy tsruya
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Prime, once again you are right..
really sorry for the inconvenience...
Here is the code I have, I omitted unrelevant stuff:



This is what I get:
The method setCurrentState(EntityState<capture#2-of ? extends BaseGameEntity>) in the type EntityStateMachine<capture#2-of ? extends BaseGameEntity> is not applicable for the arguments (ItemUnidentifiedState)
 
Rob Spoor
Sheriff
Pie
Posts: 20492
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, now I could pinpoint the exact location of the error.

"this.states" is an EntityStateMachine<? extends BaseGameEntity>. And that wildcard is the problem. EntityStateMachine<T> expects a T for its setCurrentState method. However, what is T in this.states? You don't know. It could be BaseGameEntity, InfObject, or anything else that extends BaseGameEntity.

I suggest you make BaseGameEntity generic as well. The class definitions then become as follows:
One more change is required, in BaseGameEntity:
This now matches the initialization of states inside Item:
After these changes I could compile your code.
 
leroy tsruya
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow! Thanks Rob!
It compiles now! No errors at all
However, can you please explain what that line of code means:


And also, if I may.. Is that the best way to do it?
Or, did I complicate it more than it should be?
 
Rob Spoor
Sheriff
Pie
Posts: 20492
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The other alternative is to use I haven't tested if that would compile. If so, that would actually be easier.

As for that line. The T is the new generic type, as usual. Because you had "? extends BaseGameEntity" the T must be bound as well. That would lead to "T extends BaseGameEntity". However, BaseGameEntity is now generic, so the compiler will complain about a raw type. You must fill in the generic type. There are actually more alternatives:
- BaseGameEntity<?> -- any BaseGameEntity is allowed. This would allow Item to extend InfObject<BaseGameEntity>, InfObject<InfObject>, InfObject<Item>, or any other sub class of BaseGameEntity.
- BaseGameEntity<T> -- Item can only extend InfObject<Item>
- BaseGameEntity<? extends T> -- Item can only extend InfObject<Item> and InfObject<X> where X is any sub class of Item
- BaseGameEntity<? super T> -- like ? but limited to BaseGameEntity, InfObject and Item
- BaseGameEntity<X> with X being a hard coded class. You definitely do not want that though.


I think that trying out to remove the "? extends" from states would actually be worth checking out. It will make your classes less complex.
 
leroy tsruya
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks all for the help, especially Rob, you have been a great help for me.
It works perfect now, and I updated other classes I wrote.
Unfortunately, your suggestion seems the only way the code will compile.
Thanks a lot
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic