Regarding static and final variable effect on class - java

If you execute this program you will get only the i value but not SIB, my question is when class loading into the memory SIB should execute and should give ooutput, but here I am getting only the i value? Then keep one method in class test then call that method from another class then you will get output of SIB, i method ( keep method also as static final)
class Test
{
static final int i =3;
static
{
System.out.println("SIB");
}
{
System.out.println("IIB");
}
}
class A1
{
public static void main(String[] args)
{
System.out.println(Test.i);
}
}

A static final variable is a compile-time constant and its value is copied into the other class referencing it. Therefore your class Test won't load and no initializers will be executed. When the variable is only static, then the class must be loaded to read the current value and your SIB block will be executed. The IIB block will be executed only when you instantiate Test with new Test().

Related

Is it possible to create object in a static block?

I am little bit confused about static block.if we talk about system.out.println method here system is a class,out is the reference variable that have the reference ID of printstream class that declares in a static block then how it is possible to create any object in a static block because a static block always executes at class loading time, while object is created at run time...
how i can make the difference b/w loading time and running time..
Static block
The static block is a static initializer (a class initializer). You can use it to initialize a class or to do some logic during class load. If you remove the static modifier the code block is an instance initializer.
For instance, with static initializers you can initialize a map with db data to be used later during object instantiation.
You can read this link that explains very well about it.
I find useful this quotation:
Static blocks are also called Static initialization blocks. 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. And dont forget, this code will be executed when JVM loads the class. JVM combines all these blocks into one single static block and then executes.
For example, this code:
public class StaticExample{
static {
System.out.println("This is first static block");
}
public StaticExample(){
System.out.println("This is constructor");
}
public static String staticString = "Static Variable";
static {
System.out.println("This is second static block and "
+ staticString);
}
public static void main(String[] args){
StaticExample statEx = new StaticExample();
StaticExample.staticMethod2();
}
static {
staticMethod();
System.out.println("This is third static block");
}
public static void staticMethod() {
System.out.println("This is static method");
}
public static void staticMethod2() {
System.out.println("This is static method2");
}
}
Generates this output:
This is first static block
This is second static block and Static Variable
This is static method
This is third static block
This is constructor
This is static method2
Static method (alternative to static block)
You can write a private static method to achieve the same, and an advantage of using private static methods is that they can be reused later if you need to reinitialize the class variable.
For instance:
class Whatever {
public static varType myVar = initializeClassVariable();
private static varType initializeClassVariable() {
// initialization code goes here
}
}

system.out.println statement outside any method in java

My question is can't we write an output statement outside the main in java? If I enclose it in { } braces then I don't get error, but if I directly write it, I get an error. why so?
public class abc
{
int a=3;
int b=0;
System.out.println("this statement gives error"); //Error!!
{System.out.println("this works fine");}
public static void main(String args[]) {
System.out.println("main");
abc t=new abc();
}
}
I tried writing it in main, it works. Why doesn't it work without a method?
When you enclose it in braces, you are putting it in an initializer block, which runs when the class is instantiated. No statements except variables declarations/initialization may take place outside of methods or initialization blocks in Java.
A Class can only have attributes or methods.
A class is the blueprint from which individual objects are created.
int a=3; // attributes
int b=0; // attributes
System.out.println("this statement gives error"); //Error!!
{System.out.println("this works fine");} // init block whenever an object is created.
// since it is inside { }
{...} is called an instance initializer . It runs in addition to the constructor each time an instance object is created .
static{...} is another type of block that is called Static Initializer it is when you add a static keyword before { } . This static initializer only runs when the class is first loaded.
So you can write code in these two block and class member functions.
Other than that the only place left is meant for the class data members declaration and initialization.
Basics/Fundamentals
Java Class contains only member functions and class variables and few other exceptions like instance initliazer, static blocks etc.
You can't just sprinkle executables(like System.out.println()) anywhere you wish inside Class.
Instance initliazer
{...} in Java is instance initializer which gets called whenever an object is created. Because it is instance initializer, it actually gets called before constructor.
You can write System.out.println() inside {...} or instance initializer.
Static block
static{...} is called static block in Java, which contains lines of code which gets called ONLY ONCE when the class is loaded by JVM.
Again, You can write System.out.println() inside {...} or static block.
Simple executable example below
public class JavaExample {
public JavaExample (String name){
System.out.println("Inside constructor" + name);
}
{
System.out.println("Inside instance initializer");
}
static{
System.out.println("Inside static block");
}
//System.out.println("Will give error"); //ERROR
public static void main(String[] args) {
JavaExample obj1 = new JavaExample ("obj1");
JavaExample obj2 = new JavaExample ("obj2");
System.out.println("Inside the public static void main");
}
}
Output
> Inside static block
> Inside instance initializer
> Inside constructor: obj1
> Inside instance initializer
> Inside constructor: obj2
> Inside the public static void main
Please note the order of execution.
Static block (gets called once when JVM loads Class, hence first of all)
Instance initializer (before the call of any object instantiation)
Constructor (during object creation/initialization)

