Java pointers
October 13, 2005 2:45 PM   Subscribe

Very specific JAVA question. Java.sun.com and various google searches have been of no use.

I've written two classes, which for simplicity sake I'll call class A and class B. I have an instance of class A, which I'll call a. Within a are a couple of instances of class B, which I'll call b and bb. b and bb need to be able to access variables and methods in a. Not A, a, so making everything static is not really an option. In C++ I would use a pointer, but this isn't C++ and Java is annoying like that. Any suggestions on how I can make this work?
posted by martinX's bellbottoms to Computers & Internet (18 answers total)
 
have you considered making B an inner class of A?

if you post the C++ code here it would make it easier to give a solution.
posted by andrew cooke at 2:53 PM on October 13, 2005


First, this sounds broken. Two classes mutually needing to use each other is just .. weird (not even sure Java syntactically would allow the mutual imports...)

Having said that, you could probably use reflection to dynamically access the other object (and just store a vanilla Object type reference of 'a' on b).

Not that I recommend that.

Rachael
posted by R343L at 2:55 PM on October 13, 2005


Oooh. Should have previewed. I forgot about inner classes. Thinking a bit more in the usage of other mainstream languages. That would probably work pretty well (and doesn't seem like as much of a hack!)

Rachael
posted by R343L at 2:57 PM on October 13, 2005


I'm having difficulty parsing what you want to do; perhaps you're referring to polymorphism.
posted by Rothko at 2:58 PM on October 13, 2005


I don't get why you think you can't use a pointer. Just pass the object (or this if you're in the object already).
posted by smackfu at 3:01 PM on October 13, 2005


Yeah, you have a design issue here, called a cyclic dependency. Usually avoidable, but not always.

In Java, you can pass your object into the b objects easily. Make them so their constructors take an "A" parameter, and pass in "this" (inside 'a', which is a reference to 'a' itself) when you create them.
posted by knave at 3:05 PM on October 13, 2005


He's using the B instances as closures.

Couple of possibilites: do as Andrew Cooke suggests and make B an inner class of A.

Or make B an interface and the instances anonymous classes that implement the interface.

Or, if B only needs access to A's public interface, do what smackfu suggests: make the B ctor take an A instance, and operate on its A instance through that reference.

For more on closures in java, see here and here.
posted by orthogonality at 3:25 PM on October 13, 2005


Response by poster: smackfu and knave: to my understanding java doesn't work that way. If I pass a as a reference to B's constructor, I'll end up with a copy of a, not a. Any changes I make will be to the copy, not the original a. The C++ code to declare b would look something like B b=new B(&a); because the ampersand passes the address of a rather than creating a new instance of A that at the time is the same as a. Now I'm probably mixing C++ and Java, but anyone who knows both will get the point.

I'll try making B an inner class in A, and see if that works out the way I want it to. B is eventually going to become a thread, and A extends JPanel, from the java.awt library, and the method I most need to access is the paint method, if that makes any difference.
posted by martinX's bellbottoms at 3:43 PM on October 13, 2005


Doing something like

public class A {
private B b = new B(this);
private B bb = new B(this);
}

passes a reference along to b and bb. No extra copies made.
posted by fnerg at 3:52 PM on October 13, 2005


First, passing objects around in Java is always by reference. You won't make a copy unless you explicitly do so (primatives are another matter). This is similar to C++ if you had "class B { private A a; B( A& _a ) : a( _a ) {} };".

But you really want an inner class here. If I do:
public class A {    private class B extends Thread {        public void run() {            bar();        }    }    B b;    public void foo() {        b = new B();        b.start()    }    public void bar() {        // do something    }}
That will work how you'd expect it to.
posted by sbutler at 3:56 PM on October 13, 2005


Java is all pointers. They aren't called pointers, but unless you make an explicit copy yourself or are talking about primitives (int, long ...) or String you're deailing with pointers.

If you pass A in B's constructor it will be "the" A, not a copy of A. Best would be to have A implement an interface of the methods it chooses to vend to B and use that as the type of the object in the constructor to B.

Example
public class A implements UsefulInterface {
public A() {
    B b = new B((UsefulInterface)this); // The cast is for clarity
    B bb = new B((UsefulInterface)this);
 }
}
The constructor for B looks like
public B(UsefulInterface useful) {
}
One caveat - if you create the B's in A's constructor you shouldn't call any methods on A in the constructor for B or in another thread until the constructor for A has exited, since A is not fully constructed yet.
posted by true at 3:58 PM on October 13, 2005


Also, there's a Java Tutorial page dealing with the particulars of my example. They call it an inner class, but in a slightly different sense than orthogonality's links.
posted by sbutler at 4:09 PM on October 13, 2005


It's already been stated, but java passes references to objects, not objects. So there is no implicit copying going on. The only time this isn't true is for native types, like int and boolean. Those are copied by value.
posted by knave at 4:20 PM on October 13, 2005


Response by poster: public class A {
private B b = new B(this);
private B bb = new B(this);
}

I tried that, and it didn't work for the graphics stuff I was using. (it didn't let me use b to tell a to repaint().)
I messed around a little bit making B an inner class of A but it didn't work out so well either because there are other classes that extend B and those classes started having problems.

true: i haven't tried your suggestion yet, but will it work with the paint method in A? which as I've said, is what I really need.

As you can probably tell, I'm relatively new to java, and I seem to have taken on a project that's a bit out of my reach, so even if I can't apply this advice now, I'll probably remember it for later.
posted by martinX's bellbottoms at 5:13 PM on October 13, 2005


Response by poster: public class A {
private B b = new B(this);
private B bb = new B(this);
}

on second thought... I wrote a simpler program and tried that again, and it seems to work. That's strange, because I swear I tried that and versions of that in my program and test programs several times before I even posted this question and it never worked, or even compiled, which was what led me to my apparently misguided view of references in Java.
I'll try it again in the other program.
posted by martinX's bellbottoms at 5:38 PM on October 13, 2005


Aah, graphics.
I'm assuming you're using swing? You need to call the repaint method in the GUI thread. Look at SwingUtilities.invokeLater and SwingUtilities.invokeAndWait ...

Also, remember that the GUI subsystem is free to post your repaint request on a very low priority thread....
posted by Arthur Dent at 9:53 PM on October 13, 2005


Ahhh, AWT and Swing, some of the funnest Java bugs to be found are in those inferna.. uhm.. USEFUL packages. And fwiw, Java is never typed in all caps, it's not an acronym :) (unlike the hojillion Java acronyms out there JNDI, JSP, J2EE, JMS, CMP, etc etc etc).
posted by eurasian at 7:11 AM on October 14, 2005


you might also look at anonymous inner classes. many uses of closures (if that is what you're doing) tend to be handled by inline anonymous classes in java (typically implementing an interface of extensing an abtsract base class). i believe (although i don't do much client gui work) this is particularly true of swing, where you're often providing callbacks and the like (example - search for "anonymous" in that page). you say that B is use elsewhere, but maybe you can rewrite B as an abstract class that is extended locally with the information you want to place in the closure.
posted by andrew cooke at 8:22 AM on October 14, 2005


« Older How to video stream my radio show?   |   Help me do my new jobs and save our company. Newer »
This thread is closed to new comments.