Can someone explain to me why I'm having this error? - java

Good day,
I have a question on which in my code, one declaration is having an error outside a function.
The snippet is:
public class Gold {
Block[][] block = new Block[4][4];
this.block[1][4] = new Block(); //1
public void populate() {
this.block[1][4] = new Block();//2
}
}
The code this.block[1][4] = new Block(); number 2 is not having an error. However, the first code which is not inside the function is showing the error:
Illegal start type
Cannot find symbol
']' expected
invalid method declaration, return type required.
I just want to understand why this is hapenning and what I am missing.
Thanks

There is no element with index 4. The last element has index 3.

You can not initialize variables directly as you did above in case 1, You can initialize block[][] in constructor like :
public Gold(){
this.block[1][3] = new Block();
}
OR in block like :
Block[][] block = new Block[4][4];
{
this.block[1][3] = new Block();
}

You have a statement which must be in a block of code.
Try
public class Gold {
Block[][] block = new Block[4][4];
{ // initializer block
this.block[1][3] = new Block(); //1
}

You have two problems here, You need to initialize any object in a scope. Either you have to call the Number 1 line in a constructor or in a function or with in a block (enclosed with in{and}). Here you need to know difference between static block and non-static blocks.
Other problem you have is this.block[1][4] = new Block(); will throw an ArrayIndexOutofBounds exception as the length of the array is 4 and you are trying to insert and object at 5th place.

I think that you should place your code in constructor:
public Gold(){
this.block[1][4] = new Block();
}
In java class you can define variables or methods (including constructors) but can not use plain code in it.

this.block[1][4] = new Block(); //1
is an expression not a field initialization. It cannot be outside of a method body.

You need to wrap your code in a method, not in the class body. If its part of the initialization of the Gold class put it inside its constructor like:
public class Gold {
Block[][] block = new Block[4][4];
public Gold() {
this.block[1][4] = new Block();
}
}
The class body allows only variable declaration and instantiations, but not standard operations like changing an object's (your array) value.
EDIT: as other pointed out, the index 4 does not exist in an array of size 4, only indices from 0 to 3 can be accessed.

The code this.block[1][4] = new Block() is compiled but will fail on runtime: your array has 4 elements while index in java and all C-like languages starts from 0, so the max value of 4-elements long array is 3.
And you cannot write code outside methods in java, so if you try this you get compilation error.

This sentence
this.block[1][4] = new Block(); //1
cannot go outside a method or Initialisation block. If you want to initialize the array you have to do it on the declaration or inside a method (constructor could be a good place) or you have to use a Initialisation block.
Also check the array bounds. In Java arrays have 0 based indexes.

Related

Object creation, variable initialization

Im reading through someone else´s code and theres this piece of code:
class Wrapper {
UnaryOperator<String> f;
}
Wrapper w = new Wrapper() { // line 3
{
f = s -> s.length() <= 1 ? s : f.apply(s.substring(1)) + s.substring(0, 1);
}
};
So if i understood it correctly, he creates a new Wrapper objecet and already initializes its variable f. I´m unfamiliar with the syntax from line 4 on, i only knew something like that from anonymous classes, but this isn´t one. Can you just initializes variables in between {} after you create a new Class()? Can you also do more than that, like override or define new methods? And why do you have to put {} in between each initialization?
It is an Instance Initialization Block. Read more in this question

Why can't I instantiate outside any method in java?

Please ignore my arrogance......learning java these days, i came across this perfectly same question for my problem : Why can't I instantiate and create Object without main method? (Stack Overflow Error)
Expecting a possible downvote too...but please go through my question once!!!!
Code that i was trying :
public class Arrayprg{
Arrayprg ag = new Arrayprg(); //ignore this for a while and go thru code please
public static void main(String []args){
System.out.println("Hello Array");
new Arrayprg().declarearray();
}
public void declarearray()
{
int[] arr;
arr = new int[11];
new Arrayprg().assignarr(arr);
}
public void assignarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
arr[i] = i;
}
new Arrayprg().printarr(arr);
}
public void printarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
System.out.println(arr[i]);
}
}
}
Thinking logically, going through the code you'll see lots of new arrayprg()....what i thought of was to instantiate outside of methods and calling all methods through it there after, but i guess it is not allowed in java.
Whats causing my Problem
Going by the solution in quoted question, as it explain that below thing happens :
Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
Explanation given in that question
.....it is initialized whenever an instance of the class is instantiated. This will never terminate until you run out of memory and get the stack overflow. Run it with a debugger for a clearer view.
My Question
so i have Arrayprg ag = new Arrayprg(); in my program which is creating a loop every-time i create an instance but why is this called when i am calling the functions through new Arrayprg().
What i mean is that when i am calling the function through new Arrayprg() inside the methods why is Arrayprg ag = new Arrayprg(); getting called and creating the loop of error for Stackoverflow?????
This will cause a StackOverflowError.
The line you tell us to ignore, interestingly, is the culprit. When you instantiate a new Arrayprg then any object initializers are called, including new Arrayprg() which will then recursively try to keep invoking constructors without end. Remove that line, or put it in a static initializer. Better yet, just don't create that Arrayprg outside the main method as your Arrayprg does not need an instance of Arrayprg itself,
I would be more clear but I don't know what you're trying to achieve.
Solution : Change this line:
Arrayprg = new Arrayprg(); //ignore this for a while and go thru code please
to:
static Arrayprg a = new Arrayprg();
And you will no longer get your infinite recursion problem as now it will only create one instance of it shared between all instances - rather than each instance immediately creating a new one.
The Explanation
As part of constructing an Object in Java all member variable initializers, initializer code blocks, etc are all called as well as the constructor itself.
So in order to create a new Arrayprg one of the things it does is look for member variables that need initializing and initialize them.
In this case it finds Arrayprg a = new Arrayprg();, so in order to initalise the field a, it tries to create a new Arrayprg().
But that new Arrayprg() goes through the exact same process again, and again, and again, etc.
There are a number of ways to fix this - including:
Pass in the Arrayprg as a parameter to the constructor - so a new one doesn't need to be created.
Make the Arrayprg static - so only a single one needs to be created once rather than creating a new one each time
Lazy initaliziation on the Arrayprg so that you only create it the first time you try and access it rather than when the parent Arrayprg is created.
Why it doesn't happen in a method call:
The important thing that causes the recursion here is that the call happen during the creation of a new object. If trying to create a new object involves creating another copy of the same object then you will end up with infinite recursion which will then cause the failure.
So you can create a new object anywhere you like - so long as it is not inside the creation of itself.
class A {
A a = new A(); // Recursion
}
class A {
A() {
A a = new A(); // Recursion
}
}
class A {
A getNewA() {
return new A();
// This is fine as it doesn't happen during creation of an A
}
}
class A {
A() {
getNewA();
// Recursion as calling getNewA creates a new A, which calls getNewA, which....
}
A getNewA() {
return new A();
// This is fine on its own but is broken if called from the constructor
}
}
class B {
A a = new A();
// This is fine as B is not A, so you can create a new A within B.
}
Let's step through this visually.
Arrayprg = new Arrayprg();
So what do you need to create an object of type Arrayprg? Well you need to create it's fields.
Arrayprg = new Arrayprg();
And once again, you're telling the JVM to give you another Arrayprg object. By definition, this means making another Arrayprg object.
This is giving you a StackOverflowException.
Solution?
You shouldn't really be nesting types like this. It's pointless. You're inside the class already, so use it's methods.
public void declarearray()
{
int[] arr;
arr = new int[11];
assignarr(arr);
}
Follow this pattern, and you'll eliminate the need for the Arrayprg field.
Every time you create an instance of Arrayprg, you call this line: Arrayprg = new Arrayprg();, this means every time you create one, it creates another and another and another etc. You can instantiate objects there, but instantiating another object of the same type causes your infinite loop.
Also, in your methods (declareArr, assignArr etc) you can remove the 'new Arrayprg().' and just call the functions on the existing object.
In a class you can create objects outside any method, object cannot be of the same class.
It is meaningless. Take it as a rule.

