Static variable initialisation - java

Are static variables initialised every time a new instance of the object containing these variables are created ? Or are they initialised just once when the object is first called?

You said
Are instance static variables initialised...
stop right there, the statement makes no sense. static variables live on the class, not on any particular instance. They are initialized in an initialization procedure that is run when an instance is created, a static method on the class is run, or a static variable on the class is accessed. (Full disclosure, #Bruno's answer led me to this information).

Static fields are initialized during the initialization of the class (don't mix initialization and loading, they are different things -- a class can be loaded, and you can do reflection on it, without ever initializing it).
Also, class initialization can happen more than once for a given class if you are using multiple ClassLoaders.
See VM Spec section 2.17.4, Initialization, and section 2.17.5, Detailed initialization procedure for more details on when exactly a class will be loaded and when exactly it will be initialized..
EDIT: trivial example that will show how a class can be loaded and initialized multiple times and that loading does not automatically imply initialization:
public class A { static { System.out.println("I've been initialized!"); } }
public class Main {
public static void main(String... args) {
ClassLoader cl = new URLClassLoader(..., null);
System.out.println("loading...");
Class<?> aClass = cl.loadClass("A");
// here you could perform reflection on aClass, without initializing it
System.out.println("Will be initialized now:");
Object o = aClass.newInstance();
System.out.println("Let's load once again...");
ClassLoader cl2 = new URLClassLoader(..., null);
Class<?> aClass2 = cl2.loadClass("A");
System.out.println("Will be initialized a second time:");
Object o2 = aClass2.newInstance();
// the following is false:
System.out.println("aClass1.equals(aClass2) = " + aClass1.equals(aClass2));
// the following is true:
System.out.println("aClass1.getName().equals(aClass2.getName())" + aClass1.getName().equals(aClass2.getName()));
}
}
(I hope this compiles when you specify the missing URL[] object in the URLClassLoader's constructor...)
Note that it is necessary to set the class loaders' parents null, otherwise their parents would be the main application class loader (ie, the same that loaded the class Main), then because Java delegates the loading to the parent class loader first by default, if the class A is in the class path, you would see the load and initialization only once.
Finally, note that Class.load("A") is not equivalent to classLoader.loadClass("A"). If you check the documentation of Class.load(String), you will see that this method loads and initializes the class. There's an overload of Class.load(...) that takes a boolean indicating if it should initialize the class or not.

Related

why have a constructor called in the same class?

public class Store {
// instance fields
String productType;
// constructor method
public Store(String product) {
productType = product;
}
// advertise method
public void advertise() {
String message = "Selling " + productType + "!";
System.out.println(message);
}
// main method
public static void main(String[] args) {
String cookie = "Cookies";
Store cookieShop = new Store(cookie);
cookieShop.advertise();
}
}
In this class, the constructor for the class is called in its own main method. Why wouldn't this recursively call itself infinitely?
EDIT: From the future, yes; this quite a noob question that could be, and has been solved by reading the docs.
Constructors of a class are used to construct class-instances. Static methods are methods of the class, not of its instances (although they can be accessed through its instances). A class is loaded through a ClassLoader. Most classes are loaded and constructed through the ClassLoader.getSystemClassLoader(), the JVM takes care of constructing the class.
The class Store is already loaded when main(...) is executed and the call to the constructor creates, as explained above, an instance of that class, not the class itself. Thus, no recursive calls occur.
As was pointed out by #AndyTurner, even if an instance method were to call a constructor, this would not necessarily lead to a recursion. The constructor constructs a new instance, the old instance is decouple from the new instance.
Main method is a static method and it is called one time when application is starting. Once application started, main method can't run again.
When you making a store object, It is true that constructor is running. But it does not calling main method again.

Initializing static final variable in declaration vs initializing during Application.OnCreate()

I want to store an object state between activities (already considered Parcelables, JSON, yadda yadda) but since I have a couple of Singletons, might as well refer to them in a class that extend Application (modularity + easy to maintain).
So to my question, let's say I have a simple singleton:
class SimpleSingleton
{
private static final SimpleSingleton instance; //The question will refer this line later.
public static SimpleSingleton getInstance()
{
return instance;
}
private SimpleSingleton(){}
}
1: At first I create an initInstance() method within the above class, e.g:
class SimpleSingleton
{
//... the code above
public static void initInstance()
{
if(instance == null) instance = new SimpleSingleton();
}
}
2: Hence the below works, (in which afterwards, I can refer to the singleton from any activity via CustomSingleton.getInstance()):
class MyApp extends Application
{
#Override
public void onCreate()
{
super.onCreate();
initSingletons();
}
protected void initSingletons()
{
SimpleSingleton.initInstance();
}
}
BUT. What if I declare
private static final SimpleSingleton instance = new SimpleSingleton();
instead of
private static final SimpleSingleton instance;
in the SimpleSingleton class?
I assume the object is initialized during compile time, so doesn't that makes the whole #1 and #2 unnecessary? Or do I get the order wrong (especially WHEN the class is actually initialized)? I came from C# and currently developing for Android so this kinda gave me a quick gotcha when I want to refer to my Singletons. Also, I ask this since according to this blog:
The explanation of the weird behavior I saw that makes more sense to me is that the static variables instances are bound to the class loader of the class that first initialized them.
The only difference i can think of is when you do
private static final CustomObject instance = new CustomObject();
when you application is launched it will create and allocate space for it.
Note it might never be used but it would still be using memory.
when you create it on an onCreate method it will only create an instance when it is called.
Using static also has one more disadvantage that is it will use your perm gen space and if by chance it fails to give it space or fails to create it your program will crash on startup. Leaving you confused.
I strongly suggest using the onCreate method approach.

non-static variable this cannot be referenced from a static context error [duplicate]

The following code is generating an error on the variable con2 saying "non-static variable con2 cannot be referenced from a static context Error." I Googled for a resolution and they are suggesting the variable isn't initalized yet to make the methods available. Am I initializing this incorrectly? I also tried changing things to public but that didn't help either.
import java.io.*;
import java.net.*;
import java.sql.*;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import net.sourceforge.jtds.jdbcx.JtdsDataSource;
import net.sourceforge.jtds.jdbc.Driver;
class testconnect {
private java.sql.Connection con2 = null;
private final String url2 = "jdbc:jtds:sqlserver://";
private final String serverName= "SQL01";
private final String portNumber = "2677";
private final String databaseName= "App";
private final String userName = "bob";
private final String password = "boob";
private final String selectMethod = "cursor";
private String getConnectionUrl2(){
System.out.println("initalizing jtds");
//String returnVal = url+serverName+":"+portNumber+";databaseName="+databaseName+";user="+userName+";password="+password+";instance="+instance+";";
String returnVal = url2+serverName+":"+portNumber+"/"+databaseName+";user="+userName+";password="+password;
System.out.println("url2: " + returnVal);
return returnVal;
}
public static void main (String[] args) {
con2 = java.sql.DriverManager.getConnection(getConnectionUrl2());
}
} //end class
You probably want to add "static" to the declaration of con2.
In Java, things (both variables and methods) can be properties of the class (which means they're shared by all objects of that type), or they can be properties of the object (a different one in each object of the same class). The keyword "static" is used to indicate that something is a property of the class.
"Static" stuff exists all the time. The other stuff only exists after you've created an object, and even then each individual object has its own copy of the thing. And the flip side of this is key in this case: static stuff can't access non-static stuff, because it doesn't know which object to look in. If you pass it an object reference, it can do stuff like "thingie.con2", but simply saying "con2" is not allowed, because you haven't said which object's con2 is meant.
No, actually, you must declare your con2 field static:
private static java.sql.Connection con2 = null;
Edit: Correction, that won't be enough actually, you will get the same problem because your getConnection2Url method is also not static. A better solution may be to instead do the following change:
public static void main (String[] args) {
new testconnect().run();
}
public void run() {
con2 = java.sql.DriverManager.getConnection(getConnectionUrl2());
}
Java has two kind of Variables
a)
Class Level (Static) :
They are one per Class.Say you have Student Class and defined name as static variable.Now no matter how many student object you create all will have same name.
Object Level :
They belong to per Object.If name is non-static ,then all student can have different name.
b) Class Level :
This variables are initialized on Class load.So even if no student object is created you can still access and use static name variable.
Object Level:
They will get initialized when you create a new object ,say by new();
C)
Your Problem :
Your class is Just loaded in JVM and you have called its main (static) method : Legally allowed.
Now from that you want to call an Object varibale : Where is the object ??
You have to create a Object and then only you can access Object level varibales.
Your main() method is static, but it is referencing two non-static members: con2 and getConnectionUrl2(). You need to do one of three things:
1) Make con2 and getConnectionUrl2() static.
2) Inside main(), create an instance of class testconnect and access con2 and getConnectionUrl2() off of that.
3) Break out a different class to hold con2 and getConnectionUrl2() so that testconnect only has main in it. It will still need to instantiate the different class and call the methods off that.
Option #3 is the best option. #1 is the worst.
But, you cannot access non-static members from within a static method.
The simplest change would be something like this:
public static void main (String[] args) throws Exception {
testconnect obj = new testconnect();
obj.con2 = DriverManager.getConnection(obj.getConnectionUrl2());
obj.con2.close();
}
This is an interesting question, i just want to give another angle by adding a little more info.You can understand why an exception is thrown if you see how static methods operate.
These methods can manipulate either static data, local data or data that is sent to it as a parameter.why? because static method can be accessed by any object, from anywhere.
So, there can be security issues posed or there can be leaks of information if it can use instance variables.Hence the compiler has to throw such a case out of consideration.

