I am getting ready for a java certification exam and I have seen code LIKE this in one of the practice tests:
class Foo {
int x = 1;
public static void main(String [] args) {
int x = 2;
Foo f = new Foo();
f.whatever();
}
{ x += x; } // <-- what's up with this?
void whatever() {
++x;
System.out.println(x);
}
}
My question is ... Is it valid to write code in curly braces outside a method? What are the effects of these (if any)?
Borrowed from here -
Normally, you would put code to initialize an instance variable in a
constructor. There are two alternatives to using a constructor to
initialize instance variables: initializer blocks and final methods.
Initializer blocks for instance variables look just like static
initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
You may also wanna look at the discussions here.
This is an initializer block that is executed while the instance of the class is being loaded/created and that is used to initialize member properties of a class (See Java http://download.oracle.com/javase/tutorial/java/javaOO/initial.html). You can have as many blocks as you want and they will be instantiated from top to bottom.
In addition to the instance block, you can have as many static blocks as you want as well to initialize static members. They would be declared as follows:
public class Initialization {
static int b = 10;
int a = 5;
static {
b = -9;
}
{
a += 2;
}
public static void main(String[] args) throws Exception {
System.out.println(ClientVoting.b);
System.out.println(new ClientVoting().a);
System.out.println(ClientVoting.b);
System.out.println(new ClientVoting().a);
}
static {
b = 1;
}
{
a++;
}
}
While the class is being initialized, the static member "b" is initialized as 10, then the first static scope changes its value to -9, and later to 1. This is only executed once while the class is loaded. This executes before the initialization of the first line of the main method.
On the other hand, the similar example to your class is the instance reference "a". A is initialized as 5, then the instance block updates it to 7, and the last block to 8. As expected, the static members are only initialized once in this code, while the instance blocks are executed EVERY time you create a new instance.
The output to this example is 1 8 1 8
It's an initializer block. It's used to set instance variables. The motivation to use initializer blocks over constructors is to prevent writing redundant code. The Java compiler copies the contents of the block into each constructor.
Related
What is the problem with below code?
class test {
static int a;
a=10;
}
If I'm writing like this (as above), I'm getting a compile time error.
class test {
static int a=10;
a=4;
}
For the second one, I'm not getting any error.
Neither of your examples should compile.
a=10;
is a statement, which is not valid directly inside a class declaration. You can only put the following directly inside a class:
Member declarations (member/static variable declarations (like static int a;), methods, nested classes and interfaces);
Static and instance initializers;
Constructors.
You need to put a statement inside a block, for example a static initializer:
static int a;
static {
a = 10;
}
which is equivalent to:
static int a = 10;
You need to use a static block of statement to do an assignment on an other line (outside a method)
class test {
static int a;
static { a=10; }
}
a=4; must be done in a valid scope
either a method or a constructor...
this line is valid instead
static int a=10;
because java allows youto declare and initialize in one statement!
If you want to initialize a after defining it as a null int, you can only do that in a function, because it is static.
must be initialized inside static block or init block or in constructor.
you can only initialized your member variable after declaration inside a function or block because it is static you should use static block
What you are currently doing is declaring a variable in a class decleration, which is not valid. Looking at this neither of your examples should give you any good result.
In a class declaration you can however initialize a variable:
static int a;
Then if you want to work with it you would have to create a method first (if you are not aware of this I would strongly advise to watch some youtube tutorials or read books about this topic) :
public void foo(int a){
a = 6; //Here you can play with your variables and change them
}
In class declararions you can: declarations methods, initializers and constructors. (there is a bit more you can do, however I would have a look at these points before diving in too deep).
Furthermore it seems that you are not aware what a static variable or a static method does, I think the following posts will help you with that:
difference between 'static int' and 'int' in java
What are static method and variables?
I hope I could help and have fun learning Java
Because for static memory allocated at the time of class loading
so we need do like this
class test {static int a =10;
public static void main(String args[]) { a=12 output(test.a (or) a);}}
A Java class body is should contain declarations and declaration with an initializer, not the standalone statements. Let's unwrap your requirement of initializing a static variable.
Static variables should not be initialized inside methods as these variables belong to the class. But they can be initiated inside the constructor.
public class Example {
static String name;
static int age;
Example() {
name = "James";
age = 34;
}
public static void main(String args[]) {
new Example();
System.out.println(Example.name);
System.out.println(Example.age);
}
}
Now the output will be :
James
34
If new Example(); is not called then the output will be :
null
0
This is because the static variables are initialized with an object creation and for each Example object name and age will be overwritten with the same value. But at least one object needs to be created for name and age to be initialized.
But if you declare a static and final instance variable, we cannot initialize that in the constructor, it is mandatory to initialize static and final variables at the class level. We can initialize while declaring the variable or using a static initialization block. This runs before the main() method in Java. Hence when the main() method is loaded this static variable will be initialized and the compiler will not throw any errors.
static final int name = "STRING";
static final int age;
static {
age = 10;
}
Putting all these things together,
A static variable can be initialized,
When declaring.
Inside a constructor.
Inside a static block.
A static final variable can be initialized,
When declaring.
Inside a static block.
A final variable can be initialized,
When declaring.
Inside a constructor (If you have more than one constructor in your class then it must be initialized in all of them).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java static class initialization
in what order are static blocks and static variables in a class executed?
When I run this code the answer is 1, I thought it would be 2.
What is the order of initialization and the value of k in each step?
public class Test {
static {k = 2;}
static int k = 1;
public static void main(String[] args) {
System.out.println(k);
}
}
Edit 1: As a follow up to "k is set to default value" then why this next code doesn't compile? Theres an error "Cannot reference a field before it's defined".
public class Test {
static {System.out.println(k);}
static int k=1;
public static void main(String[] args) {
System.out.println(k);
}
}
Edit 2: For some unknow to me reason it^ works when instead of "k" its "Test.k".
Thanks for all the answers. this will sufice :D
They are executed in the order that you write them. If the code is:
public class Test {
static int k = 1;
static {k = 2;}
public static void main(String[] args) {
System.out.println(k);
}
}
then the output becomes 2.
The order of initialization is: ..the class variable initializers and static initializers of the class..., in textual order, as though they were a single block.
And the values (for your code) are: k = 0 (default), then it's set to 2, then it's set back to 1.
You can check that it's actually set to 2 by running the following code:
private static class Test {
static {
System.out.println(Test.k);
k = 2;
System.out.println(Test.k);
}
static int k = 1;
public static void main(String[] args) {
System.out.println(k);
}
}
Short answer
When the initialization of the class starts, k will have initial value of 0.
The static block (since it precedes the assignment in the declaration) is then executed, and k will be assigned 2.
Then the initializer in the declaration is executed, and k will be assigned 1.
Long explanation
Let us use this example, since your example is a bit simple:
class TestInitOrder {
static {
System.out.println(TestInitOrder.stat1);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
str = "something";
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
private static final int stat1 = 10;
static final String str2 = "sdfff";
static String str = "crap";
private static int stat2 = 19;
static final Second second = new Second();
static final int lazy;
static {
lazy = 20;
}
static {
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
public static void main(String args[]) {
}
}
class Second {
public Second() {
System.out.println(TestInitOrder.second);
}
}
According to Java Language Specification, from section 4.12.5:
Every variable in a program must have a value before its value is used:
Each class variable, instance variable, or array component is initialized with a default value when it is created
(The following lines from the specification specify the default value for all the types, basically some form of 0, such as 0, 0.0d, null, false, etc.)
So before the class is initialized (due to one of these reasons), the variables will hold an initial value.
According to the detailed initialization procedure (only the interesting steps are quoted here, and emphasis mine):
6.
[...] Then, initialize the final class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
[...]
9.
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
Let us look at step 6, with the 4 final class variables: stat1, str2, second, lazy.
Since 10 is constant expression, and so is "sdfff", and due to the order of execution, it is not possible to observe the initial value for str2 and stat1. In order to make an observation, the earliest you can do is in step 9.
The case of second demonstrate that when the right hand side is not a compile-time constant expression, so its initial value is visible.
The case of lazy is different, since the assignment is done in static block, and hence happen in step 9 - so it is possible to observe its initial value. (Well, the compiler checks carefully that lazy is assigned exactly once).
After the initialization of final class variables with compile-time constant expression comes the execution of static blocks and the rest of the initializers.
As you can see from the example, the static blocks and initialization happens according to textual order - demonstrated with the use of str variable - it is first printed out as null, then something, then crap.
Some may find it similar to the SO question Will Java Final variables have default values? but that answer doesn't completely solve this, as that question doesn't directly print the value of x within instance initializer block.
The problem arises when I try to print x directly inside the instance initializer block, while having assigned a value to x before the end of the block :
Case 1
class HelloWorld {
final int x;
{
System.out.println(x);
x = 7;
System.out.println(x);
}
HelloWorld() {
System.out.println("hi");
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
This gives a compile time error stating that variable x might not have been initialized.
$ javac HelloWorld.java
HelloWorld.java:6: error: variable x might not have been initialized
System.out.println(x);
^
1 error
Case 2
Instead of directly printing, I am calling a function to print:
class HelloWorld {
final int x;
{
printX();
x = 7;
printX();
}
HelloWorld() {
System.out.println("hi");
}
void printX() {
System.out.println(x);
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
This compiles correctly and gives output
0
7
hi
What is the conceptual difference between the two cases?
In the JLS, §8.3.3. Forward References During Field Initialization, its stated that there's a compile-time error when:
Use of instance variables whose declarations appear textually after the use is sometimes restricted, even though these instance variables
are in scope. Specifically, it is a compile-time error if all of the
following are true:
The declaration of an instance variable in a class or interface C appears textually after a use of the instance variable;
The use is a simple name in either an instance variable initializer of C or an instance initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
The following rules come with a few examples, of which the closest to yours is this one:
class Z {
static int peek() { return j; }
static int i = peek();
static int j = 1;
}
class Test {
public static void main(String[] args) {
System.out.println(Z.i);
}
}
Accesses [to static or instance variables] by methods are not checked in this way, so the code above produces output 0, because the variable initializer for i uses the class method peek() to access the value of the variable j before j has been initialized by its variable initializer, at which point it still has its default value (§4.12.5 Initial Values of Variables).
So, to summarize, your second example compiles and executes fine, because the compiler does not check if the x variable was already initialized when you invoke printX() and when printX() actually takes place at Runtime, the x variable will be assigned with its default value (0).
Reading the JLS, the answer appears to be in section 16.2.2:
A blank final member field V is definitely assigned (and moreover is not definitely unassigned) before the block (§14.2) that is the body of any method in the scope of V and before the declaration of any class declared within the scope of V.
This means that when a method is called, the final field is assigned to its default value 0 before invoking it, so when you reference it inside the method, it compiles successfully and prints the value 0.
However, when you access the field outside of a method, it is considered unassigned, hence the compilation error. The following code will also not compile:
public class Main {
final int x;
{
method();
System.out.println(x);
x = 7;
}
void method() { }
public static void main(String[] args) { }
}
because:
V is [un]assigned before any other statement S of the block iff V is [un]assigned after the statement immediately preceding S in the block.
Since the final field x is unassigned before the method invocation, it is still unassigned after it.
This note in the JLS is also relevant:
Note that there are no rules that would allow us to conclude that V is definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C. We can informally conclude that V is not definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C, but there is no need for such a rule to be stated explicitly.
The difference is that in the first case you are calling System.out.println from initializer block so the block which is invoked before constructor. In the first line
System.out.println(x);
variable x is not yet initialized so that you get compilation error.
But in the second case you call instance method which doesn't know if variable has already been initialized so you don't have compilation error and you can see the default value for x
Ok, here is my 2 cents.
We all know that final variables can be initialized only While declaring or later on in constructors. Keeping that fact in mind, let see what happened here so far.
No errors Case:
So when you use inside a method, it have already a value.
1) If you initialize it, that value.
2) If not, the default value of data type.
Error case :
When you do that in an initialization block, which you are seeing errors.
If you look at the docs of initialization block
{
// whatever code is needed for initialization goes here
}
and
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
In compiler's eye, your code is literally equals to
class HelloWorld {
final int x;
HelloWorld() {
System.out.println(x); ------------ ERROR here obviously
x = 7;
System.out.println(x);
System.out.println("hi");
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
You are using it before even initializing it.
Case 1 :
Gives you a compile-error,
Because at System.out.println(x);
you are trying to print x which was never initialized.
Case 2:
Works because you are not directly using any literal values, instead you are calling some method, which is correct.
General Rule is,
If you are trying to access any variable which is never initialized
then it will give a compilation error.
We deal here with initializer block. The Java compiler copies initializer blocks into every constructor.
The compiler error don't occure in second example, because printing x is in another Frame, please refer to spec.
Here is example code:
class A {
static {
int a;
class B {
}
}
public static void main(String[] args){
// cannot access class B and in a;
}
}
I don't know what the static keyword in this context means. I declare an int variable and a class inside it. But I cannot use it inside class A or in the main method. I compile and it doesn't produce any errors. So, I think this type of declaration has some purpose.
This is a static initialization block. You can use this to collect initialization for static/class members.
Similarly you can have a non-static initialization block to initialize instance members for each new object:
class A
{
static int a;
private int b;
// static/class initialization:
static
{
// initialize class members
a = 5;
}
// instance initialization:
{
// initialize instance members
b = 5;
}
}
This example is trivial, you could instead just initialize the variables in their declaration: static int a = 5, and in fact generally that would be clearer. But use an initialization block when the initialization is multi-step, or generally more complicated, for example, setting up a database connection.
For more examples, see: Initializing Fields from the java tutorials.
The code inside the static {} block will be executed when the class (not an object of this class) is loaded for the first time.
See this
It is referred as static block in Java. This is usually used for initialization purposes that your Class A might require
static blocks are executed when JVM loads this class. There can be many such blocks and they would be executed in the order of appearance
This is a static initialization block. Here is Oracle Java SE documentation static initialization blocks.
In your example, int a is a local variable to the static initialization block. Here is another Stackoverflow post regarding local variables in static initialization blocks: What is the scope of variables declared inside a static block in java?. That is why you cannot access it in your main method.
That definition is a static initializer block. It allows extra logic for initialization, in this case applied to static members.
You will be able to access whatever you initialize in the block if you call the class A constructor, because "the Java complier copies initializer blocks into every constructor". Check docs
This is the static initializer block.
The reason that int a and class B cannot be accessed outside of the block is due to scoping. Similar to constructors and methods, variables declared within the scope of the initializer block are not accessible outside of the block.
I've never seen this before - what is it called? This is a class level variable, at the beginning of the file.
Just to be clear, I'm referring to the static {} after the variable.
private static final UriMatcher URI_MATCHER;
static {
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH);
URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH);
URI_MATCHER.addURI(AUTHORITY, "books", BOOKS);
URI_MATCHER.addURI(AUTHORITY, "books/#", BOOK_ID);
}
It's an static initialization block. It can be declared anywhere inside a class (but outside a method), but by convention it's usually written right after the static variable that's being initialized. It's specified in the Java Language Specification, section §8.7.
As the name implies, it's normally used for initializing the state of static attributes in the class at class-loading time. From the Java tutorial:
A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword (...) A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
that is used to initialize static variables. As you know, you cannot initialise them in constructor of your class, so you can use static block
As an example:
you want to fill static array with value 1, 2, 3 and so on. There is two ways:
public class Main {
static int[] array1 = {1, 2, 3, 4 ...};
static int[] array2;
static {
array2 = new int[N];
for (int i = 0; i < N; i++) {
array2[i] = i;
}
}
}
This is a static portion of code that initialices the static var URI_MATCHER after it's declared
It's a static initialization block. It allows you to "set up" your static fields, which cannot be done correctly in the methods of the class instances.
It's just a static initialization block. Check out: http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html