0

I am studying for my certification exam, and I run into this example that compiles and runs, but the problem is that I do not think that it should compile, since the method is private and we are trying to invoke a private method from an instance of the class. Can someone please explain to me why it works?

Here is the code:

public class Test {
    public static void main(String[] args) {
        Test instance = new Test();
        System.out.println(instance.number());
    }

    /* protected */ private int number() {
        try {
            new RuntimeException();
        } finally {
            return 1;
        }
    }
}
Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93
jrobertsz66
  • 953
  • 1
  • 12
  • 29
  • 2
    That method isn't `private`. It says right there that it's `protected`. – awksp May 19 '14 at 17:15
  • 3
    First: the message is *protected* and not private. Second: even if it _was_ private you can still access it from within any method of the defining class. private means "class private" not "instance private" –  May 19 '14 at 17:15
  • In any case, you're working in the class that the method is defined in, so there's absolutely no reason that you couldn't access that method. – awksp May 19 '14 at 17:16
  • Duh...I guess I need coffee today...I had changed the example to use protected instead of private, and I just realized that it works in the main method because we are still inside the Test class....:) Thank you so much for such quick responses...I feel somewhat obtuse after asking this question...:) – jrobertsz66 May 19 '14 at 17:17
  • 1
    The interesting question is why it prints 1 ;) Good look for your exam. – Thomas Uhrig May 19 '14 at 17:18
  • Thanks Thomas, and thank you a_horse...and user35... for taking the time to respond. Cheers. – jrobertsz66 May 19 '14 at 17:19
  • I have edited making the method private, so that the code matches the question now. – Audrius Meškauskas May 19 '14 at 17:36

3 Answers3

3

I will try, remember that a finally block is guaranteed to run (unless you call System.exit).

public class Test { 
  public static void main( String[] args) { 
    Test instance = new Test();  // <-- instantiate a Test instance.
    System.out.println( instance.number());  // call get number method. gets 1
  } 
  protected int number() { 
    try { 
      /* throw */ new RuntimeException(); // instantiates an unchecked exception.
      // even if you threw it, it wouldn't matter....
      // even if you did return 0;
    } finally { 
      return 1; // swallows the unchecked exception and returns 1.
    } 
  } 

}

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • `new RuntimeException();` actually doesn't throw a runtime exception, it only instantiates a new one. – niiru May 19 '14 at 17:31
  • @niiru Good catch, but it doesn't matter... it would still return 1. – Elliott Frisch May 19 '14 at 17:34
  • Agreed 100%! I've seen some hard-to-trace bugs arise when people accidentally initialize exceptions when they meant to throw them, though... – niiru May 19 '14 at 17:51
3

The private methods and fields are accessible anywhere from the declaring class, even if called not from inside the instance method:

   class Test {
      private void doThis() {};

      public static void main() {  
         Test a = new Test();
         Test b = new Test();

         a.doThis(); // No problem
         b.doThis(); // No problem
      }
   }

P.S. The method in your code was initially protected, not private (protected methods are accessible anywhere in the same package and also outside the package in derived classes). I have edited to make it private now. Also such code compiles and runs.

Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93
2

As the protected class is in the same package/class or subclass then the instance that is calling it, there is no problem.

In fact protected is less restrictive then private.

In Java, difference between default, public, protected, and private

Community
  • 1
  • 1