• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

How to call a generic method when I only have an Object

 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I have an interface that specifies an encoder in a generic way. It specifies a method to convert an object of type T, resulting in a byte array:

I have several implementations of this, for example:

Now I have a heterogenous list of values (in a List<Object>), and I want to encode each of these using the appropriate encoder. However, the encode method of each encoder can only be called with the specific type that it accepts - it can't be called with a plain Object:

How can I call the encode method of the encoder?

I want to keep the encoders type-safe (i.e. keep the generics in the Encoder interface).

It can be done with reflection, but is there also another way without using reflection?
 
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm not 100% sure this would work, but it's the first thing that springs to mind (and it compiles!): try wrapping the Encoder in a generic "untyped" encoder. Within that wrapper you have access to the generic type, so you can cast the object. Like this:Then you can use it like this:
Any use?
 
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You're going to need an unsafe cast there somewhere. You can try forcing encoder into an Encoder<Object> reference. The compiler sees it as unsafe, but as long as you guarantee that encoder and value match types then that shouldn't be a problem.

Matthew: nice try, but the extra class is unnecessary. With it I get two warning because you're creating a raw EncoderWrapper instance, then assigning that to the typed wrapper variable. I can get only one warning (unchecked cast) with only one line of code:
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:Matthew: nice try, but the extra class is unnecessary. With it I get two warning because you're creating a raw EncoderWrapper instance, then assigning that to the typed wrapper variable.


Yeah, fair enough. My "theory" (which I felt was not quite right, but I didn't get any warnings so thought I might have got away with it) was that the typed encoder I was passing into the constructor would provide the generic type of the wrapper. But of course that doesn't actually work because the compiler doesn't know what type it is....

Blame the C# I've been learning recently.
 
Ranch Hand
Posts: 492
Firefox Browser VI Editor Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Couldn't you just use the Object class' getClass() method to determine what type of object you are looking at as you encounter them and declare the Encoders conditionally?

ex:


Hunter

 
Rob Spoor
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Getting the Encoder isn't the issue. It's calling the encode method of an Encoder<?> (type unknown; your example shows just why) using Object as argument. Sure, you could put the encoding within the if-statement, but I'm thinking Jesper's Encoder<?> lookup is a bit different than this one (perhaps using a Map?).
 
Hunter McMillen
Ranch Hand
Posts: 492
Firefox Browser VI Editor Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm I see that now, I was so focused on getting the correct encoder I completely missed the issue with the call to encode.

Hunter
 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Remember that Java generics are a compile-time construct: they exist only in the mind of the compiler. Any code that has to make a runtime decision about unknown types is going to be forced to include unsafe casts, by definition. Fact of life, unfortunately.
 
Jesper de Jong
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Rob's solution looks simple, I'll try that.

Ofcourse there has to be an unchecked cast somewhere to do this, so it's not going to be 100% type-safe, but at least I can implement the encoders themselves in a type-safe way - one thing I thought of was leaving the generics out of the interface, and just pass or return Object, but that's not so good, especially since I need to implement a list of different encoders for different Java types.

It's actually the same situation as a question that comes up on the forums here every now and then - why you can't add elements to a List<?>: because the compiler doesn't know what the type "?" is, so it has no way to check that you pass the right type of object.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic