2

If I have this code.

public class Test{
        {
            class People {

            }
        }

        public static void main(String[] args) {
            People person = new People();//Compile ERROR
        }

    }

I can't create instance of People.

Does that mean Initializer Block can't be used for defining classes?

2
  • If you post the exact error you're getting, it would be better for everyone. Commented Mar 14, 2014 at 19:13
  • What you are doing is creating local class which normally can be used only in scope you are declaring it. To use it outside this scope you would probably have to use reflection. Commented Mar 14, 2014 at 19:18

5 Answers 5

6

(Adding a second answer as my wrong one had three upvotes already.)

You can declare a class within an initializer block - but its scope is that initializer block, just like if you declared it in a method. So this works:

public class Test {
    {
        class People {            
        }

        People people = new People();
        System.out.println("In initializer block!");
    }

    public static void main(String[] args) {
        new Test();
    }
}

I can't say I've ever done this before though, nor can I imagine myself wanting to do it any time soon. Note that this is a local class, which is always implicitly an inner class. (Although if you declare a local class in a static method, there's no enclosing instance, just to make the terminology slightly weird...)

If you want to create a class which code outside the initializer block can "see", you need to declare it outside the initializer block. (Just like any other declaration - if you declared a variable within the initializer block, you wouldn't expect to be able to see it outside would you?)

Sign up to request clarification or add additional context in comments.

2 Comments

On a side note, that class declaration cannot be static, as you suggested earlier and other answers suggest.
@m0skit0: Indeed, as it's a local class. (Hence the deletion of my answer, of course - I made the same mistake everyone else did, but I didn't want my second attempt to start off with a +3 vote advantage :)
2

You need to make the inner class static:

static class People {

4 Comments

There is another problem here that I do not think this answer addresses: There are an extra set of {} surrounding the inner class declaration. Simply making it static does not make it compile.
That was my first answer too, but it's not what the question's really about.
That won't work either: "Illegal modifier for the local class People; only abstract or final is permitted"
@JonSkeet I was gonna leave my comment on your question, but you were too quick to delete it!
1

The initializer block (defined by the extra brackets) changes the scope of the declared class, so it will not be visible outside, much like a variable would not be. So, the only place where a People object can be created, is within the block itself, e.g.

{
   class People {
   }

   People person = new People();
}

Without the initializer block, there are 2 options you can follow:

  1. Declare the People class as static
  2. Create a Test object and then instantiate a People object

In the first case, the only thing that changes is the line

static class People

For the second case, the main method would look something like

public static void main(String[] args) {
    People person = new Test().new People();
}

1 Comment

The extra brackets are meant to be there - read the final sentence of the question.
1

You can do

Test t = new Test();
People person = t. new People();

Because People otherwise has no enclosing instance

EDIT:

Since the class definition is in an initialization block, it is only visible and useable locally, INSIDE the initialization block (which makes it a peculiar place to define a class). The People class can't be visible in main since there is no visible type for People. The approach I outlined above would only work if there were no initialization block around the class definition.

6 Comments

No, we cant do this in main method. People is local class which belongs to initializing block scope only.
Yes you can. I just (re)tested it by adding a method to the People class and invoking it from the person object in main
In other words, person object is accessible from main, and since OP is creating the object in main, I'm assuming he wants to use it there.
If Person class is declared inside initialization block (like in OP example) then there is no Test.Person type. That is why OP is asking "Does that mean Initializer Block can't be used for defining classes?". What you are saying in your answer it is perfectly fine, just use instance of outer class, while it is not. That is why Jon Skeet removed his first answer which was similar to yours.
Ah, I see it now. I missed those extra brackets making this class local ONLY to the initializer block. Thanks
|
0

Yes we can declare initializer block and scope of the class People will be within it.Update the code as below :

  public class Test {
    {
        class People {  
             /// Stuff          
        }

        People people = new People(); // Create object of People
        System.out.println("Initializer block");
    }

    public static void main(String[] args) {
        Test obj = new Test();
    }
}

1 Comment

The brackets are deliberate - the OP is trying to use an initializer block, as per the final sentence of the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.