Sign in to follow this  

[java] how to know the class of an object

This topic is 4481 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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...

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
When overriding the equals functions you should follow the definition from the java api docs Object.equals( Object o ) And make sure you are consistant with its definition. I would definitely advise against the top way of checking for class equivalence. Or you could catch the ClassCastException like so.


public boolean equals( Object o ) {
boolean toRet = true;
try {

if( !bigInteger.equals( ((BigInteger)o).toString() ) )
toRet = false;

}catch(ClassCastException cce) {
toRet=false;
}
return toRet;
}




However, you are doing things in a very confusing and incohesive manner.

I would have done it like this

public boolean equals( Object o ) {
return bigInteger.equals(o);
}


There is no need to compare using the toString() method. Why would you do something like that. BigInteger.equals() already compares itself to the object checks if its a BigInteger class and if the values are equal.

Share this post


Link to post
Share on other sites
Oh! so why don't you turn the bigInteger into a BigInteger class instead of comparing the strings.


public boolean equals( Object o ) {
return (new BigInteger(bigInteger)).equals(o);
}



or just store the bigInteger as a BigInteger which should be what you do anyways since your variable name happens to be 'bigInteger'.

Is there as reason for storing it as a string since you can just use the toString() of BigInteger to get the string representation if you need it.

Share this post


Link to post
Share on other sites
Yeah...

How do you think a very long list of digits would be stored? I can think of a few ways: a very big array, a linked list, or a string. I chose the latter to be the underlying data structure for a very big integer.

Share this post


Link to post
Share on other sites
Actually I would choose to store them not as a String since each char of a string is 8 bits in ASCII format or more for extended character formats. I would choose to store the number using bytes. And it appears the BigInteger class does exactly that also giving you the option to manipulate the individual bits which allows you to use the BigInteger class like a bit array.

Share this post


Link to post
Share on other sites

This topic is 4481 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this