Ok, so I've been stuck for a little while now on this problem. I'm trying to pass an array of Tabs and I'm just not doing it correctly. I believe I'm missing something simple, because I need to learn more about what is happening with my code rather than just going through the motions.

Here's my code.

public class CountProg extends Canvas {
    private Tab[] incTabs;

    public CountProg()
    {
        super();
        //some code
       tabSet.addTab((Tab) getTabs()[0]);
    }


     public Tab[] getTabs()
    {
        return incTabs;
    }
    
    public void setTabs(Tab[] incTabs)
    {
            this.incTabs=incTabs;
        
    }
}
public class stCountTest extends CountProg {

    private StaffMain _sm;


    public stCountTest(StaffMain sm,String permission)
    {
        super();
        _sm=sm;
        
    
        setTabs(createTabs());
        init();
    }


     public Tab[] createTabs()
    { 
        Tab[] temp = new Tab[]{
        new Tab("One"),
        new Tab("Two"),
        new Tab("Three")
        };
        return temp;

    }

}

I know the problem is with my set and get methods but I just cant figure out precisely what it is.

If I create and array of tabs in the getTabs() method and return it, everything works fine.

I appreciate any help, thank you.

Dani AI

Generated

A concise explanation of what happened and why 's change fixed it: the base-class constructor executed before the subclass had a chance to call setTabs, so the code in the constructor depended on a field that was still null. Returning a newly created array from getTabs() hid the timing problem because it avoided the uninitialized field. Moving the tab-setup out of the constructor and doing it after setTabs() is a straightforward, correct fix.

Java guarantees that superclass constructors and initializers run before the subclass constructor body. The language specification describes instance creation and initialization order; this is why methods or state that the subclass establishes are not yet available when the base constructor runs (JLS 12.5 — Creation of New Class Instances). Calling methods that rely on subclass state (or overridable methods) from a constructor is therefore fragile.

Safer alternatives:

  • Constructor injection: make the base class accept the Tab[] in its constructor so the base has what it needs as soon as it starts.
  • Post-construction init: provide a public init() or setupTabs() that is called after the object is fully constructed (this is what chose).
  • Factory/builder: construct the Tab[] externally and hand it into the constructor, avoiding subclass ordering issues.

Example pattern (constructor injection):

public class BasePanel {
    private final Tab[] tabs;

    public BasePanel(Tab[] tabs) {
        this.tabs = tabs;
        initTabs();
    }

    private void initTabs() {
        for (Tab t : tabs) tabSet.addTab(t);
    }
}

Troubleshooting tips: add simple logging in each constructor and in setTabs() to confirm call order; avoid calling non-final, overridable methods from constructors; prefer immutable state passed into constructors when possible. The post-construction init used in the thread is a practical and common approach.

Well, i figured out my problem. It was pretty simple, I was calling the super class which setup my tabs in the constructor. Then I gave the tabs the information they needed to be set up. Kind of like putting the cart ahead of the horse.

I think my presentation of the problem was unclear. But anyway, i just took the tab setup code out of the constructor and made it it's own method, then when i setTabs() I also call the new method with the tab setup code. Well thanks all, and sorry about the ambiguity!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.