aspose file tools*
The moose likes Java in General and the fly likes How to call a generic method when I only have an Object Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "How to call a generic method when I only have an Object" Watch "How to call a generic method when I only have an Object" New topic
Author

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

Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 13870
    
  10


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?

Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4240
    
    7

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?
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19541
    
  16

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:

SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4240
    
    7

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.
Hunter McMillen
Ranch Hand

Joined: Mar 13, 2009
Posts: 492

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


"If the facts don't fit the theory, get new facts" --Albert Einstein
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19541
    
  16

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

Joined: Mar 13, 2009
Posts: 492

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
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24166
    
  30

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.


[Jess in Action][AskingGoodQuestions]
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 13870
    
  10

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.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: How to call a generic method when I only have an Object
 
Similar Threads
generics
Generic Method from K&B Master Exam
Simple J2SE 5.0 Tiger Notes
Generics - return types
what does List.toArray(T[]) return?