I am trying to use static blocks like this:
I have a base class called Base.java
public class Base {
static public int myVar;
}
And a derived class Derived.java:
public class Derived extends Base {
static
{
Base.myVar = 10;
}
}
My main function is like this:
public static void main(String[] args) {
System.out.println(Derived.myVar);
System.out.println(Base.myVar);
}
This prints the out put as 0 0 where as I expected 10 0. Can somebody explain this behavior? Also, if I want my derived classes to set the values for a static variable how can I achieve that?
As I understand. You don't call any Derived properties (myVar belongs to Base, not to Derived). And java is not running static block from Derived. If you add some static field to Derived and access it, then java executes all static blocks.
class Base {
static public int myVar;
}
class Derived extends Base {
static public int myVar2;
static
{
Base.myVar = 10;
}
}
public class Main {
public static void main( String[] args ) throws Exception {
System.out.println(Derived.myVar2);
System.out.println(Base.myVar);
}
}
From java specification, when class is initialized (and static block got executed):
12.4.1 When Initialization Occurs 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.
Static initializer-blocks aren't run until the class is initialized. See Java Language Specification paragraphs 8.7 (Static initializers) and 12.4.1 (When initialization occurs):
A static initializer declared in a class is executed when the class is
initialized (§12.4.2). Together with any field initializers for class
variables (§8.3.2), static initializers may be used to initialize the
class variables of the class.
Here's a similar example straight out of JLS 12.4.1:
class Super {
static int taxi = 1729;
}
class Sub extends Super {
static { System.out.print("Sub "); }
}
class Test {
public static void main(String[] args) {
System.out.println(Sub.taxi);
}
}
This program prints only:
1729
because the class Sub is never initialized; the reference to Sub.taxi
is a reference to a field actually declared in class Super and does
not trigger initialization of the class Sub.
There is a single copy of myVar and both parent and child class will share the same.
Untill and unless child class get initilized.
When we do
class Base {
public static int myVar = 0;
static {
System.out.println("Base");
}
}
class Derived extends Base {
static {
System.out.println("Derived");
Base.myVar = 9;
}
}
public class StaticBlock {
public static void main(String[] args) {
System.out.println(Base.myVar);
System.out.println(Derived.myVar);
}
}
The Output will be
Base
0
0
That means derived class's static block not executing..!!
Here is the link to the Java Specification - section 8.7 talks about static initializers. It gives good details about how they should function and the order in which they get called. http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.7
Related
I am new to java. I am currently reading some articles about static variables. When I am trying to implement my learnings, I encountered a problem about static variables. Here is the first code sample.
public class Human {
// in Human.java
public static int population = 0;
public static void main(String[] argv) {
System.out.println(population);
}
}
This code works fine and the outcome is 0.
But for the following code, I wasn't allow to compile it.
public class Human {
// in Human.java
public class Charlie extends Human {
public static int number = 0;
}
public static void main(String[] argv) {
System.out.println(new Human().new Charlie().number);
}
}
An error occurred: The field number cannot be declared static in a non-static inner type, unless initialized with a constant expression
I am confused with this situation. For the first code sample, my Human class is non-static and I was allowed to declare a static variable inside it. How come I can't do the same for my second code sample.
Any help would be appreciated. Thanks. :)
Try with public static final int number = 0; because Java does not let you define non-final static fields inside function-local inner classes. Only top-level classes and static nested classes are allowed to have non-final static fields.
From the JLS section 8.1.3:
Inner classes may not declare static members, unless they are constant variables (§4.12.4), or a compile-time error occurs.
Other way to make inner class static and access it
public class Human {
// in Human.java
public static class Charlie extends Human {
public static int number = 0;
}
public static void main(String[] argv) {
System.out.println(new Human.Charlie().number);
}
}
What is the real time utility of non static fields inside static inner class?
Also, how instance creation of static inner class works :
class Outer {
static class Inner {
public final String text = "Inner";
}
}
public class A {
public static void main(String[] args) {
System.out.println(new Outer.Inner().text);
}
}
Just consider static inner class as normal class (just placed inside class instead package) and consider non-static inner class something like generic, based on instance of outer class.
Please see the below code --
public interface TestInterface {
public static String NON_CONST_B = "" ;
}
public class Implemented implements TestInterface {
public static String NON_CONST_C = "" ;
}
public class AutoFinal {
public static String NON_CONST_A = "" ;
public static void main(String args[]) {
TestInterface.NON_CONST_B = "hello-b" ;
Implemented.NON_CONST_C = "hello-c";
AutoFinal.NON_CONST_A = "hello-a" ;
Implemented obj = new Implemented();
}
}
However, the compiler complains that TestInterface.NON_CONST_B is final --
AutoFinal.java:6: error: cannot assign a value to final variable NON_CONST_B
TestInterface.NON_CONST_B = "hello-b" ;
^
1 error
why ?
Regarding:
public interface TestInterface {
public static String NON_CONST_B = "" ;
}
public class AutoFinal {
public static void main(String args[]) {
TestInterface.NON_CONST_B = "hello-b" ;
// ....
}
}
However, the compiler complains that TestInterface.NON_CONST_B is final --
But it in fact is final whether you explicitly declare it to be or not since it is declared in an interface. You can't have non-final variables (non-constants) in an interface. It's also public and static whether or not it has been explicitly declared as such.
Per the JLS 9.3 Interface Field (Constant) Declarations:
Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted to redundantly specify any or all of these modifiers for such fields.
In java, all variables was declared in Interfacel are public static final default
Variables declared in interface are always public static final by default in java. Interface variables are static because Java interfaces cannot be instantiated in their own right; the value of the variable must be assigned in a static context in which no instance exists. The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.
As all answers saying that by default all the variables declared in Interface are static final variables.
FYI, you can not declare a static method in interface. You can find the reason in this SO question.
however, you can declare Inner Class in an interface that can contain static methods and non static and non final variables.
There is error with this code
public class DoIt {
public static void main(String[] args) {
final class Apple {
public static String place = "doIt";
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println(Constants.place);
}
});
thread.start();
}
}
Error- The field name cannot be declared static in a non-static inner type, unless initialized with a constant expression
The problem is that the field is non-final: only final fields are allowed to be static in the context of non-static inner classes:
final class Apple {
// This should compile
public static final String place = "doIt";
}
JLS 8.1.3
Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.
final class Apple {
public static final String place = "doIt"; // This is good
}
Inner classes are instance classes. The point of using a static member is to call it directly without having to instantiate. So it wouldn't make much sense to allow static members inside an inner class. However, you can declare them as static-
static final class Apple {
public static String place = "doIt";
}
final class Apple { {
// you can't define non final field inside the final class
// you have to use final with static
}
you can use
public final static String place = "doIt";
According to the Java tutorials,
A local class can have static members provided that they are constant variables.
So you would have to declare it final:
public static void main(String[] args) {
final class Apple {
public static final String place = "doIt";
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("");
}
});
thread.start();
}
Before i reason out the error terminology is as follows
Terminology: Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes(more specifically local inner class).
Now in your case you have local inner class. According to the docs Because an inner class is associated with an instance, it cannot define any static members itself.
Objects that are instances of an inner class exist within an instance of the outer class and static members are loaded when classes are loaded whereas in your case you cannot access Apple class at the time of class loading to load place variable.
Also A local class can have static members provided that they are constant variables.
so you can do public static final String place = "doIt";
public class tt {
static{
System.out.println("class tt");
}
}
It the first time ive come across it and im wondering what it is and what it's used for
It is the static initialiser of the class. When the class is loaded, the static initialiser is run. It is like the constructor, but for the class rather than for individual objects.
Multiple static initialisers can appear in a class, as well as direct initialisers for static variables. These will be combined into one initialiser in the order in which they are declared. For example, the following will print "foo" to stdout whenever the class is loaded (usually once per application).
public class Foo {
static String a;
static {
a = "foo";
}
static String b = a;
static {
System.println(b);
}
}
Its initilizer block
A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:
static {
// whatever code is needed for initialization goes here
}
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
There is an alternative to static blocks —you can write a private static method:
class Whatever {
public static varType myVar = initializeClassVariable();
private static varType initializeClassVariable() {
//initialization code goes here
}
}
The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.
Resource
here is the static initializer tutorial http://download.oracle.com/javase/tutorial/java/javaOO/initial.html
It runs when the class is loaded before the initialization.
public class A {
static {
System.out.println("A from static initializer"); // first
}
public A(){
System.out.println("A"); // second
}
public static void main(String[] args){
new A();
}
}
It is a static initializer. The code inside that block runs when the JVM loads the class, which is immediately before the first time the program needs to do anything with that class (e.g. look up a static field, call a static method, instantiate an object,...).
It's a static initializer block. It will be executed once when the class is first loaded, along with static field initializers like this:
private static int staticField = someMethod();
The difference is that an initializer block can contain control flow structures like try/catch blocks.