Why can we do this:
class A{int a=5;}
but are not allowed to do this:
class A {
int a;
a=5;
}
just put it inside a block then.
class A {
int a;
{a=5;}
}
An initialization block will run every time you make in instance of the class e.g.
new A();
this is of course between two other initializations related to creating a new instance.
first is the field's initializations like when you declare a field with a value.
int a = 25;
then the block initialization
{
a = 5;
}
then the constructor:
A() {
a = 6;
}
Related
when I am coding this at class level
int a;
a=5;
it throws error : "identifier expected"
But when I declare it as a local variable like
void m1() {
int a;
a=5;
}
No error is thrown.
When you're doing this at class level, you're allowed to combine declaration and assignment in just one statement, like:
class A {
int a = 5;
}
Otherwise, you have to wrap the assignment withing a block (constructor, method, initializer block). For example:
class A {
int a;
public A() { a = 5; } //via constructor
void setA() { a = 5; } //via method
{ a = 5; } //via initializer block
}
Assigning a value to variable is called as expression. We could not write any expression in a class. We could do the same in method bodies. Basically we could right expressions when scope is defined and hence allowed in method.
The reason following:
int a=5;
declared at class level does not produce compile time error when:
void m1() {
int a;
a=5;
}
is declared because m1() has its own scope.
For instance, if don't declare and access variable a, it would refer to class's field, where as when you declare a locally, you'd always refer to one declared inside a.
PS : You cannot do following at class level:
int a;
a=5;
You'd have to:
int a=5;
You can not write code into the class, only in method, constructor or into initializer {} block. That is why you get syntax error.
Probably you want to use initializer block like this:
class my{
int a;
{
a=1;
}
}
what is the difference in following two pieces of code:
class B{
B(){}
}
//1)
class A{
B b = new B();
}
//2)
class A{
B b;
{
b = new B();
}
}
what is the difference in initialization in these two ways ? Also if both the statement are in one single class , what would be their sequence of execution and why?
EDIT: Adding some more clarification:
class C{
//1)
int i = 5;
//initializers block
{
i =7;
}
}
What is the sequence of execution for both these two statements ? What is the final value of i ?
UPDATE FOR THE NEW CLEARER QUESTION:
It sees now that I should have added more text to my question. I
wanted to know what would be the sequence of execution in case both
these statements(1 and 2) are in one single class for the same
variable ?
You are interessted something like this:
private class Test {
public String field = new String("1");
{
field = new String("2");
}
}
At first the field get the value 1, after that the constructor will be called and the init block which was placed in the ctor at compile time will be executed so the value of field is "2".
See this example:
http://ideone.com/72uxES
See also this Question and answer:
Default constructor vs. inline field initialization
OLD VERSION
I think you mean something like this:
Object obj = new Object()
Or
Object obj;
{
obj = new Object();
}
The curly brackets define a scope in which the variable life time is given.
Say we have following example:
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
private static void checkObject(Object obj) {
if (obj == null)
System.out.println("Object is null");
else
System.out.println("Object is not null");
}
public static void main (String[] args) throws java.lang.Exception
{
Object obj;
{
obj = new Object();
checkObject(obj);
}
checkObject(obj);
}
}
The Output is:
Object is not null
Object is not null
But if we change it to:
{
Object obj = new Object();
checkObject(obj);
}
checkObject(obj);
It will not even compile and give these error msg:
Main.java:22: error: cannot find symbol
checkObject(obj);
^
symbol: variable obj
location: class Ideone
1 error
The first declares a variable obj and initialize it inside the scope
because it was outside declared it can be used after the scope.
If it is declared and initialized only in the scope it can be used only inside the scope.
The lifetime is bound to the scope.
If you use the curly brackets to initialize class fields
you are able to use more than one statement to initialize them
but you can also simply create a final method and call the method to initialize the field.
Example for curly brackets and field initialization:
class A {
private String field;
{
StringBuilder builder = new StringBuilder("Text").append(value)
.append(" ")
.append(otherValue);
//make some computations
//append to builder
//add to field
field = builder.toString();
}
Hint:
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.
See working example:
http://ideone.com/X42rQI
As you know that the constructor is called when we instantiate a class. Also all classes have top level Class as Object in JAVA. Now whenever we call the constructor of any class for your case A as new A() it leads us to call first super() leading to Object's constructor.
Now in your example1 your variable b is declared and initialised in the class itself. So before the constructor of class A is executed the variable b is initialised i.e. all the code that you write in public A() will be executed after b has been initialised.
In your example2 your variable b is declared in the class but is being initialised in the constructor of A. If you have some code before the line b = new B(); that code would be executed first then the b would be initialised.
See the example below :
Class A{
B b = new B();
public A(){
b == null; //FALSE as it has been already initialised.
}
}
But
Class A{
B b ;
public A(){
b == null; //TRUE as it has not been initialised.
b = new B();
b == null; //FALSE as it has been just initialised.
}
}
I assume it has to do with the following:
Initializing Instance Members
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.
https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Basically it means that all instance variables that are between the brackets will be initialized for all constructors. Even though your classes dont have multiple constructors
added example with multiple constructors
class A{
B b;
int index;
String result;
{
b = new B();
index = 0;
}
public A(int temp){
// nothing
}
public A(int temp, String test){
this.result = test;
}
public int getIndex(){
return index;
}
}
It doesnt matter here which constructor you use, as the initialization between the brackets is copied into both constructors. a.getIndex() will always return '0'
If I have:
class A
{
void foo()
{
int a = count;
}
void bar()
{
int a = c; // here ERROR
int c = 10;
}
private int count = 10;
}
here in foo count is used without problem also if it's declared after the use.
The same is not true in method bar where the variable c must be declared before its
use.
Which are the class scope rules? How they differs from method scope rules?
P.S.
My doubt is because the common scope resolutions rules:
When the compiler find count it should try to find it "back" to its
use but back there is Class A... so maybe private int count is "hoisting" at
beginning of Class A?
Imagine that you were a compiler, and you get to the line:
int a = c;
Won't you get angry and ask yourself "What is c"? The order is important1.
1count doesn't make a problem because it's a class member, it's known in the whole class. You can place class members in the beginning of the class, or at the end.
count is declared in the class while c is declared in the method
While compiling, the class would find count in the class.
class A
{
void foo()
{
int a = count;
}
private int count = 10;
}
is equal to put count anywhere in the class, as it is a class member and can be found in the class everywhere.
while in your case of
class A
{
void bar()
{
int a = c; // here ERROR
int c = 10;
}
}
c is not defined before use, as c is a local variable in a method.
My question is regarding the declaration and value assignment rules in Java.
When writing the fields we can declare and assign values together but we cannot do the same separately.
E.G.:
class TestClass1 {
private int a = 1;
private int b ;
b= 1;
private int sum;
public int getA() {
return a;
}
public int getB() {
return b;
}
public int getSum() {
sum = a + b;
return sum;
}
}
public class TestClass {
public static void main(String[] args) {
TestClass1 testClass1 = new TestClass1();
System.out.println("total =" + testClass1.getSum());
}
}
Here in line:
private int a = 1;
We are able to declare a as a private int and assign a value 1 to it. But in case of:
private int b ;
b= 1;
Eclipse does not allow this to happen and throws an error. Kindly explain the logic behind this.
Code inside a class, but outside a function, is purely declarations. It does not get "executed". It simply declares what fields a class contains.
The reason you can do the shorthand private int a = 1; is just syntactic sugar that the Java language allows. In reality, what happens is that the a = 1 part is executed as part of the constructor. It's just easier to read and write when it is next to the variable declaration.
It's something nice that the Java langage creators allowed. Not every language allows that, look at C++ as an example that does not always allow it.
you have to put b=1; inside a method or put this inside a constructor.
you are getting this error since you can't do any thing other than declaration(private int a= 1;
) in class level.
It's just a question of syntax in Java. In the example you show, you try to affect a value to b in the member declaration part of your class. This is not allowed by the syntax of Java. You can only do it when you declare your attribute, in the body of a method or in a static block if your attribute is static e.g. :
private static int b;
static {
b = 1;
}
It is only a syntax problem. You can do it like this :
private int b ;
{ // <- Initialization block
b= 1;
}
See What is an initialization block?
You are unable to write logic directly in the class. You should move it to the constructor.
Java only allow declaration within the class and outside any method. Declarations like int b = 1; will be executed when you initialize a new Object.
Is it possible to assign a value to a final variable anywhere else in the program? Or is it mandatory that they be assigned a value upon creation?
class TestClass() {
//this won't compile but is it possible to assign str a value anywhere else in the program?
public static final String str;
}
You need to assign a value when it's declared - in the constructor if it's not static, in the static initializer block if it is. Once you set the value, it can't be modified.
Do it like this:
public class FinalTest {
private static final String CONSTANT;
private final String value;
static {
CONSTANT = "Hello";
}
public static void main(String [] args) {
FinalTest ft = ((args.length > 0) ? new FinalTest(args[0]) : new FinalTest(CONSTANT));
System.out.println(ft);
}
public FinalTest(String value) {
this.value = value;
}
public String toString() { return this.value; }
}
Local variables
A final variable needs to be assigned a value exactly once before it is accessed. This means that if it's never assigned a value and never accessed, the compiler won't complain.
void foo() {
final int a; // Never assigned, but never accessed either, so no problem
final int b = 7;
System.out.println("b is " + b);
// System.out.println("a is " + a);
// Uncommenting the above line would cause a compile error
}
Static fields
A similar logic applies to final static fields, except it's assumed that they will be accessed at some point, so they must be initialized either on the definition line or in a static initializer block.
Here's what the Java tutorial has to say about static initialization blocks:
This works well when the initialization value is available and the initialization can be put on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used. To provide the same capability for class variables, the Java programming language includes static initialization blocks.
Note: It is not necessary to declare fields at the beginning of the class definition, although this is the most common practice. It is only necessary that they be declared and initialized before they are used.
Instance fields
While we're at it, a final instance (non-static) field must be assigned a value exactly once by the time the instance initialization is complete. This means there are three places where you can initialize one (but you must pick one):
1. Definition line:
// For when you know the answer
class Foo {
final int theAnswer = 42;
}
2. Constructor:
// For when you need to have the answer passed in
class Foo {
final int theAnswer;
Foo(int answer) {
theAnswer = answer;
}
}
// Or for when you need to do some computation
class Bar {
static final int ANSWER_COUNT = 10;
final int[] answers;
Foo() {
answers = new int[ANSWER_COUNT];
for (int i = 0; i < ANSWER_COUNT; i++) {
answers[i] = i;
}
}
3. Initializer block:
// For when you need to do some computation and have many constructors
class Bar {
static final int ANSWER_COUNT = 10;
final int[] answers;
{
answers = new int[ANSWER_COUNT];
for (int i = 0; i < ANSWER_COUNT; i++) {
answers[i] = i;
}
}
// I have many constructors and don't want to copy-paste
// the initialization logic above to all of them
Bar() { ... }
Bar(int i) { ... }
Bar(String blah) { ... }
}
From the same page in the tutorial, regarding initializer blocks:
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 the code you posted, the field is static so it could be given a value from within a static initialization block:
static {
str = "my string";
}
For non-static fields, they can either be initialized in the constructor, or in an instance initializer block:
class TestClass {
private final String str;
{
str = "my string";
}
TestClass() {
}
}