2

I've been trying to understand scoping in Java, more precisely, when it comes to having inner classes.

I have the following snipped of code:

import javax.swing.*;

public class OuterClass {

    // Constructor
    public OuterClass() {
    }

    public static void main(String[] args) {
        OuterClass app = new OuterClass();
        app.doStuff();
    }

    private void doStuff(){
        System.out.print("\033[H\033[2J"); // DEBUG clear out output

        InnerClass newNote = new InnerClass("images/01-SOL.png");

        // QUESTION: why are the following working and accessible??
        ImageIcon myIcon = newNote.getIcon();
        System.out.println(myIcon.getImage());
        System.out.println(newNote.iconPath);
    }

    // define private inner class
    private class InnerClass {
        private String iconPath;

        private InnerClass(String iconPath){
            this.iconPath = iconPath;
        }
        private ImageIcon getIcon(){
            return new ImageIcon(this.iconPath);
        }
    }
}

I have an Outer class, and within it, an Inner class. As per my question in code, I do not understand WHY the private members of InnerClass (whether properties, or functions) are accessible from OUTSIDE the inner class, meaning in my example, in my outer class.

I'm writing another small swing app, almost done, but am just lost in what scoping I should be using in my Inner classes...

I was expecting to have to

  1. set the inner class itself to private (thus only accessible to the outer class).
  2. set the inner class members to private (thus only the inner class itself could access them)
  3. set the inner class getter/setter functions to public, so that the outer class could access them ...

Doesn't seem to work at all this. I'm puzzled...

Could anyone shed a light on this from my example?

Much much thanks!

==========

UPDATE:

And so we're clear why an inner class... My project is a swing app that shows random music notes. Each note "Note" has a few properties (index, image file, icon, finally, it has an ArrayList of object of type from another inner class "PositionCombi").

The NotePosition class has a positionNum, fingerNum, and stringNum..

Here's the bulk of it:

public class OuterClass {

   private String[] allNoteNames = ["C","D","E","F","G","A","B"];
   private Note noteImages[];

   public OuterClass {
      initNotes();
      doStuff();
   }

   private void initNotes(){
      this.noteImages = new Note[19];

      noteImages[0] = new Note(4, "images/01-SOL.png");
      noteImages[0].addPositionCombi(1, 0, 4);
      noteImages[0].addPositionCombi(2, 3, 4);
      noteImages[0].addPositionCombi(3, 2, 4);

      //...etc.
   }

   private Note getShuffledNote(){
      //... return a random note object from this.noteImages
   }

   private void doStuff() {
      // get a suffled note:
      Note workingNote = getShuffledNote();

      lblNoteName.setText( this.allNoteNames[ workingNote.getIndex ] );
      lblImage.setIcon( workingNote.getIcon() );
      ArrayList<Note.PositionCombi> notePositions =  workingNote.getPositions()

      //print positions for given note:
      for (Note.PositionCombi notePosCombi : notePosCombinations) {
         System.out.println( "Position: " + notePosCombi.getPositionNum() );
         System.out.println( "Finger: " + notePosCombi.getFingerNum() );
         System.out.println( "String: " + notePosCombi.getStringNum() );
      }
   }


   /*** INNER CLASS DEFS ***********/
   private class Note {  // inner Note class
      private int noteIndex;
      private String iconPath;
      private ArrayList<PositionCombi> PositionCombis;

      private Note(int noteIndex, String iconPath){
         this.noteIndex = noteIndex;
         this.iconPath = iconPath;
         this.PositionCombis = new ArrayList<PositionCombi>();
      }

      private int getNoteIndex(){
         return this.noteIndex;
      }
      private ImageIcon getIcon(){
         return new ImageIcon(this.iconPath);
      }

      private ArrayList<PositionCombi> getPositionCombis(){
         return this.PositionCombis;
      }

      private void addPositionCombi(int positionNum, int fingerNum, int stringNum){
         this.PositionCombis.add(new PositionCombi(positionNum, fingerNum, stringNum));
      }

      private class PositionCombi { // inner-INNER PositionCombination class
         private int positionNum;
         private int fingerNum;
         private int stringNum;

         private PositionCombi(int positionNum, int fingerNum, int stringNum){
            this.positionNum = positionNum;
            this.fingerNum = fingerNum;
            this.stringNum = stringNum;
         }
         private int getPositionNum(){
            return this.positionNum;
         }
         private int getFingerNum(){
            return this.fingerNum;
         }
         private int getStringNum(){
            return this.stringNum;
         }
      }
   }

}
Pat
  • 449
  • 1
  • 4
  • 14
  • 1
    does this answer your question? https://stackoverflow.com/questions/1801718/why-can-outer-java-classes-access-inner-class-private-members – Miss Skooter Feb 08 '23 at 10:00
  • 1
    This possibly helps: https://stackoverflow.com/a/33171163/426463 – trappski Feb 08 '23 at 10:00
  • The InnerClass you declared is effectively an inner class (without static qualifier) ; check this: https://stackoverflow.com/questions/1353309/java-static-vs-inner-class – Martín Zaragoza Feb 08 '23 at 10:01
  • "..but am just lost in what scoping I should be using in my Inner classes" <- I don't know anything about your code or project at all, but I would recommend rethinking whether inner classes are needed at all. Maybe it's just the field I'm working in but I can count the number of times on one hand when I really needed to use inner classes that are neither anonymous nor static. Like in the example above you have given I don't see a really good reason why InnerClass should be an actual inner class. – OH GOD SPIDERS Feb 08 '23 at 10:01
  • I also don't particularly understand what the purpose of your expected functionality is. Realistically, limiting variable and method scope is to prevent outside access to things that you don't want to be messed with. I can't imagine a use case where that would be necessary for an inner class. So the scope being "public" within the outer class makes sense in my head. – Miss Skooter Feb 08 '23 at 10:05
  • @OHGODSPIDERS my initial post only included a snipped for demonstration, of course in only that, it didn't make sense to use an Inner class! My question was regarding scoping behavior. Not "should I be using an inner class" .... Anyhow, I've updated the post to include a more detailed use case. – Pat Feb 09 '23 at 08:09
  • 1
    @MissSkooter From the other's shared link and some other readings, I understand now that any members / functions within an inner class will be accessible from anywhere within _the body part_ of the outer class... https://stackoverflow.com/questions/1801718/why-can-outer-java-classes-access-inner-class-private-members https://stackoverflow.com/questions/19747812/why-can-the-private-member-of-an-nested-class-be-accessed-by-the-methods-of-the?lq=1 Thx all for your comments. – Pat Feb 09 '23 at 08:17

1 Answers1

-1

You must understand that the InnerClass and object properties are the same for the OuterClass

Maxwell
  • 1
  • 1