how to load a java class along with static initializations before they are used?

I need to load some classes along with their respective static initializations, for example, in a factory method implementation.
If I just make reference to the class using the below syntax, the JVM does not run the static initialization part. Actually, does the JVM even load the classes?
Class<Shape> shapeClass = Shape.class;
or
Shape s = null;
But with class.forname() it does execute static initializations.
Class.forname("Shape");
The question is if this is the only way to do load a java class along with static initializations? Or are there other ways? Any significant performance penalties for using class.forname()?
From Class.forName(String className) API: Invoking this method is equivalent to: Class.forName(className, true, currentLoader).
The second argument = true means initialize class, and initialize class means run static initializers
This is a test to check
package test;
class Test2 {
static {
System.out.println("static init");
}
}
public class Test1 {
public static void main(String[] args) throws Exception {
Class.forName("test.Test2");
}
}
output
static init
but if you load Test2 with
Class.forName("test.Test2", false, ClassLoader.getSystemClassLoader());
there will be no output. You can also use this test to see that Test.class.getName() does not load the class either.
The simplest way to make it load is to add an empty static method and call it:
class Test2 {
public static void load() {
}
...
Test2.load();
When you load/resolve a class, the static initializers are executed in the order they are defined. It shouldn't matter how you load them, reflection or not. That is, unless you're meaning some other sort of initialization?

Static block is never run

I have a utility class that looks like this:
public final class MyUtils {
public static final List<String> MY_VALUES = new ArrayList<String>();
{
MY_VALUES.add("foo");
MY_VALUES.add("bar");
}
}
I call this from another class just like this:
MyUtils.MY_VALUES
If I do so, the list is empty and if I debug I see the static block is never run.
As I understand from the answers to When does static class initialization happen? and How to force a class to be initialised? the block should run when a static field of the class is assigned, which I do right away. I also tried making the variable non-final to fulfill the condition "a non-constant static field is used".
I could use an init method as also sugested in the two other questions and als in Why doesn't my static block of code execute? but I would still like to understand why it isn't working in the first place although I seem to have fulfilled the conditions from the language specification.
You have to add the static keyword in front of your block in order to make it static:
public final class MyUtils {
public static final List<String> MY_VALUES = new ArrayList<String>();
static {
MY_VALUES.add("foo");
MY_VALUES.add("bar");
}
}
A initialization block gets called everytime the class is constructed.
A static initialization block gets called only once at the start of your program.

Static Initializers And Static Methods In Java

Does calling a static method on a class in Java trigger the static initalization blocks to get executed?
Empirically, I'd say no. I have something like this:
public class Country {
static {
init();
List<Country> countries = DataSource.read(...); // get from a DAO
addCountries(countries);
}
private static Map<String, Country> allCountries = null;
private static void init() {
allCountries = new HashMap<String, Country>();
}
private static void addCountries(List<Country> countries) {
for (Country country : countries) {
if ((country.getISO() != null) && (country.getISO().length() > 0)) {
allCountries.put(country.getISO(), country);
}
}
}
public static Country findByISO(String cc) {
return allCountries.get(cc);
}
}
In the code using the class, I do something like:
Country country = Country.findByISO("RO");
The problem is that I get a NullPointerException because the map (allCountries) is not initialized. If I set up breakpoints in the static block I can see the map getting populated correctly, but it's as if the static method has no knowledge of the initializer being executed.
Can anyone explain this behavior?
Update: I've added more detail to the code. It's still not 1:1 (there are several maps in there and more logic), but I've explicitly looked at the declarations/references of allCountries and they are as listed above.
You can see the full initialization code here.
Update #2: I tried to simplify the code as much as possible and wrote it down on the fly. The actual code had the static variable declaration after the initializer. That caused it to reset the reference, as Jon pointed out in the answer below.
I modified the code in my post to reflect this, so it's clearer for people who find the question. Sorry about the confusion everyone. I was just trying to make everyone's life easier :).
Thanks for your answers!
Does calling a static method on a class in Java trigger the static initalization blocks to get executed?
Empirically, I'd say no.
You're wrong.
From the JLS section 8.7:
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.
Section 12.4.1 of the JLS states:
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.
This is easily shown:
class Foo {
static int x = 0;
static {
x = 10;
}
static int getX() {
return x;
}
}
public class Test {
public static void main(String[] args) throws Exception {
System.out.println(Foo.getX()); // Prints 10
}
}
Your problem is in some part of the code that you didn't show us. My guess is that you're actually declaring a local variable, like this:
static {
Map<String, Country> allCountries = new HashMap<String, Country>();
// Add entries to the map
}
That hides the static variable, leaving the static variable null. If this is the case, just change it to an assignment instead of a declaration:
static {
allCountries = new HashMap<String, Country>();
// Add entries to the map
}
EDIT: One point worth noting - although you've got init() as the very first line of your static initializer, if you're actually doing anything else before then (possibly in other variable initializers) which calls out to another class, and that class calls back into your Country class, then that code will be executed while allCountries is still null.
EDIT: Okay, now we can see your real code, I've found the problem. Your post code has this:
private static Map<String, Country> allCountries;
static {
...
}
But your real code has this:
static {
...
}
private static Collection<Country> allCountries = null;
There are two important differences here:
The variable declaration occurs after the static initializer block
The variable declaration includes an explicit assignment to null
The combination of those is messing you up: the variable initializers aren't all run before the static initializer - initialization occurs in textual order.
So you're populating the collection... and then setting the reference to null.
Section 12.4.2 of the JLS guarantees it in step 9 of the initialization:
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
Demonstration code:
class Foo {
private static String before = "before";
static {
before = "in init";
after = "in init";
leftDefault = "in init";
}
private static String after = "after";
private static String leftDefault;
static void dump() {
System.out.println("before = " + before);
System.out.println("after = " + after);
System.out.println("leftDefault = " + leftDefault);
}
}
public class Test {
public static void main(String[] args) throws Exception {
Foo.dump();
}
}
Output:
before = in init
after = after
leftDefault = in init
So the solution is either to get rid of the explicit assignment to null, or to move the declarations (and therefore initializers) to before the static initializer, or (my preference) both.
The static initializer will get called when the class is loaded, which is normally when it is first 'mentioned'. So calling a static method would indeed trigger the initializer if this is the first time that the class gets referenced.
Are you sure the null pointer exception is from the allcountries.get(), and not from a null Country returned by get()? In other words, are you certain which object is null?
Theoretically, static block should get executed by the time classloader loads the class.
Country country = Country.findByISO("RO");
^
In your code, it is initialized the first time you mention the class Country (probably the line above).
I ran this:
public class Country {
private static Map<String, Country> allCountries;
static {
allCountries = new HashMap<String, Country>();
allCountries.put("RO", new Country());
}
public static Country findByISO(String cc) {
return allCountries.get(cc);
}
}
with this:
public class Start
{
public static void main(String[] args){
Country country = Country.findByISO("RO");
System.out.println(country);
}
}
and everything worked correctly. Can you post the stack trace of the error?
I would say that the problem lies in the fact that the static block is declared before the actual field.
Do you have allCountries = new HashMap(); in your static initializer block? The static initializer block is actually called upon class initialization.

Categories

Resources