How does Java find already loaded classes?

I know that Java uses the ClassLoader hierarchy for loading the classes.
For example a program:
public void test(){
A a = new A(); // Line 1 The class is accessed first time here so it should be loaded and defined
A ab = new A(); //Line 2 How can the second line be represented?
}
The first line of the code is similar to
Thread.currentThread().getContextClassLoader().loadClass("A");
So the class is loaded and defined to create instance of Class.
Now the question is when the second line is executed the Class A is referred again, will Java not lookup for the class again and return the same loaded instance of the Class?
As the Java classloader document says that every class loader should maintain the instances of loaded classes and return the same instances for the next call.
Where does Java keep the loaded classes? ClassLoader class has a Vector of classes which is called by VM to add the loaded classes.
Maybe the question is a bit confusing, basically I am trying to figure out from which method are the already loaded classes returned. I tried to keep a debug point in the loadClass() method but it is not called for the Line 2.
The loadClass() method of ClassLoader has findLoadedClass method but that too is not called.
If you want to "translate" the mention of A to any method call, then the closest you could get is not loadClass() but Class.forName().
This method call queries the classloader for the class, which may or may not trigger class loading (and the caller doesn't even care). It will simply return a fully loaded (and initialized, if you don't use the three-argument version) class back to the caller.
And once the class has been loaded, the class loader no longer get's invoked when the class is used (as the name suggests, it's job is done, once it loaded the class).
package java_language;
public class NewClass {
Java_language j;
public NewClass() throws ClassNotFoundException {
j=new Java_language();
if (Class.forName("java_language.Java_language", true, Thread.currentThread().getContextClassLoader()).equals(j.getClass())) {
System.out.println("CLass has been loaded");
}
}
public static void main(String[] args) throws ClassNotFoundException {
new NewClass();
}
}
package java_language;
public class Java_language {
static Java_language java_language = null;
public Java_language() {
System.out.println("Stack Overflow");
}
}
Ans is:
enter image description here

