-1

It might be a basic question , but please help me. I'm writing code for a tic-tac-toe. I wanted to use a hashmap to document the state of each box.

public class tictactoe extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tictactoe);
    }
    boolean player = true;
    
    Map<Integer , Integer> hashMaps = new HashMap<>();

    {hashMaps.put(233, 333);}


    public void thismeth(View view) {
        ImageView ig = (ImageView) view;
        ig.getId();

        if(player){ig.setImageResource(R.drawable.cross);
        player = false;
        ig.setEnabled(false);}
        else{
            ig.setImageResource(R.drawable.zero1);
            player = true;

            ig.setEnabled(false);
        }

    }
}

The above code snippet does not throw any errors in the hashmap

public class tictactoe extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tictactoe);
    }
    boolean player = true;

    Map<Integer , Integer> hashMaps = new HashMap<>();

    hashMaps.put(233, 333);


    public void thismeth(View view) {
        ImageView ig = (ImageView) view;
        ig.getId();

        if(player){ig.setImageResource(R.drawable.cross);
        player = false;
        ig.setEnabled(false);}
        else{
            ig.setImageResource(R.drawable.zero1);
            player = true;

            ig.setEnabled(false);
        }

    }
} 

While this code shows put() as an invalid method. Without curly brackets it does not work, but with the curly brackets it does. Can someone please explain why it works with the curl brackets?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
shivam
  • 38
  • 5
  • the hashmap has random integer values – shivam Mar 20 '21 at 12:03
  • 1
    Does this answer your question? [system.out.println statement outside any method in java](https://stackoverflow.com/questions/18795467/system-out-println-statement-outside-any-method-in-java) – Savior Mar 21 '21 at 05:41

2 Answers2

0

You can only declare or initialize an object within a class as in the first example. If you need to use it, then it should either be inside a method or an initialization block.

The curly braces indicate an initialization block. This would be run each time an object of the class is instantiated.

{
    // initialize...
}

Initialization blocks could also be static. This would be run only once for a class.

static {
    // ....
}
Gautham M
  • 4,816
  • 3
  • 15
  • 37
0

The explanation is fairly straightforward: Because the Java Language Specification says so.

Specifically, code cannot appear inside classes. Code can only appear inside something else, such as methods, constructors, initializers, or field-initializing expressions, and those can be in classes.

Thus:

class Example {
   System.out.println("Hello");
}

does not compile (the idea being: When do you want that code to run? It is not clear, hence, that code does not make sense, and nonsensical code should optimally not compile at all).

In contrast, this:

class Example {
    private static final boolean whatever = sayHello();

    public static boolean sayHello() {
        System.out.println("Hello");
        return false;
    }
}

Compiles fine, even though we have 2 instances of 'code' here: The sayHello method contains code that says hello, and the expression that follows the = sign for the whatever field contains the code sayHello().

Think about that for a moment: Fields can be declared with an immediately value. These are all legal field declarations:

long x;
long y = 10;
long z = System.currentTimeMillis();

and yet that last one definitely requires code to actually be executed (the compiler can't "pre-run" it for you, the current time is not a constant of course). You can use a construct called an 'initializer' for more flexibility on this: There is such a thing as 'code that runs when the class is loaded' as well as such a thing as 'code that runs when a new instance is created'. That last one is a bit murky; you'd think: The constructor, that runs when an instance is created - which is true, but something like: class Example { long z = System.currentTimeMillis(); } has no (visible) constructor and yet code needs to run when you write new Example(). Thus, yes, there is instance initializing code as well.

The language syntax to write an initializer (which lets you run arbitrary code during class or instance initialization, the same place the compiler puts the code it needs to run when you use code to initialize fields), is:

static initializers (run when the class is used for the first time anywhere in your application):

static { codeHere(); }

instance initializers:

{ codeHere(); }

Yes, just braces. That is an element you can stick in a class and that means: This is an instance initializer- to be run when new instances are made.

And that's what you've created when you stick your map.put statement in {}. Specifically, these are the direct contents of your class tictactoe construct:

  • protected void onCreate(Bundle savedInstanceState) - a method. Those are acceptable.

  • boolean player = true; - a new field; acceptable. initialized with a constant value which is hardcoded directly in the produced class/apk file.

  • Map<Integer , Integer> hashMaps = new HashMap<>(); - a new field; acceptable, initialized with code, which will be translated to an instance initializer.

  • {hashMaps.put(233, 333);} - an instance initializer. It'll be added to the instance initializer, together with hashMaps = new HashMap<>();.

  • public void thismeth(View view) { - a new method.

All acceptable things. Whereas just hashMap.put(233, 333);, which is an expressionstatement, doesn't work - statements cannot go inside classes, only inside methods, constructors, instance initializers, and static initializers.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72