we know that a static block in java is resovled while compliling, not at runtime. Hence again We know that a static inner class is instantiated during the first call to the nested class.
Now suppose the nested class is having a static block. So, in that case can we say that static block inside the nested class will be resolved when the first attempt to access that nested class is made?
Sample code:
public class A
{
public static class B
{
static A a;
static
{
a=new A();
}
public static A getA()
{
return a;
}
}
}
Now I am accessing as:
A a= A.b.getInstance();
I hope at that point only static block in B will be executed and not before that.
This should answer your question:
public class Test {
public Test() {
System.out.println("Test instantiated");
}
public static class Inner {
static {
System.out.println("Static block executed");
}
public Inner() {
System.out.println("Test.Inner instantiated");
}
}
}
When calling:
Test test = new Test();
Test.Inner inner = new Test.Inner();
We get:
Test instantiated
Static block executed
Test.Inner instantiated
static block in java is resovled while compliling
No it isn't.
All static code is resolved once by the classloader, when loaded/initalized.
From jls Compile time error will happen from static blocks only when
If a static initializer cannot complete normally.
If a return statement appears anywhere within a static initializer.
If the keyword this or the keyword super or any type variable declared outside the static initializer, appears anywhere within a static initializer.
static block will be executed when the class is initialized, so in your example, the static block inside your static class B will get executed first.
Related
As per java doc, static block is executed when the class is initialized.
Could anyone please tell me why static block is not executed when I run below code?
class A {
static {
System.out.println("Static Block");
}
}
public class Main {
public static void example1() {
Class<?> class1 = A.class;
System.out.println(class1);
}
public static void example2() {
try {
Class<?> class1 = Class.forName("ClassLoading_Interview_Example.ex1.A");
System.out.println(class1);
}catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
example1();
}
}
A class's static initialization normally happens immediately before
the first time one of the following events occur:
an instance of the class is created,
a static method of the class is invoked,
a static field of the class is assigned,
a non-constant static field is used, or [...]
You are currently not doing any of the above.
So, by replacing
Class<?> class1 = A.class;
System.out.println(class1);
with this for example
A object = new A();
will give you your result.
Referencing A.class will not resulting in executing A's static initializers, see here
Initialization of a class consists of executing its static
initializers and the initializers for static fields (class variables)
declared in the class.
And
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.
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).
I have one class Student which is
package org.ahmed;
public class Student {
public Student() {
// TODO Auto-generated constructor stub
System.out.println("Generated constructor");
}
static { // static block
System.out.println("Hello world static");
}
{ // insance block
System.out.println("Hello world non static");
}
}
and then
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("org.ahmed.Student"); // this line causing static block execution in Student class
// Student s; // this line doesn't execute the static block.
}
}
I understand by using Class.forClass() we can dynamically run any
class in runtime. But I have some question in other case regarding
static block.
If I use Class.forClass("org.ahmed.Student") in my main method, then it's
executing the static block of Student. But if I declare Student s in
main method its doesn't execute the static block. I thought
Class.forClass("ClassName") is same as declaring class with a variable
name.
There's a distinction between loading a class (JLS§5.3 and, I think, JLS§5.4) and initializing a class (JLS§5.5). By default, Class.forName does both, although there's an override you can use that lets you control whether to initialize the class.
Just declaring a Student variable doesn't initialize the class. In fact, even referring to Student.class doesn't initialize the class. You must do something to trigger initialization, such as something that uses the new, getstatic, putstatic, or invokestatic bytecode operations with the class (but see the link to §5.5 for details, there are other things that initialize the class).
So for instance, if you gave Student a public field:
public static String foo = "bar";
...and then in Main.main you did:
System.out.println(Student.foo);
...that would trigger initialization of the class.
When you use Class.forName("org.ahmed.Student") you actually force the JVM to load the class and invoke its static blocks. You can read more here.
From javadoc:
Invoking Class.forName(className) method is
equivalent to: Class.forName(className, true, currentLoader), where the second parameter specifies whether or not the class will be initialized.
So if you don't want to initialize the class, just call the method with initialize = false, e.g:
Class.forName("org.ahmed.Student", false, this.getClass().getClassLoader())}
Declaring the class references loads the class to JVM hence static block will be executed. i'm able to see static block execution on
Student s;
Example:
package com.snofty.test;
public class ClassLoading {
public ClassLoading(){
System.out.println("in constructor");
}
static {
System.out.println("in static block");
}
{
System.out.println("in instance block");
}
public static void main(String[] args) {
ClassLoading classLoading;
}
}
Class.forName()
it is used to load the class dynamically by passing the class name
for example
public void loadClass(String className){
Class.forName(className);
}
public class DataFactory {
private static DataFactory ourInstance = new DataFactory();
static {
System.out.println("static initialize");
}
private DataFactory() {
System.out.println("constructor");
}
public static void doNothing() {
System.out.println("inside doNothing");
}
}
public class App {
public static void main(String[] args) {
System.out.println("main start");
DataFactory.doNothing();
}
And After I run it, here is the printed sequence:
main start
constructor
static initialize
inside doNothing
Why calling DataFactory.doNothing() will trigger Constructor?
and why constructor is running before the static initializer?
When the class is initialized, it'll execute all of the static {...} and static field initializers, in the order they appear in the code (see JLS 12.4.2, and in particular step 9 in the list of steps there). In your example, there are two such initializers:
private static DataFactory ourInstance = new DataFactory();
The static {...} block
So, the first one happens first. It instantiate an object and assigns its reference to ourInstance. To instantiate the object, it needs to call the constructor, which it does (as you saw).
When that's done, the static block is executed, which prints "static initialize."
At this point, the class is initialized, and the method doNothing can finally be invoked.
It's invoking the constructor because you are creating an instance of DataFactory inside the same DataFactory; so it needs to call the constructor once in order to be able to instantiate it. Comment or delete the private static DataFactory ourInstance = new DataFactory(); line and the constructor call is not going to happens.
A static initializer is executed right after the class is initialized.
Sorry to tell that Rod_Algonquin is incomplete and Machina too. The right answer is that:
"Static Initialization Blocks run when the class is first loaded"
So, you are correct to ask "why the constructor is run before static?!".
How can? And there is a rule for initialization blocks (statics and instance).
The order in which initialization blocks appear in a class matters.
Just swap the order of your static initialization block to the static instantiation to see what happen:
public class DataFactory {
static { //// SWAPPED HERE
System.out.println("static initialize");
}
///// SWAPPED HERE
private static DataFactory ourInstance = new DataFactory();
private DataFactory() {
System.out.println("constructor");
}
public static void doNothing() {
System.out.println("inside doNothing");
}
}
OUTPUT:
main start
static initialize
constructor
inside doNothing
Your static field initialization calls the constructor.
In the end, the code that initializes the field "ourInstance" is also part of the static initializer.
So what is actually happening is:
public class DataFactory {
private static DataFactory ourInstance;
static {
outInstance = new DataFactory(); // 2
System.out.println("static initialize"); // 4
}
private DataFactory() {
System.out.println("constructor"); // 3
}
public static void doNothing() {
System.out.println("inside doNothing"); // 6
}
}
public class App {
public static void main(String[] args) {
System.out.println("main start"); // 0
DataFactory.doNothing(); // 1 (static init) and 5 (method call)
}
}
Here is the JLS documentation for the constructor:
Constructors are invoked by class instance creation expressions (§15.9)
And the JLS documentation for the static block:
A static initializer declared in a class is executed when the class is initialized (§12.4.2).
As you can see the constructor is first called when the class is initialized and then right after the constructor call then the static block is then called.
I'm unsure what this does, I haven't seen it before and can't find any information about it.
private static String[] names = { "A.ttf" };
private static Map<String, Font> cache = new ConcurrentHashMap<String, Font>(names.length);
static {
for (String name : names) {
cache.put(name, getFont(name));
}
}
That is not a static method but a static block.
Static blocks are executed first(in same order they are declared) when class gets loaded and usually used for initializing things.
in your case it puts all names in "names" to cache.
refer this or an answer on SO for more info
A block is denoted by {\\some code}. A placed static keyword denotes that it is a static block. static block is known as Static Initializers and non static block is known as Instance Initializers.
None of them can contain return statement.
The non-static block will be called every time you are creating a new instance and it will be called/executed just before the Constructor. The static block will be called/executed only once and it will be the first time your are accessing the class.
Example:
class A {
static{ // static
System.out.println("Static block of Class A");
}
{ // non-static
System.out.println("Non-Static block of a instance of Class A");
}
public A(){
System.out.println("Constructing object of type A");
}
}
public class StaticTest {
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
}
}
Output:
static block of Class A
Non-Static block of a instance of Class A
Constructing object of type A
Non-Static block of a instance of Class A
Constructing object of type A
I have few question about static in java
Can we have static block in non static class??If an object of
that(no-static) class is initialized in some other class,will the
static block get executed then??
If there is a static class having static block and variable( int a =
3) and main() method,and it is executed then will the variable
initialization take place first or static block execution?I know
that static block gets executed before the main() method.
1) No, you cant, try this
class Test1 {
class X {
static { <-- compile error: Cannot define static initializer in inner type Test1.X
}
}
...
X should be static.
Note: I assume we are talking about nested classes, because this is where static modifier is applicable for classes
2) it depends, see this
class Test1 {
static {
x = 3;
}
static int x = 2;
public static void main(String[] args) throws Exception {
System.out.println(x);
}
}
output
2
but now
class Test1 {
static int x = 2;
static {
x = 3;
}
public static void main(String[] args) throws Exception {
System.out.println(x);
}
}
output will be
3
Static initialization runs only ones during class loading, it happens always before any instance instantiation. Interestingly both static fields initialization and static init block code runs in the same bytecode function with the name <clinit>:
static <clinit>()V
L0
LINENUMBER 12 L0
ICONST_3
PUTSTATIC test/Test1.x : I
L1
LINENUMBER 15 L1
ICONST_2
PUTSTATIC test/Test1.x : I
RETURN
Please look here http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
It's called static initializer in the spec. This code will be executed when JVM loads the class. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
You can't use static code in nonstatic inner classes:
public class MyClass {
static {
System.out.println("static code from nonstatic class");
}
class In {
/* it will not compile
static {
}
*/
}
static class In2 {
static {
System.out.println("static code from static inner class");
}
}
public static void main(String[] args) {
MyClass c = new MyClass();
}
}
See Detailed Initialization Procedure in The Java® Language Specification for details about calling order. Simply the static blocks are executed in the order they appear in the source code.
Having a static class vs. a normal class does not affect what programming constructs you are allowed to use, but simply controls whether or not the class has access to instance fields/methods of the surrounding class.
Yes we can have a static block in a non-static class and it is loaded as soon as class loads in JVM
public class StaticDemo {
static{
System.out.println("already loaded");
}
public static void main(String [] args){
}
}
This outputs already loaded
For question 2, the answer can be found in the Java Language Specification §12.4.2, in particular step 9 of the "detailed initialization procedure":
Next, execute [...] the class variable initializers and static initializers of the class [...] in textual order, as though they were a single block.
In other words, the static {} blocks and the initializer expressions of static fields are executed in the order they appear in the source code - if the static block is before the field declaration then it will run first (and see the default value of the field, typically null or 0), if the static block is after the field declaration then it will run second (and will see the value assigned by the initializer expression).