What's the difference between ClassLoader.load(name) and Class.forName(name) [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Difference betweeen Loading a class using ClassLoader and Class.forName
AFAIK, two ways are provided in java to init a class from its name.
Class
public static Class forName(String
className) throws
ClassNotFoundException
public static Class forName(String
name, boolean initialize, ClassLoader
loader) throws ClassNotFoundException
ClassLoader:
public Class loadClass(String
name) throws ClassNotFoundException {
return loadClass(name, false);
}
The known thing is in forName method, we can specify the flag of initialize to be false ,this will skip some static things to be initialized for this class. But what's else?
And how should I use them correctly?
It's better you can show some good examples.
Thanks!
UPDATE:
After raised question,I made some simple classLoader test.
ClassLoader cls = ClassLoader.getSystemClassLoader();
Class someClass = cls.loadClass("Test");
Class someClass0= Class.forName("Test");
Class someClass1= Class.forName("Test",false,cls);
URL[] urls = new URL[] {new File("bin/").toURL()};
ClassLoader cls2 = new URLClassLoader(urls, null);
Class someClass2 = cls2.loadClass("Test");
ClassLoader cls3 = new URLClassLoader(urls, cls);
Class someClass3 = cls3.loadClass("Test");
System.out.println(someClass.equals(someClass0));
System.out.println(someClass.equals(someClass1));
System.out.println(someClass.equals(someClass2));
System.out.println(someClass.equals(someClass3));
The result is
true,true,false,true
UPDATE
Here is my answer about
Difference between loadClass(String name) and loadClass(String name, boolean resolve)
Consider this code
class X
{
static{ System.out.println("init class X..."); }
int foo(){ return 1; }
Y bar(){ return new Y(); }
}
The most basic API is ClassLoader.loadClass(String name, boolean resolve)
Class classX = classLoader.loadClass("X", resolve);
If resolve is true, it will also try to load all classes referenced by X. In this case, Y will also be loaded. If resolve is false, Y will not be loaded at this point.
There doesn't seems to be any good reason for resolve=true. If nobody calls X.bar(), Y will never be needed, why should we load it at this point? And if Y is missing or corrupt, we'll get an error trying to load X, which is totally unnecessary.
Interestingly, this method is protected, so it's not easy to invoke it.
Another method loadClass(name) simply calls loadClass(name,false). It's public, and it takes the sensible choice of resolve=false. So it is exactly what's needed by developers.
ClassLoader only loads classes, it does not initialize classes. We can inspect the class metadata, e.g. its super class, its annotations, its methods and fields, etc. without triggering the static initialization execution. This fact is very important for frameworks.
Now, Class.forName
Basically, Class.forName(String name, boolean initialize, ClassLoader loader) calls loader.loadClass(name). And if initialize=true, the class is initialized - in the X example, we'll see "init class X..." printed.
Class.forName(name) is the same as forName(name, true, currentLoader).
Now, why would anyone want to initialize the class at this point? Wouldn't it be better if the class is initialized only when necessary? A famous use case is JDBC initializing:
Class.forName("com.mysql.jdbc.Driver");
The convention is, a JDBC driver class registers itself in its static initializer. The above code will trigger the static initialization, making the driver available for subsequent uses.
From today's point of view, that design is really odd. We usually don't rely on static initializers. So there isn't much justification for initialize=true, and Class.forName(name) should be avoided.
A "class literal" will return the class, without initializing it
Class c = com.mysql.jdbc.Driver.class;
// actually compiled to
Class c = Class.forName("com.mysql.jdbc.Driver", false, currentLoader);
Now, what the heck is the "currentLoader"? It is the class loader of the current class
class A
{
void foo()
{
currenLoader == THIS_A_CLASS.getClassLoader()
}
}
When X.bar() is invoked for the first time, a "Y" class is needed. what's happening is roughly
class X
bar()
// new Y();
Class classY = currentLoader.loadClass("Y");
Constructor cst = classY.getConstructor();
// next line will initialize Y (if not yet)
// creating an instance of a class requires it be initialized
Object y = cst.newInstance();
ClassLoader.loadClass(String name) will attempt to load the class using the specified classloader. Class.forName(String name) will attempt to load the class using the default system classloader hierarchy.

Categories

Resources