Just wondering why static is always the one that will print out first rather than a method.
Code:
public class TestMe {
static {
System.out.println("D");
}
{
System.out.println("B");
}
public void printMe() {
System.out.println("Z");
}
public static void main(String []args) {
new TestMe().printMe();
}
}
Output:
D
B
Z
static blocks are executed when a class is first initialized (initialization of a class happens once it is loaded ) so they execute earlier than instance level blocks / methods (executed after creating an object)
You have two types of initializer block in your class
one is static initializer which is executed by the time the class is initialized
8.7. Static Initializers
A static initializer declared in a class is executed when the class is initialized
8.6. Instance Initializers
two is the Instance Initializers which is executed when instance of the class is already create
An instance initializer declared in a class is executed when an instance of the class is created
Those are from JLS documentation
So static initializer will be called directly when class is initialized vs Instance Initializers that is called when instance of that class is already created thus static initializer is executed first.
Because static blocks are executed when the class is loaded.
because that gets executed when class initializes it self
Also See
doc: Initializing Fields
Related
I know this is reference variable which holds the reference for object and static method loads when the class is first accessed by class loader, either to create an instance, or to access a static method or field.
Why its not allowed for this but for instance itself? For e.g.
Class A{
public static void main(String... args){
this.method(); //not allowed
new A().method(); //allowed, how?
}
void method(){
System.out.println("Class A");
}
}
this.method(); //not allowed
You have no instance this in static context so you can't invoke method.
new A().method(); //allowed, how?
You have instance created by new operator so that you can invoke a method.
To invoke a method without having a real instance you have to declare it as static. i.e.:
static void method(){
System.out.println(“Class A”);
}
this will work when calling just method() and via instance:
public class A {
public static void main(String[] argv) {
method(); //works because method is static
new A().method(); //still ok, we can call static method using an instance
this.method(); //not allowed, there is no 'this' in static context
}
static void method(){
System.out.println("Class A");
}
}
static variables and instance variables follow the initialization order you mention when they are initialized in their declarations. Also static initializer blocks follow that order.
Methods (including constructors) on the other hand need no initialization at runtime. They are fully defined at compile-time and therefore exist and can be called as soon as the class is loaded, also before the initialization is complete. Therefore there is no problem in your main method instantiating the class (calling the default constructor) and calling a method that is declared later, as method is declared below main.
In addition, the main method is also only executed after any static initialization is complete.
After going through Java documentation I understand that a field declared with 'static' keyword is class variable (or static field) and similarly when using 'static' during method declaration, is a static method (or class method). Class variable and Class methods are reference by class name itself.
Read this and this topics however could not understand following sentences from Java documentation.
What does it mean when it says.....
Not all combinations of instance and class variables and methods are allowed:
Instance methods can access instance variables and instance methods
directly.
Instance methods can access class variables and class methods
directly.
Class methods can access class variables and class methods directly.
The Java doc clearly explains about Class variables and Class methods but above 3 points are confusing to me.
Example Execution
1.Instance methods can access instance variables and instance methods directly.
Some Info:
Instance method are methods which require an object of its class to be
created before it can be called.To invoke a instance method, we have to
create an Object of the class in within which it defined.
Instance variables are declared in a class, but outside a method, constructor
or any block.
class Example1 {
int a = 100; // instance variable
public void printData() { // this an instance method called using an object of class Example1
getData(); // accessing another instance method directly without any object
}
public void getData() {
System.out.println(a); // accessing instance variable 'a' directly without any object
}
}
public class InstanceDemo {
public static void main(String[] args) {
Example1 obj1 = new Example1();
obj1.printData(); // will print 100
}
}
2.Instance methods can access class variables and class methods directly.
Class variables also known as static variables are declared with the static
keyword in a class, but outside a method, constructor or a block.
class Example2 {
static int a = 20; // 'static' / class variable
public void printData() { // instance method
setData(); // accessing class method directly
System.out.println(a); // accessing class variable directly
}
public static void setData() { // class method 'static'
a = 200; // setting value of class variable 'a'
}
}
public class InstanceDemo {
public static void main(String[] args) {
Example2 obj2 = new Example2();
obj2.printData(); // will print 200
}
}
3.Class methods can access class variables and class methods directly.
Static methods are the methods in Java that can be called without creating an
object of class. They are referenced by the class name itself or reference to
the Object of that class.
Memory Allocation: They are stored in Permanent Generation space of heap as
they are associated to the class in which they reside not to the objects of
that class. But their local variables and the passed argument(s) to them are
stored in the stack. Since they belong to the class so they can be called to
without creating the object of the class.
class Example3 {
static int a = 300;
public static void printData() {
getData(); // accessing class method
}
public static void getData() {
System.out.println(a); // accessing class variable 'a'
}
}
public class InstanceDemo {
public static void main(String[] args) {
//calling class method : class method are called using class name.
Example3.printData(); // will print 300
}
}
I think you just need to practice programming, so you can experience how the language works. Understanding the quirks of static access is one of the hardest things to grasp initially. Static members are generally geared towards providing class utility.
An instance method gets a pointer to the instance it's operating on, on the stack, therefore it can access the members of the instance. A static method isn't associated with any particular instance. There's no 'this' reference, thus it can't access instance members.
Instance methods can access instance variables and instance methods
directly.
This means a method that doesn't have a static modifier i.e. an instance method can access any non-static variable as well as call any non-static method.
Instance methods can access class variables and class methods
directly.
This means a method that doesn't have a static modifier i.e. an instance method can access a static variable or call a method with the static modifier.
Class methods can access class variables and class methods directly.
This means a static method can access any static variable as well as call any other method that has a static modifier.
To put it simply, an instance method i.e. a method without the static modifier can access both a static variable as well as a non-static variable and it can also directly call a static method and a non-static method.
On the other hand, a static method can only access static variables and call static methods. it cannot, however, access an instance variable or instance methods directly without an object.
I have written the following code and created object for the super class.
class SuperClass{
static int a=2;
static int b(){
return 2;
}
int c(){
return 2;
}
SuperClass(){
System.out.println("Super");
}
static {
System.out.println("super");
}
}
public class Sub extends SuperClass{
Sub(){
System.out.println("Sub");
}
static {
System.out.println("sub");
}
static int b(){
return 3;
}
int c(){
return 3;
}
public static void main(String ax[]){
SuperClass f =new SuperClass();
System.out.println(f.c());
System.out.print(SuperClass.b());
}
}
When I checked the output, it is as follows:
super
sub
Super
2
2
I know that static block is executed only when object of the class is initialized or any static reference is made. But here, i did not make any of these to Sub class. then why do i see "sub" i.e. sub class' static block output?
I know that static block is executed only when object of the class is initialized or any static reference is made. But here, i did not make any of these to Sub class.
Your code doesn't, but in order for that main to run, Sub has to be loaded. So the static initializer for it is run.
E.g., I'm assuming you ran it like this:
java Sub
The java tool has to load Sub to call Sub.main. That's the static reference (access, really) causing the static initializer to run. (If you ran it in an IDE, the IDE will do the java tool part, but the result is the same.)
So here's what happened:
java triggers load of Sub
JVM has to load SuperClass in order to load Sub
So we see their static initializers run, in order (SuperClass, then Sub):
super
sub
java tool calls main
Code in main calls new SuperClass:
Super
Code in main calls f.c()
2
Code in main calls SuperClass.b:
2
As Holger helpfully points out, this is covered by the JVM specification in §5.5 - Initialization and the related §5.2 - Java Virtual Machine Startup:
Initialization of a class or interface consists of executing its class or interface initialization method (§2.9).
A class or interface C may be initialized only as a result of:
...
If C is a class, the initialization of one of its subclasses.
If C is a class, its designation as the initial class at Java Virtual Machine startup (§5.2).
That second-to-last bullet point covers SuperClass, and the last bullet point covers Sub.
Because your main() method is a member of Sub, that class needs to be loaded for your program to run.
In calling main, all the static initialisers are called, first in the super class, then the sub class.
That explains the output you observe.
static blocks are run when the class is loaded. usually that is because you call a constructor or static member. in this case, it is because you executed the main method (a static member).
side notes:
another edge case is calling Class.forName(className) to load a class.
you may also notice that the base class is loaded before the subclass.
The following Java code does not invoke the static initializer of class B. Why?
Code:
class A
{
static
{
System.out.println("A static init");
}
public static void f()
{
System.out.println("f() called");
}
}
class B extends A
{
static
{
System.out.println("B static init");
}
}
public class App
{
public static void main( String[] args)
{
B.f(); //invokestatic #16 // Method com/db/test/B.f:()V
}
}
Program output:
A static init
f() called
Tested on JDK 1.8.0_25
There is no such thing as "static constructor". It's a static initialization block, and it is only executed when the class is initialized. Since you are calling a static method of class A (even though you are referring to it via class B), there is no need to initialize class B. Calling B.f(); is the same as calling A.f();.
The static initialization block of class B will be executed if you create an instance of class B or access a static member/method of class B.
Here are the only conditions that trigger class initialization (JLS 12.4.1):
A class or interface type T will be initialized immediately before the
first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
Since only class A defines the method f(), class B is loaded but not initialized.
You could use java -verbose:class MyClassName to check this.
On a jdk6 / jdk 8 machine, this will be printed.
[Loaded App from file:/C:/XXXX/]
[Loaded A from file:/C:/XXXXXX]
[Loaded B from file://C:/XXXXXXX]
A static init
f() called
Class B will be initialized lazily but loaded greedily (since it is being referred).
Change your code to A.f(). Then you will see that B is not loaded.
[Loaded App from file:/C:/XXXX/]
[Loaded A from file:/C:/XXXXX]
A static init
f() called
Note : Class loading and initialization are 2 different things. Check documentation for Class.forName() for details.
I naturally can have classes inside any class, so in my main method. I also can access to its methods and its attributes.
But this code isn't working. I know main to be static, so is it something like:
The main method runs and is it the one constructing any class, even the one who contains it.
Then, main should start, construct the class who contains it, and then any class or method inside.
package holamundo;
public class HolaMundo {
public class AnotherClass {
// Class body
}
public void method () {
// Code
}
public static void main(String[] args) {
AnotherClass a = new AnotherClass();
method();
}
So doing:
package holamundo;
public class HolaMundo {
public static class AnotherClass {
// Class body
}
public static void method () {
// Code
}
public static void main(String[] args) {
AnotherClass a = new AnotherClass();
method();
}
We could say main is running first, among the AnotherClass and method definitions?
I tried writing this up with my own words, but the SCJP 6 book does it way better, so here it goes:
A static nested class is simply a class that's a static member of the
enclosing class
Perhaps to better understand, here's some code:
public class HolaMundo {
public static class AnotherClass {
public void hello(){
System.out.println("Hello");
}
public static void hola(){
System.out.println("Hola");
}
}
public static void main(String[] args) {
HolaMundo.AnotherClass.hola();
HolaMundo.AnotherClass holaAnother = new HolaMundo.AnotherClass();
holaAnother.hello();
}
}
Note that the above code in the main() method will continue to work if you remove the occurrences of HolaMundo..
If you're confused, here's more from the book:
The class itself isn't really "static"; there's no such thing as a
static class. The static modifier in this case says that the nested
class is a static member of the outer class. That means it can be
accessed, as with other static members, without having an instance of
the outer class.
A static method (like main()), doesn't belong (and also cannot access) to any particular instance of any class.
This means that a static method can create new instances of any class it has access to, even if it happens to be an instance of the class that declared said method in the first place.
Now, since in this case, main(), AnotherClass and method() are all static members of HolaMundo, then yes, this means that they all "run together".
More specifically, they are loaded when the class is first loaded by the JVM (aka at Class Loading time).
In Java, non-static nested classes have an implicit reference to an instance of the container class and so cannot be utilized in static contexts (like the main method) since there is no instance to reference.