Meaningless Drivel is fun!*
The moose likes Java in General and the fly likes A question about casting from Object[] Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "A question about casting from Object[]" Watch "A question about casting from Object[]" New topic
Author

A question about casting from Object[]

Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 53
Suppose I have a Deivce that contains Widget(field) and that Widgets have two methods getPartsList() and repairPart(WidgetPart wp). further suppose that there are many types of Widget object, all subclassed from AbstractWidget. There are also many different types of WidgetParts, but these are NOT subclassed from AbstractWidgetPart. These widget-y parts are defined in third party libraries that Device has no contact with (hopefully).


Of course Device doesn't know how repairPart is implemented. In fact it doesn't even know what type of widgety parts that Widget will have. It just knows that it can receive a list of the parts from a particular Widget, and can then repair them as appropriate later by calling repairPart() on a member of that list.

I originally planned that Widget would maintain an ArrayList of its own parts. It could then pass that array list up to its owner (a Device object) by way of its getPartsList method.

Object[] getPartsList(){
return partsList.toArray();
}

In Device I would have something like

Object[] widgetParts = myWidget.getPartsList();
.... Some code....
for (i = 0, i < widgetParts.length, i++) {

myWidget.repairPart(widgetParts[i];
}


But this seems like it won't compile (or at least it shouldn't) because repairPart will need a particular KIND of widget part since it can only repair parts of that kind. Even if it knows that Device is passing an object that was originally of the correct type, but which was cast to Object in the ".toArray()" command of getPartsList, it still can't cast that object to that type. Because Java can't (or at least shouldn't) allow me to cast something of type Object to something that is a subclass of Object. And even if Java did let me do that (some kind of unchecked cast) then what will happen if Device gets the list, and the accidentally changes the contents of the myWidget field before calling myWidget.repairPart?


I considered creating a super class that encapsulated an arbitrary WidgetPart, but the various WidgetParts don't inherit from a common class, and can't be made to do so because I can't multiply inherit.

I think the solution might be some type of Generics programming here, but maybe I am just overlooking the obvious. I would like a fresh set of eyes on it.


Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

So a Widget contains an ArrayList<WidgetPart>? Or more likely, AbstractWidget contains that. Also I don't understand why you are converting the list to an array. Why not just return the list?
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 53
Paul,

AbstractWidget can't contain the ArrayList<WidgetPart> because that would require that All Widgets have parts that inherited from the same class, WidgetPart. They don't. There is no AbstractWidgetPart from which all parts are inherited. The only common ancesstors for all possible parts of all possible Widgets is Object (everything in Java extends Object). And that is fine, I can cast it Object, but then it is a brick. Everything that made it a special kind of part, is gone forever.

Let me be concrete. First recall that Device owns Widget. Widget owns one or more "parts". . All parts of a single widget are the same type but different Widgets have different types of parts. Widgets have methods that take as parameters parts of the same type as the ones owned by that widget.


Lets say that Device is a repair shop. It has two Widgets, NetworkSocketWidget and BicycleWidget. The parts of NetworkSocketWidget might be the remote IP address, the port number and some parameter relating to a particular network card. All of these inherit from a single class called NetworkSocketPart. Calling NetworkSocket.repairPart(NetworkSocketPart nsp) does something that the repair shop doesn't understand. He doesn't need to fix a NetworkSocketPart, NetworkSocketWidget does that for him. He just needs a way to tell his NetworkSocketWidget which part to fix! In a similar way, the parts reported by BicycleWidget might be things like wheels and seat posts and gears. Lets say these all inherit from BicyclePart. Whatever BicycleWidget.repairPart does when it is a passed a BicyclePart, it is going to be entirely different than what what NetworkSocketWidget does to its own to a NetworkSocketPart. And that is the whole point. Device knows nothing about Widget. Only that they have parts, and that those parts can be repaired.


The problem is, BicyclePart and NetworkSocketPart only share one common ancesstor, Object. Everything is an object, but once I cast a part to Object, there is no way to cast it back to the part that it once was.

YOu asked "why not pass up the ArrayList<part> . I could do that if all of the different parts all inherited from AbstractWidgetPart. But they don't, nor can they be made to do so since these parts come from 3rd party libraries and have their own complex inheritance tree.

I really think I am missing something obvious. But I have two solutions so far.

1. getPartsList doesn't return a list of parts, but rather a list of Strings that represent the parts. So one BicycleWidget might return an array of strings that looked like {seat, chain, wheel1, wheel2, frame}. It would then keep track of which String reference went with each real BicyclePart object. Then modify repairPart to accept a String object which is a reference to a part.

2. I could create an WidgetPart interface that includes such function as repairPart. This function would in tern call the static function of the appropriate widget type. so in my example above, BicyclePart implements WidgetPartInterface. Then BicycleWidget.getParts list would return an array of WidgetPartInterface[] objects. Then instead of calling myBicycleWidget.repairPart(myPart), instead call myPart.repairPart(). If myPart is an instance of BicyclePart it will call the static function BicycleWidget.repairPart(this).


Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3605
    
  14

Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Derik Davenport wrote:YOu asked "why not pass up the ArrayList<part> .


Yes. I asked you something like that because I couldn't understand why you would bother converting a List to an array. Just pass the List around already.
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 53
First let me extend my thanks to Paul and Stephan,

I looked at Paul's second request for why I didn't pass the List object, and at Stephan's use of Generics to declare the Widget<P> classes. And I said to myself "What part of my question am I not explaining properly?" Let me give it another try.

What I had was

public class Device{
ArrayList<Widget> widgetList;



If I allow Widget to use generics and become Widget<P> then obviously Device becomes
public class Device<P>{
ArrayList<Widget<P>> widgetList;


As Paul suggested, Widget.getParts() can now pass the ArrayList<P> up to its owner, Device, because Device now knows all about <P>. The problem is that when an instance of Device is created, I don't necessarily know <P>. Widgets of arbitrary type are passed to Device after its creation. My goal is to allow Device to handle all types of widgets the same way (with the same code) regardless of class type of the Widget's internal field. This is why I had Widgets passing up to Device an array of String identifiers (#1 from my second post). If all widgets can create unique identifiers for their parts (no matter class the part is an instance of) then Device can be safely ignorant of the class of widget.parts. It works, but it seems terribly clumsy, and I am looking for a more elegant solution. I might give #2 a try.


Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

So at some point in time a Device has a Widget<T> object (following on from Stephan's code). And the Device can ask the Widget<T> object to give out its List<T> which is a list of parts. But why? The Device doesn't know anything about the parts -- as far as it's concerned they are just any old objects -- so what does it do with them? Can't you encapsulate the part-handling inside Widget?

I also think that representing the parts as strings is a failure to do object-oriented design. I would at least wrap them in a Part object, where the Part class is designed so that the Device can actually do something with the parts.

As for my question about lists versus arrays, that was only because I didn't understand why the conversion from list to array was necessary. There wasn't any technical requirement to do that, so I was just suggesting it wasn't a necessary step.
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 53
Hi Paul,

I also think that representing the parts as strings is a failure to do object-oriented design

I totally agree. That is what I meant by "clumsy".

And the Device can ask the Widget<T> object to give out its List<T> which is a list of parts. But why? The Device doesn't know anything about the parts so what does it do with them?


Mostly it doesn't touch the parts, it just touches Widgets. But, it needs to test the status of Parts and "repair" them as needed. The key part is user interaction. Device basically represents the GUI of my system (or at least it controls many of the GUI's components). Here is some more psuedo code to make it more clear.



Device{
ArrayList<Widget> widgetList = new ArralyList<Widget>;


// Constructor code that extracts widgets from files to build widgetList
// display list of Widgets to user and allow consolidation and elimination of widgets.

// user selects widget from WidgetList.
activeWidget = GUI.component.getSelected();

Object[] partsList = activeWidget.getPartsList(); //at this time Widget was using the ArrayList.toArray() to return an array of Object.
Object activePart = null
for (i = 0, i< partsList.length, i++){
activePart = partsList(i);
if (activeWidget.getStatus( partsList(i) )){
addPartToActivePartsList (activePart);
}
.// interact with user some more (see notes)
...

}
// Now Device has a list of active parts for the chosen widget. If the widget has no active parts, it might simply call Widget.close, or Widget.destroy. Or, depending on parameters by the user it might go in to a waiting routine where by it monitors the status of the parts, and displays a count of active parts on the GUI. If the user gets impatient, He can click a button to tell Device to call activeWidget.repair(part) for each part that was active when the initial status check was done. The widget will know if deactivating the part makes sense or is even physically possible.

And now you can see how this thread got named. Device was passing things of type java.lang.Object to methods like Widget.getStatus, and then having getStatus(part) recast those Objects into instances of a specific class

public class BikeWidget extends Widget{
public Boolean getStatus (Object part){
BikePartOS myPart = (BikePartOS)part; //BikePartOS comes from 3rd party libraries.
return myPart.doStuff()
...

}


But the cast of Object to BikePartOS reminds me a lot of casting void pointers in C to just about anything you want. The Java compiler will let me do it and it will throw a _runtime_ exception if I pass a BikeWidget.getStatus something of type Object which was not originally something of type BikePartOS. But it still annoyed me.



Can't you encapsulate the part-handling inside Widget?


That is exactly what I want to do. But I don't want a lot of GUI stuff in Widgets.
Having written all this out, I think I could change things a little bit so that Widget keeps the list of 'active' parts. then reports status on that list, or reports changes to that list in real time to Device (which can then update the GUI). That is a little counter intuitive in the big picture of my code, but maybe it would be better.

I could extend the third party "PartOS" classes to include the handling code that is currently in Widget for that purpose. This new class could then implement some of the interface (partInterface) that is currently implemented by Widget for that purpose. Then Device, could not know the details of Part, but could still call on parts to do the status checking.






Anyway, thanks again. Just talking it out has really helped clarify the whole thing. Often just explaining something helps me see relationships.







Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Derik Davenport wrote:Anyway, thanks again. Just talking it out has really helped clarify the whole thing. Often just explaining something helps me see relationships.


Yes, I've found that to be true in the past. Only this time I'm the one asking the stupid questions which clarify the requirements. Glad to be of service!
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3605
    
  14

I still don't really understand why you would need an array though. Anyway, here is what your Device class might look like:
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 53
Stephan,

I really liked your use of generics to solve this problem. In particular your use of the wildcard generic <?> in the declaration of the widgets field of Device.

Could I ask you a few questions on style? You use the keyword 'final' a lot more than I do. I am wondering if I don't use it enough. For instance, I would never have considered declaring the BicycleWidget and BicyclePart classes final. A 'final' class can not be extended, but I have never really understood what advantage I get from making one of my classes final, even if it is never extended in code. Similarly you use the final keyword in the declaration of the 'parts' field in the declaration of AbstractWidget<P> (Line #12 of the code in your first post). It is certainly true that this field would never change from the time I first initialize it in the constructor. But do I really get performance advantages for declaring it final? Or is it simply good etiquette to do that whenever you can as a clue to the programmers that come after you?

In an unrelated question you twice used code like this


In that code you declared a field, and then waited until the Constructor to initialize it.

I might have been inclined to move the initialize widgets right in the declaration. After all, it is 'final' and this would ensure it gets initialized exactly once.


Is there some advantage to your method? Or is it just style?



Finally, I am new to JavaRanch. What are these "+1" buttons for?



Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19656
    
  18

Derik Davenport wrote:I might have been inclined to move the initialize widgets right in the declaration. After all, it is 'final' and this would ensure it gets initialized exactly once.

[..]

Is there some advantage to your method? Or is it just style?

Final fields must be either instantiated when they are declared, or otherwise in all constructors that do not call another constructor through this(...). Mostly it's just style, but sometimes the field's value isn't that simple; it may need to be calculated from some constructor arguments, for instance.

Finally, I am new to JavaRanch. What are these "+1" buttons for?

It's like Facebook's Like buttons. You can use them to indicate a post is helpful to you (or others).


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3605
    
  14

Derik Davenport wrote:A 'final' class can not be extended, but I have never really understood what advantage I get from making one of my classes final, even if it is never extended in code.

There is a *huge* advantage to making classes final, if there's no direct cause to extend them. If a class is extensible, there are some extra things you have to think about carefully before you release the class in the wild. You will have to document the class' self-use (methods that call other methods in the same class), because overriding methods may break other methods that depend on them. If the class is Cloneable, you may have to override the clone() method (which is no trivial issue by itself). If you want your subclasses to be able to define their own hashCode(), equals() and compareTo() methods, you can not override them in your extensible class (admittedly, this problem is separate from whether or not your class is final).

The most important reason to make a class final however, is that you can make a final class non-final whenever you want. Once a class is extensible, you can never go back to final.

Similarly you use the final keyword in the declaration of the 'parts' field in the declaration of AbstractWidget<P> (Line #12 of the code in your first post). It is certainly true that this field would never change from the time I first initialize it in the constructor. But do I really get performance advantages for declaring it final? Or is it simply good etiquette to do that whenever you can as a clue to the programmers that come after you?

I just think it's good practice. It tells whomever is reading your code: "This field will never change, that's one less thing for you to worry about".
The compiler might also be able to make small performance tweaks when a field is final, although this is only a very minor benefit, and this should never be the reason for you to make fields final.

In that code you declared a field, and then waited until the Constructor to initialize it.

[...]

Is there some advantage to your method? Or is it just style?

This is purely a personal choice. I like to do this, because I really don't care about what the concrete types of my fields are. It makes it much easier for me to read my list of fields when I have a lot of them.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: A question about casting from Object[]
 
Similar Threads
really need some help here concerning treeNode data types and the like. (data type issues really)
Unchecked cast
Casting
Collections and Generics
Use of Parent reference