I am not able to understand flow of control in the following code:
class Television {
private int channel=setChannel(7);
public Television (int channel) {
this.channel=channel;
System.out.println(channel + "");
}
public int setChannel(int channel) {
this.channel=channel;
System.out.print(channel + " ");
return channel;
}
}
public class TelevisionMain {
public static void main(String[] args) {
Television t = new Television(12);
}
}
The output is 7 12.
It means explicit invocation occurs first.
I am new to java and I thought that execution starts from main so the constructor should have been invoked first.
Can anyone please explain why this happens.
initialisation is part of construction and it is defined to occur after the super() has been called and before the body of the constructor.
the constructor should have been invoked first.
It is. The field initialisation is part of the constructor.
Your Television constructor is compiled to roughly:
public Television(int channel)
{
super();
this.channel = this.setChannel(7);
this.channel = channel;
System.out.println(channel+"");
}
So when you call Television t = new Television(12);, it first sets the channel to 7, then 12.
Ultimately the answer is because the specification says it should. However it is reasonable that it be this way round because to behave the otherway round would make it impossible to overwrite a default initialed value
If the order were constructor first then everything else, then the order would be
called Television(12)
channel set to 12 within constructor
channel set back to 7 by int channel=setChannel(7);
This is clearly an unreasonable state of affairs as you could never use default values because these default values could not be changed by a constructor
In Java there is essentially a hidden default constructor. If you don't declare one, you can initialize a variable at the top of a class with a default variable. That's the way we like to think of it anyways. The reality is that each class has a static block where variables can be declared and played with before actual constructor declaration hits during the class load process.
I feel like your above declaration is similar to this, and that is why you are seeing the output 7 12.
class Television {
//The below code is essentially equal to your declaration of
// private int channel = setChannel(7);
private int channel;
static{
//This occurs before constructor call during class load.
channel = setChannel(7);
}
....
}
A better explanation can be found in the java tutorials on Initializing Fields
Related
i am trying to grasp the idea of ObjectOriented programing can someone explain why the local variable (a) prints zero instead of the set int that is placed in the getter and setter.
These are the objects in the AppClass
Symptoms obj = new Symptoms();
test obj2 = new test();
actionPerformed... i think this is all you need from the AppClass
#Override
public void actionPerformed(ActionEvent e) {
int x = Integer.parseInt((field.getText()));
obj.setSleep(x);
writeSleep();
frame.setVisible(false);
obj2.tester();
readSleep();
initialize2();
}
This is the Symptoms class that i hope to add more symptoms if i can get this to work
public class Symptoms {
private int sleep;
public int getSleep() {
return sleep;
}
public void setSleep(int sleep) {
this.sleep = sleep;
}
}
this is the tester class where i hope to print out the value of (a)
public class test {
public void tester(){
Symptoms get = new Symptoms();
int a;
a = get.getSleep();
System.out.println(a);
}
}
It seems as tho the test class isnt getting the "message" but if i run the same code in the AppClass, given i modify the code a little bit, then (a) will print.
Because the JLS says so, see chapter 4.12.5. Initial Values of Variables:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10):
For type int, the default value is zero, that is, 0.
Now after you saw it's confusing, I recommend you to explicitly set it to zero in the future, it's clearer.
In test.tester(), an instance of Symptoms is created and the method setSleep() is never called with it, so getSleep returns the default value of a, which is 0.
You only ever call setSleep in obj.setSleep(x);, where obj is an entirely different instance from get. But since x is not static, calling obj.setSleep doesn't change the value of get.x -- only the value of obj.x.
here is a better version of the question and the answer. It has nothing to do with setting int to zero.
How to set and get with three Classes?
Here is the following code where I have two classes practically doing nothing. When the decompiled code of the "class TestBed" is checked "int val = tb.display()" gets placed in constructor automatically. How is this happening ?
class TestBed
{
int display()
{
return 100;
}
TestBed tb;
int val = tb.display(); /* will get placed in constructor
automatically. But how? */
}
public class DeleteThis {
public static void main(String[] args) {
System.out.println("printing");
}
}
After decompiling "TestBed.class" using decompiler following code appears
/* Following is decompiled code */
class TestBed
{
TestBed tb;
int val;
TestBed()
{
val = tb.display(); /* How int val = tb.display() gets placed
in constructor automatically */
}
int display()
{
return 100;
}
}
That's because of the format of the *.class file. When you compile a *.java file into a *.class file, all instance fields that are initialized in the way your field var are (this is: T myVar = myValue) are going to be initialized in the constructor's code.
A brief and incomplete description of the class format:
A class format is made up of different kind of "structures", two of them are the field structure (where your field var is registered) and the method structure (code lives only inside this kind of structure under the attribute "code").
The field structure doesn't have room for code (the code that would initialize you var: int val = tb.display();) so it needs to be put inside the "code" attribute of the method structure that corresponds to the constructor.
Have a look at the Java Virtual Machine Specification, Ch. 4 for more details (trying to explain everything here in few words would be too complicated)
Your field val has value equals tb.display. All fields initialize with default value (0 for int) and other predefined user value at constructor. So method tb.display is called in constructor.
Run time the above code gives Null Pointer Exception since the tb variable has not been initialized.
As the initialization of Class level variables has to happen on the class instantiation, the compiler places the code in the constructor.
Try defining an explicit constructor with some argument and also try one more approach by below change
static TestBed tb;
static int val = tb.display();
I don't think there is any particular reason for this behavior.
Typically, though, variables are instantiated inside of the constructor and the decompiler is probably just using this standard. The effect of both segments of code, in this case, should be exactly the same.
Regardless, val will be set to tb.display();.
The instance variable initialization is actually put in the constructor(s) by the compiler.
See here
Your variable TestBed tb is not initialized yet you are calling , int val = tb.display(); which will throw exception. The reason you are not getting exception is because you are not instantiating the class TestBed anywhere in the main() , the moment you change code to :-
public class DeleteThis {
public static void main(String[] args) {
TestBed tb=new TestBed();
System.out.println("printing");
}
You wil get nullpointer exception
And the reason why you get that code in decompiler is because of this, reading from a java tutorial (could not find the link for javadocs source :))
The Java compiler generates instance-field initialization code automatically and puts it in the constructor or constructors for the class. The initialization code is inserted into a constructor in the order it appears in the source code.
hence the compiler breaks int val= tb.display() into
int val;
TestBed(){
val=tb.display();
}
I need to know how to call a variable from one method to another
Can anyone help me?
public static void number(){
number = 1;
}
public static void callNumber(){
/*How can I call number to this method???
*/
}
Actually, "call a variable from an other method" is not very explicit, since a variable in a method is either global (used in the method but naturally available in the entire program), or a local variable of the method.
And in this last situation it is impossible to get this value.
Then either you declare your variable externally and it is trivial, or you specifiy a type value to your method "number()":
public static int number() {
int number = ...;
return number;
}
and you call it:
public static void callNumber() {
int numberReturned = number();
// other things...
}
Note: your code number = 1; specifies that your variable is global...
The trick is to set "number" available either by the return of the method, or by specifying this variable global.
I don't know if I've answered your question, if not try to be more explicit.
Between static methods, variables can be shared by making them global,
or by sending them as parameters(noas described by #Gaétan Séchaud).
However, if those two methods has a continuos connection between them, and they handle some variables needed to be shared, it smells like a class is needed.
There is a code which is given as a task for a junior Java developers. I use Java during five years and this piece of code completely confusing me:
public class Main {
String variable;
public static void main(String[] args) {
System.out.println("Hello World!");
B b = new B();
}
public Main(){
printVariable();
}
protected void printVariable(){
variable = "variable is initialized in Main Class";
}
}
public class B extends Main {
String variable = null;
public B(){
System.out.println("variable value = " + variable);
}
protected void printVariable(){
variable = "variable is initialized in B Class";
}
}
The output will be:
Hello World!
variable value = null
But if we change String variable = null; to String variable; we will have:
Hello World!
variable value = variable is initialized in B Class
The second output is more clear for me.
So, as far as I know the sequence of inizialisation in Java like this:
We go to the root of the class hierarchy (for Java it is always Object class), when we come to this root parent class:
All static data fields are initialized;
All static field initializers and static initialization blocks are executed;
All non-static data fields are initialized;
All non-static field initializers and non-static initialization blocks are executed;
The default constructor is executed;
Then we repeat the procedure for the underlying child class.
Also there is post which describes the behavior of the this keyword in context of a superclass - Calling base class overridden function from base class method
Based on the rules given above, I assume to have sequence like this:
We are going to create a new instance of class B;
We go to the part class Main;
Initialize main.variable with null;
Then we move to the default constructor of class Main;
Constructor calls method b.printVariable() in class Main; (Why doesn't it call main.printvariable? We don't have this key word here.)
The field b.variable "variable is initialized in B Class"
Now we come back to the class B;
We should initialize field b.variable with null value, am I right?;
The default constructor of class B executed
Please, can someone give a complete and full explanation of how this inheritance inizialisation sequence works. And why changing String variable = null; to String variable; leads to another output.
The sequence is:
Main -> "Hello"
Main -> new B()
B() -> Main() -> b.printVariable() -> sets the variable
Back to initialising B, so variable=null occurs.
So basically, the super object Main() is constructed before any intialisation events of class B. Which means variable=null occurs later. This makes sense as otherwise B could break the initialisation of Main.
Joshua Bloch covers a lot of good ground in his effective java book about how dangerous inheritance is to get right, I would recommend it.
First, you need to understand, what happens when you write variable = null;. When is that code executed. This basically determines the output.
Before I begin, I should also mention that when you create an object of class B, the printVariable() function of the main class is not called. Instead, always the printVariable() of B will be called.
Keeping this in mind, when you have variable = null, the execution for B's constructor will begin. First Main() will be called, which will call the printVariable() method. At last, variable=null, will be called overwriting the variable variable.
In the other case, where you do not initialize variable=null, the variable set by the printVariable() function will not be overwritten, hence you get what you were expecting.
In summary, this is the order of execution of statements, when you do new B():
Main() //super constructor
B#printVariable()
initializtion of variables in B's constructor (if any) [i.e. variable=null, if present]
This is a nice exercise! But it's not a fair question to ask junior developers. This one is for seniors. But to make this text useful during the technical interview, I'd modified it by adding an argument to the Main's constructor:
public Main(String something){
printVariable();
}
If the person will answer what will happen, then remove the argument and ask the original questions. If the person won't answer - there is no need to continue - s/he is junior.
You can also remove the protected qualifier in class B and ask what will happen if you have a goal not to hire this person :)
$ javac InitInt.java
InitInt.java:7: variable right might not have been initialized
InitInt(){}
^
1 error
$ cat InitInt.java
import java.util.*;
import java.io.*;
public class InitInt {
private final int right;
// Design Problem?
// I feel the initialization problem is just due to bad style.
InitInt(){}
InitInt{
// Still the error, "may not be initialized"
// How to initialise it?
if(snippetBuilder.length()>(charwisePos+25)){
right=charwisePos+25;
}else{
right=snippetBuilder.length()-1;
}
}
public static void main(String[] args) {
InitInt test = new InitInt();
System.out.println(test.getRight());
}
public int getRight(){return right;}
}
Partial Solutions and Suggestions
use "this" to access methods in the class, instead of creating empty constructor
change final to non-final
with final field value: initialize all final values in every constructor
remove the empty constructor, keep your code simple and clean
You mean define, not initialize. The problem you're having (after that pretty radical edit) is you're defining a constructor that doesn't initialize a final variable, which Java doesn't allow -- all finals need to be initialized by the time the instance is finished constructing. Either initialize it in your constructor, or make it non-final
Yeah, the problem is that one of your constructors doesn't initialize the final field. In Java final non-static fields have to be initialized at the declaration time, in an initialization block, OR in EVERY constructor! The default constructor in your example doesn't do that.
Remember as well that implementing an empty default constructor makes sense only if you want to use inheritance features. If you don't provide a default constructor, but you will some other one Java won't make a hidden default constructor for you, because the default one is not required. So don't implement things like MyClass() {} with no special purpose - keep your code clean and save!
You can't use new with int. int is a primitive, and new is an object operator. Consider using Integer instead, or just assigning an integer literal to it.
There's nothing wrong with your if-else statement, and nothing wrong with initializing a final variable within a branching statement in a constructor. I just ran a simple constructor like yours to initialize private int right and it worked fine. Make sure that you are declaring your constructor correctly, as InitInt() { ... }.
The error you posted is because you have in your code InitInt(){}, an empty constructor that does not initialize right. You need to initialize final fields in this and all constructors.
Your constructor is absolutely Okey!!!! The problem is that you left the "right" variable uninitialized.
You have to initialize the "right" variable:
private final int right = 0;
If you only try to access the methods in the class, use this, instead of creating empty-constructor for it:
import java.io.*;
import java.util.*;
public class FileDir {
private ArrayList<Integer> lineNumbers;
FileDir(Integer nth){
lineNumbers=new ArrayList<Integer>();
lineNumbers.add(nth);
// You don't need an empty constructor
// to call class methods, use "this"
this.printHello("Davids");
}
public static void main(String[] args) {
FileDir test = new FileDir(7);
ArrayList<Integer> inteTest=test.getLineNumbers();
for (Integer i : inteTest)
System.out.println(i);
}
public void printHello(String name) { System.out.println("Hello "+ name); }
public ArrayList<Integer> getLineNumbers() { return lineNumbers; }
}