[java] how to know the class of an object

Started by
13 comments, last by 5MinuteGaming 18 years, 7 months ago
I know, this is my third topic in a week or so, but this time I'm not even sure what to look for... Well, I created a menu. To this menu I added some separators, some items (JMenuItem) and some sub menus (JMenu). Since they all derive from Component, adding them was easy. Now I need to get those elements, and when I find a JMenu object, I repeat the scan with it. The point is that I don't know how to distinguish from the varius kinds of elements, since getComponent(int) returns a Component object and the best I can do is using getItem(int) wich return a JMenuItem. But JMenu is a JMenuItem derived class...
Advertisement
When you use getComponent(int), and a (J)Component is returned, you can use the instanceof operator to determine what sub-class of (J)Component the returned object actually is.

Like this:
JComponent comp = getComponent(0);if (comp instanceof JMenu) {    JMenu menu = (JMenu) comp;}
Remember, all classes inherit from Object so you could try something like:

String objectName = object.getClass().getName();
//get rid of package info
int index = objectName.lastIndexOf(".");
objectName = objectName.substring(index);

And then have if/case statements that do various things depending on what class you have. A bit clumsy I know but it should work and as long as you don't have too many different classes your code won't get too big and unmanageable. If you intend to do this kind of thing in more than one place in your code it might also make sense to make some kind of controller class which deals with all this, so that as you add more types of components you only have to alter one bit of code to manage them.

I'm not sure exactly what you're doing with this but I suspect that its not the best way to go about it. If you're wanting to associate actions with user input in the menus then look into adding custom actionlisteners to each of your menu buttons

Also check this out for general menu stuff:
http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html
Quote:Original post by Vyper_uk
Remember, all classes inherit from Object so you could try something like:

String objectName = object.getClass().getName();
//get rid of package info
int index = objectName.lastIndexOf(".");
objectName = objectName.substring(index);
...


Except that this will introduce all sorts of unnecessary overhead comparing Strings. Use instanceof as Optus suggests. Although, I do think programming by instanceof is extremely ugly.
Thank you all... instanceof:cool, I never heard about this operator, this may be the solution.
Well, I have a menu. When I need to make an item disabled I have to scan all the menu items till I find the one I need. But how can I distinguish between JMenuItem, JSeparator and JMenu? I cannot recursively call scan(JMenu) on a JSeparator item, for example. Using instanceof, I may do something like:

if(item instanceof JMenu) scan(item);
else if(item instanceof JMenuItem) if(item.getText() == nameIneed)item.setEnabled(false);
else return;
I would do something like this...
int numComponents = menu.getItemCount();for(int i = 0; i < numComponents; i++){    Component comp = menu.getComponent(i);    if(comp instanceof JMenu)    {       // Do stuff    }    // Keep going for each type of Component that you're interested in}

Also look at the api for JMenu... there are all sorts of methods that return arrays of menu items.
The best way to use menus and other components is to keep a reference to them and pass them around between your classes as needed.

Most Java programs end up with a few extended Frame classes which have a lot of private members. For instance:

import javax.swing.*;public class MainWindow extends JFrame {    private JMenu mnuFile = new JMenu("File");    private JMenuItem mnuItmNew = new JMenu("New");    private JMenuItem mnuItmExit = new JMenu("Exit");    public MainWindow() {      super("Component Reference Test");      //add the menu listeners here      mnuItmExit.addActionListener(           new ActionListener() {               public void actionPerformed( ActionEvent e ) {                   setVisible(false);                   dispose();                   System.exit(0);               }      });            //you would keep the reference to the menu item so you can do the enabling and disabling.      mnuItmNew.setEnabled(false);       mnuFile.add( mnuItmNew );      mnuFile.addSeparator();      mnuFile.add(mnuItmExit);      JMenuBar menus = new JMenuBar();      menus.add( mnuFile);            //add the menubar to the frame      setJMenuBar(menus);            getContentPane().add( new JLabel("Passing Component References") );      addWindowListener( new WindowAdapter() {             public onWindowClosing( WindowEvent e ) {                  setVisible(false);                  dispose();                  System.exit(0);             }       });      pack(); }}
But if you still want to lookup the Component without keeping a reference to it. But I don't recommend it simply because it adds the overhead of searching through a component array for the one your looking for. I could useful for getting all Menus and such but if you have some interesting derived component that extends JMenu somewhere as well as extends JButton and it really doesn't belong in the list of menus.

So I would definitely keep a reference instead of searching through an array of components.
As long as we're talking about instanceof, I have a question that probably doesn't warrant a new thread. I'm writing an equals() method for a class BigInteger that I'm working on. Is it better to cast, like this:

public boolean equals(Object o) {    if(bigInteger.equals(((BigInteger)o).toString()))        return true;    return false;}


Or is it better to use instanceof:

public boolean equals(Object o) {    if(bigInteger.equals(o.toString()) && o instanceof BigInteger)        return true;    return false;}


The top example would give a runtime error if the client tried to compare a BigInteger and some unrelated object, but the bottom one would return false. For some reason I want to go with the top one, but the bottom one seems more robust.
I'd imagine both methods would have similar performance as they are both just object hierarchy look-ups. I would be more inclined to use the method that wouldn't throw a ClassCastException at runtime if garbage parameters are passed.
Quote:Original post by Kevinator
As long as we're talking about instanceof, I have a question that probably doesn't warrant a new thread. I'm writing an equals() method for a class BigInteger that I'm working on. Is it better to cast, like this:

*** Source Snippet Removed ***

Or is it better to use instanceof:

*** Source Snippet Removed ***

The top example would give a runtime error if the client tried to compare a BigInteger and some unrelated object, but the bottom one would return false. For some reason I want to go with the top one, but the bottom one seems more robust.


This isn't an issue of efficiency, its an issue of semantics. In the case of your later definition, you are defining equality that can compare a BigInt to anything. By definition, a BigInt is not equal to anything that isn't a BigInt. If, however, you want to define equality as being undefined when comparing two unlike types, then an exception is more appropriate. Some types may have multiple equality methods, depending on the semantics of equality that is needed. Of course, you can only override Object.Equals once. So, in that case, I would use the more general definition, since Object.Equals is meant to be a general-purpose method.

This topic is closed to new replies.

Advertisement