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();
}
Related
In java, how is a child object constructed?
I just started inheritance and these few points are not very clear to me:
Does the child object depend only on the child class' constructor, or does it also depend on the parent's constructor? I need some details about that point.
Also, is super() always called by default in a child constructor?
Any other information regarding this topic is appreciated.
I don't think "A child object" is a good way to think about this.
You're making an object. Like all objects, it is an instance of some specific class, (After all, new SomeInterface() does not compile) and like (almost) all objects, it is made because some code someplace (doesn't have to be your code, of course) ran the java expression new SomeSpecificClass(args); somewhere.
We could say it is a 'child object' because SomeSpecificClass is a child class of some other class.
But that's rather useless. That means the only way to ever make a new 'non-child' object would be to write new Object(); - after all, all classes except java.lang.Object are a child class: If you write public class Foo {}, java will interpret that exactly the same as if you had written public class Foo extends java.lang.Object {}, after all.
So, barring useless* irrelevancies, all objects are child objects, and therefore as a term, 'child object', I'd not use that.
That also means that ALL object creation goes through this 'okay and in what order and how do the constructors work' song and dance routine.
How it works is probably most easily explained by desugaring it all. Javac (the compiler) injects things if you choose to omit them, because a lot of things that feel optional (such as a constructor, a super call, or an extend clause), at the class file / JVM level, aren't**.
Sugar #1 - extends clause
Already covered: if you have no extends clause on your class def, javac injects extends java.lang.Object for you.
Sugar #2 - no super call in constructor
A constructor must either call some specific super constructor on its very first line, or, it it must call some other constructor from the same class on its very first line (this(arg1, arg2);). If you don't, java will inject it for you:
public MyClass(String arg) { this.arg = arg; }
// is treated as:
public MyClass(String arg) {
super();
this.arg = arg;
}
Notably including a compiler error if your parent class has no zero-arg constructor available.
Sugar #3: No constructor
If you write a class that has no constructor, then java makes one for you:
public YourClass() {}
It will be public, it will have no args, and it will have no code on it. However, as per sugar #2 rule, this then gets expanded even further, to:
public YourClass() {super();}
Field inits and code blocks get rewritten to a single block.
The constructor isn't the only thing that runs when you make new objects. Imagine this code:
public class Example {
private final long now = System.currentTimeMillis();
}
This code works; you can compile it. You can make new instances of Example, and the now field will hold the time as it was when you invoked new Example(). So how does that work? That feels a lot like constructor code, no?
Well, this is how it works: Go through the source file top to bottom and find every non-static initializing code you can find:
public class Example {
int x = foo(); // all non-constant initial values count
{
x = 10;
// this bizarre constructor is legal java, and also
// counts as an initializer.
}
}
and then move all that over to the one and only initializer that classes get, in the order you saw them.
Ordering
So, via sugar rules we have reduced ALL classes to adhere to the following rules:
ALL classes have a parent class.
ALL classes have at least 1 constructor.
ALL constructors invoke either another constructor or a constructor from parent.
There is one 'initializer' code block.
Now the only question is, in what order are things executed?
The answer is crazy. Hold on to your hats.
This is the order:
First, set all fields to 0/false/null of the entire 'construct' (the construct involves every field from Child all the way down to Object, of course).
Start with the actual constructor invoked on Child. Run it directly, which means, start with the first line, which neccessarily is either a this() or a super() invocation.
Evaluate the entire line, notably, evaluate all expressions passed as arguments. Even if those are themselves invocations of other methods. But, javac will do some minor effort to try to prevent you from accessing your fields (because those are all uninitialized! I haven't mentioned initializers yet!!).
Yeah, really. This means this:
public class Example {
private final long x = System.currentTimeMillis();
public Example() {
super(x); // x will be .... 0
// how's that for 'final'?
}
}
This will either end up invoking the first line of some other constructor of yours (which is itself also either a this() or a super() call). Either we never get out of this forest and a stack overflow error aborts our attempt to create this object (because we have a loop of constructors that endlessly invoke each other), or, at some point, we run into a super() call, which means we now go to our parent class and repeat this entire song and dance routine once more.
We keep going, all the way to java.lang.Object, which by way of hardcoding, has no this() or super() call at all and is the only one that does.
Then, we stop first. Now the job is to run the rest of the code in the constructor of j.l.Object, but first, we run Object's initializer.
Then, object's constructor runs all the rest of the code in it.
Then, Parent's initializer is run. And then the rest of the parent constructor that was used. and if parent has been shifting sideways (this() invokes in its constructors), those are all run in reverse order as normal in method invocations.
We finally end up at Child; its initializer runs, then the constructor(s) run in order, and finally we're done.
Show me!
class Parent {
/* some utility methods so we can run this stuff */
static int print(String in) {
System.out.println("#" + in);
return 0;
// we use this to observe the flow.
// as this is a static method it has no bearing on constructor calls.
}
public static void main(String[] args) {
new Child(1, 2);
}
/* actual relevant code follows */
Parent(int arg) {
print("Parent-ctr");
print("the result of getNow: " + getNow());
}
int y = print("Parent-init");
long getNow() { return 10; }
}
class Child extends Parent {
Child(int a, int b) {
this(print("Child-ctr1-firstline"));
print("Child-ctr1-secondline");
}
int x = print("Child-init");
Child(int a) {
super(print("Child-ctr2-firstline"));
print("Child-ctr2-secondline");
}
final long now = System.currentTimeMillis();
#Override long getNow() { return now; }
}
and now for the great puzzler. Apply the above rules and try to figure out what this will print.
#Child-ctr1-firstline
#Child-ctr2-firstline
#Parent-init
#Parent-ctr
#the result of getNow: 0
#Child-init
#Child-ctr2-secondline
#Child-ctr1-secondline
Constructor execution ordering is effectively: the first line goes first, and the rest goes last.
a final field was 0, even though it seems like it should never be 0.
You always end up running your parent's constructor.
--
*) You can use them for locks or sentinel pointer values. Let's say 'mostly useless'.
**) You can hack a class file so that it describes a class without a parent class (not even j.l.Object); that's how java.lang.Object's class file works. But you can't make javac make this, you'd have to hack it together, and such a thing would be quite crazy and has no real useful purpose.
In inheritance, the construction of a child object depends on at least one parent constructor.
Calling the super () method is not mandatory. By default, Java will call the parent constructor without argument except if you precise a custom constructor.
Here an example
Mother
public class Mother {
int a;
public Mother() {
System.out.println("Mother without argument");
a = 1;
}
public Mother(int a) {
System.out.println("Mother with argument");
this.a = a;
}
}
child
public class Child extends Mother {
public Child() {
System.out.println("Child without argument");
}
public Child(int a) {
super(a);
System.out.println("Child with argument");
}
}
If you do this :
Child c1 = new Child();
you will get :
Mother without argument
Child without argument
If you do this :
Child c1 = new Child(a);
You will get :
Mother with argument
Child with argument
But if you change the second child constructor to and remove the super(arg) the parent constructor without argument will be called :
public Child(int a) {
// super(a);
System.out.println("Child with argument");
}
You will get :
Mother without argument
Child with argument
May be this course for beginners can help you Coursera java inheritance
I am trying to pass values from my private static void main(...) into a class that has an array stack initialized in the constructor. I was wondering how to take the values I assign to a variable in the main() and push that value onto the array stack within this innerClass?
I know that the array stack works, I have implemented this class before without a problem, but I was only using the arrayStack() I had created and a main(). The addition of the third class is confusing me.
Without getting too deep in my code, I was hopping someone could explain (or point me to some resources) to me how to pass arguments to a stack that is initialized in a constructor, with arguments from the main() method of a different class (same package)?
Example of where I'm trying to get values to:
package program2;
public class Exec {
public Exec(DStack ds) {
/*I have initilized an arrayStack to hold doubles (i.e. DStack).
* I can use ds.push()/pop()/top() etc.
* I cannot take the value from Calculator.java and push that value
* here, which is what I need help understanding?
* */
ds.push(Calculator.i); //I would expect an error here, or the value stored in
//Calculator.i to be added to the stack. Instead program
//terminates.
}
}
Where I would like to take the values from:
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
i=9; //I'm expecting that by using Calculator.i in the Exec class that
//I should be able to push 'i' onto the stack.
}
}
This question goes along with a question and answer I was able to get working yesterday here: Get answer from user input and pass to another class. There are three differences, one, I am no longer selecting an answer from the menu and performing an action. Two, I would like know how to get items on a stack versus comparing the String in a series of if/else statements. Lastly, I would like to know a little more detail about the nuts and bolts of this action.
You seem to completely misunderstand how an application works. When you launch your program, java executes your main method. All its instructions are executed in sequence until the end of the method is reached. If you haven't started any other thread from this method, when the last instruction in the main method has been executed, the program terminates.
In this case, the main method contains only one instruction:
i = 9;
So this instruction is executed, and since it's the last one, the program terminates. You don't even reference the Exec class anywhere, so this class isn't even loaded by the JVM.
If you want to use the Exec class, then you have to do something with is somewhere in the program. For example, you could do
i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack);
Note that storing something in a public static variable in order for some other object to be able to get this value is a very poor form of parameter passing. If an Exec object needs a value to work, then it should be an argument of its constructor:
public Exec(DStack ds, double value) {
ds.push(value);
}
and in the main method, you would use a local variable and not a public static variable:
double i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack, i);
If I understand your question correctly, you should create an instance of the Exec class. You can also create an instance of DStack within your program and pass it the Exec constructor after pushing the double value onto the stack.
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
DStack dStack = new DStack();
dStrack.push(i);
Exec exec = new Exec(dStack);
}
}
I think you are confusing the concept of class vs. instance. You don't pass values to classes, you pass values to instances (static fields are sometimes called class variables and can make things confusing, but ignore that for now).
In a nutshell, a class is the code for that class you wrote. An instance is the actual thing that was spawned from that definition of class and actually does stuff. So the number one trick is to "instanciate" your class and create an instance. Then you pass whatever values you want to pass it like below:
class Foo {
public static main(String[] args) {
Bar bar = new Bar(); // <-- now you have an instance called bar
bar.arrayStack.push(args[0]); // <-- Now it's passed!
}
class Bar {
ArrayStack arrayStack;
Bar(){
arrayStack = new ArrayStack();
}
}
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 :)
This is a strange one, am wondering if this is by design or a compiler bug. Am using Sun Java 6 on a PC, but also seen with Sun Java 5 on a linux box.
Suppose I have a file on disk containing a serialized class. I then add a final field to the class and declare and initialize the field in one statement:
public final int newField = 2;
If I read in an object that was serialized before this field was added, this new field is given a default value of 0, which is correct. However, the compiler replaces occurrences of the field by the constant "2". OTOH, if I instead initialize the new field inside of a constructor:
Data (int d) {
this.oldField = d;
this.newField = 2;
}
then the field does not get optimized away and everything works as expected.
More explicitly, here is my Main class:
import java.io.*;
public class Main {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream ("Data.txt");
ObjectInputStream ois = new ObjectInputStream (fis);
Data d = (Data)ois.readObject();
ois.close();
fis.close();
d.print();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
and here is the Data class:
import java.io.*;
public class Data implements Serializable {
private static final long serialVersionUID = 1;
private int oldField;
private final int newField = 2;
Data(int d) {
this.oldField= d;
}
public void print() { {
System.out.println(this.oldField + " " + this.newField);
}
}
So my Data.txt file has a serialized instance of the original class with just "oldField = 1". So the expected output of running this is
1 0
but instead I get
1 2
whereas if I move the initialization into the constructor the output is correct.
Is this expected behaviour? My feeling is that the compiler should not be optimizing away fields in serialized classes, precisely for this reason. Perhaps that is asking too much. Thanks!
This is by design. If a variable is declared as final, has a primitive type and an initializer which is a constant expressions, then it is a "constant variable". This alters the semantics of initialization among other things. Specifically, the expression value is evaluated at compile time, and then embedded into the code.
Refer to JLS 4.12.4 for details.
When you put the initialization into the constructor, the variable is no longer a "constant variable" and normal initialization occurs.
By the way, I would have thought that a final variable having a different value than what the initializer said was a bad thing, not a good thing. To me, that would be highly unintuitive. At any rate, relying on this kind of behaviour does not strike me as good practice.
It's not clear why you think this is a problem. The compiler is doing exactly what it should do. The class definition says that the final field's value is 2, and that is exactly what you're getting.
The underlying reason is that when the final variable's value is declared in the initializer, the compiler knows its value immediately, so it is able to substitute the actual value as a literal wherever you use the variable. When you initialized it in constructor code, it couldn't see the value so easily so it doesn't do that optimization. It is still free to do so if it can.
In the language of the JLS #4.12.4, this is a 'constant variable', and JLS #13.1 says 'References to fields that are constant variables (ยง4.12.4) are resolved at compile time to the constant value that is denoted', which is exactly what is happening here.
My feeling is that the compiler should not be optimizing away fields
in serialized classes
Why should the compiler have different rules for serialized classes?
The usage of final variable always provokes compiler optimization. Its doing what it supposed to do.
What purpose does it serve?
Just read an example in a book where the author has done so.
int numOfGuesses=0;
The automatic assignment to zero only applies to members, not to local variables. If it is a local variable and the = 0 is omitted then that variable has no value, not even zero. Attempting to use the value before it is assigned will result in a compile error. For example this code attempts to use an uninitialized local variable:
public class Program
{
public static void main(String[] args)
{
int numOfGuesses; // local variable
System.out.println(numOfGuesses);
}
}
and produces this compile error:
Program.java:6: variable numOfGuesses might not have been initialized
System.out.println(numOfGuesses);
Whereas this code using a member works and outputs zero:
public class Program
{
int numOfGuesses; // member variable
public void run()
{
System.out.println(numOfGuesses);
}
public static void main(String[] args)
{
new Program().run();
}
}
For members I tend to assign to zero explicilty if my code uses the fact that the initial zalue is zero, and omit the assignment if my code doesn't use the initial value (for example if it the value is assigned in the constructor or elsewhere). The result is the same either way, so it's just a style issue.
It's more explicit; some people like. Note that this applies only to fields -- local variables need to be initialized; there are no defaults.
The Java compilation and runtime differ.
When running the program, all classes are loaded with class loaders and they do the following:
This is done when class is used for the first time. Their execute order is defined by their order in the code.
run static blocks
static{
//do something here
}
initialize static variables
public static int number;
This will be initialized to zero 0;
The next group of initializations done is when creating an object.Their execute order is defined by their order in the code.
run non-static block
{
// do something here
}
initialize non-static(instance) variables
public int instance_number;
And this is when and why there is default initialization!
This is not true for methods because they don't have similar mechanism as classes.
So basically this means that you will have to initialize EXPLICITLY each method variable.enter code here