Why does a Try/Catch block create new variable scope?

For example:
try
{
SomeObject someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //can't access someObject!
But you can declare it before the try/catch block and then it works fine:
SomeObject someObject;
try
{
someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //works fine
I'm just wondering the design reason for this. Why are Objects created within the try/catch block not in scope with the rest of the method? Maybe I'm not understanding deep down how a try/catch works besides just watching for Exceptions thrown.
Why are Objects created within the try/catch block not in scope with the rest of the method?
They are. Variables declared within the try/catch block are not in scope in the containing block, for the same reason that all other variable declarations are local to the scope in which they occur: That's how the specification defines it. :-) (More below, including a reply to your comment.)
Here's an object created within a try/catch which is accessible outside of it:
SomeObject someObject = null;
try
{
someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); // This is fine -- unless the SomeObject
// constructor threw the exception, in which
// case someObject will be null
Note the difference. Where the variable is declared defines the scope in which it exists, not where the object was created.
But based on the method names and such above, the more useful structure for that would be:
SomeObject someObject = new SomeObject();
try
{
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod();
Re your comment:
I guess I'm confused as to why another scope has even been created for a try/catch block.
In Java, all blocks create scope. The body of an if, the body of an else, of a while, etc. — they all create a new, nested variable scope:
if (foo) {
SomeObject bar = new SomeObject();
}
bar.doSomething(); // <== Compilation error, `bar` is not defined
(In fact, even a block without any control structure creates one.)
And if you think about it, it makes sense: Some blocks are conditional, like the one defining the body of an if or while. In the above if, bar may or may not have been declared (depending on the value of foo), which makes no sense because of course the compiler has no concept of the runtime value of foo. So probably for consistency, the designers of Java went with having all blocks create a new nested scope. (The designer of JavaScript went the other way — there is no block scope at all, yet, though it's being added — and that approach also confuses people.)
In Java, any time you have a { } pair, you can create a new scope.
Consider the following
class ScopeTest {
public static void main(String[] args) {
int i = 0;
{ int j = 0; System.out.println(j); }
{ int j = 2; System.out.println(j); }
}
}
The try/catch just follows this idiom, and enforces a { } pair to be created.
To respond to your followup of a non-bracketed if statement, consider:
class MultiRTree {
public static void main(String...args) {
boolean b = args.length == 0;
if(b) String s = new String("hello");
}
}
results in
c:\files\j>javac ScopeTest.java
ScopeTest.java:4: not a statement
if(b) String s = new String("hello");
^
ScopeTest.java:4: ';' expected
if(b) String s = new String("hello");
^
2 errors
However, this will compile just fine.
class ScopeTest {
public static void main(String...args) {
boolean b = args.length == 0;
if(b) new String("hello");
}
}
Why this is so, according to the JLS Chapter 14, section 9, if is defined as:
IfThenStatement:
if ( Expression ) Statement
And Statement is defined as (14.5)
Statement:
StatementWithoutTrailingSubstatement
LabeledStatement
IfThenStatement
IfThenElseStatement
WhileStatement
ForStatement
StatementWithoutTrailingSubstatement:
Block
EmptyStatement
ExpressionStatement
AssertStatement
SwitchStatement
DoStatement
BreakStatement
ContinueStatement
ReturnStatement
SynchronizedStatement
ThrowStatement
TryStatement
So a block, expression statement, or empty statement those are just fine. But a declaration (defined in chapter 6) is not in the grammar of statement.
Every time you do use a bracket '{' you're expressing a new scope in both C++ and Java. You're attempt to try an operation requires some internal setup and scoping the names allows for quick jumps back out of the try block without a lot of cleanup.
Some languages will let you access those scoped variables outside of the scope as long as there isn't a name conflict (like in Python), but this requires an slightly different internal stack structure and could still increase the costs of the try catch regardless.
Also it's just how scope definitions are defined in Java -- as many of the other answers pointed out.
The scope of a variable or object is in the scope (defined by curly braces {}) in which it is defined.
Since try catch initiates a new scope where some error can be thrown so the objects defined inside try catch are not available outside it's scope.
try/catch creates a new scope for the simple reason that it is a block level element. In fact, simply placing {} just randomly inside a method will create a new block of code with it's own local scope.

In what order are initializer block and variable definitions and etc. executed? (in java)

I have problem understanding the order in which initialization happens. this is the order I assumed:
*Once per
1. Static variable declaration
2. Static block
*Once per object
3. variable declaration
4. initialization block
5. constructor
but according to this code I am obviously wrong:
class SomethingWrongWithMe
{
{
b=0; //no. no error here.
int a = b; //Error: Cannot reference a field before it is defined.
}
int b = 0;
}
And the error would disappear if I do this:
class SomethingWrongWithMe
{
int b = 0;
{
b=0;
int a = b; //The error is gone.
}
}
I can't figure out why isn't there an error on
b=0;
The Java Language Specification (section 8.3.2.3) says you can use a variable on the left hand side of an expression, i.e. assign to it, before it is declared, but you cannot use it on the right hand side.
All variables are initialized to their default values, then explicit initializers and anonymous blocks are run in the order they are found in the source file. Finally the constructor is called.
Statics are only run once on the first use of a class.
The compile error appears to be a rule of Java rather than something that necessarily makes sense in every case.
Variable definitions are not done "before" blocks. They are both done at the same time, in the order that they are defined
class SomethingWrongWithMe {
{
b = debug("block 1");
}
int b = debug("define");
{
b = debug("block 2");
}
private int debug(String str) {
System.out.println(str);
return 0;
}
}
Output
block 1
define
block 2
First of all, your assumptions are more or less correct, except for the fact that declarations (with initialization, such as int b = 0) and instance initializer blocks are executed in the order they are written.
int b = 0; // executed first
{
b = 1; // executed second
}
int a = b; // executed third
Also note that the declaration i.e. int b is not executed. The declaration just declares the existence of the variable.
As for the error you got (or, rather the error you didn't get) I agree that it looks strange. I assume that the compiler deals with referencing a variable in an expression and assigning a value to it in different ways. When writing to a variable in an instance initializer, it just checks that the variable is there, while when reading from it, it requires it to be declared above the instance initializer block. I'll see if I can find a reference for that in the JLS.

Difference between {} and {{}} initialization in Java

public class A{
}
A a = new A(){{
final int x = 1; // IT HAS TO BE FINAL HERE. WHY?
}};
A aa = new A(){
int x = 1; // THIS NEED NOT BE FINAL. WHY?
final int y = 1; // STILL FINAL IS ALLOWED HERE. WHY?
public int getX(){
return x;
}
};
Can somebody please answer the questions mentioned inside the snippet?
Thanks
The outer set of {} declares an anonymous subclass
The inner set declares an initialization block within that subclass.
With the following example, it becomes easier to understand what's going on:
List<String> strings = new ArrayList<String>() {{
add("string");
add("another string");
}};
You basically say: I want a subclass of List, which calls method add at initialization.
It's similar to:
List<String> strings = new ArrayList<String>();
strings.add("string");
strings.add("another string");
A a = new A(){{
final int x = 1; // IT HAS TO BE FINAL HERE. WHY?
It needn't.
The difference between the two is that in the first case, you're writing the code used to initialize each object in the double braces. That x is its local variable (doesn't have anything to do with objects of class A).
In the second case, you're defining the classes body. x would be its member variable. If it were static, its class variable. If final a (basically) constant.
I wonder, why would you want to use the first version of the code (the one with {{}}). The x variable declared inside it's not useful at all, it's local only to the block scope in which it was defined, and being inside an anonymous class, you won't be able to reference it anywhere in the code.
And anyway, the first version of x declaration does not need to be final, it compiles just as fine, with or without final.
In your first example the inner braces create something called an instance initializer. It's an obscure way to initialize variables and call instance methods when an object is constructed. So the first example creates an anonymous subclass of A and creates a local variable within the scope of the initializer. It doesn't have to be final.
In the second example you're creating an anonymous subclass of A but not creating an instance initializer, the variables you create are instance variables of the anonymous subclass.
The first instance A a = new A(){{... has an initialisation block inside the declaration. Another way of writing it would be like this:
A a = new A()
{
{
final int x = 1; // This is inside an initialisation block
}
};
Changing the formatting makes it a bit more obvious.

Categories