Can static variables be allocated memory during run time - java

I am new to java and I am trying to understand the sequence in which JVM works.I have following queries.
1)Can a class be loaded at run time.
2)Can static variables be allocated memory during runtime.
3)Why static variables cannot be defined inside a function in java?
May be if you can explain me with the help of an example given below:
public class Test{
public static void main(String[] args)throws IOException {
static int d;
}
}
In this example static is written inside a method which will give an error.It would be helpful if you can explain this with above context.

simply answers
Yes
Yes/No
details
You can load any java class in runtime, usually this is done via Classloader
All static variables are actually allocated and initialized by JVM (not you) during runtime, usually just before you use them, check out this answer: Order of initialization of static variable in Java
also you can re-allocate not final static variables in your code with new values/memory, like:
static String a = "a"; // default value to be used by JVM during init
public static void main(String[] args)
{
System.out.println(a); // will print a, as JVM already initialized it with "a"
a = "b"; // we've changed value
System.out.println(a); // now will print b
}
but you cannot define static variable inside function, it is possible in c/c++, but not in java

Related

When a static variable is in RIWO state, can it be accessed directly ?

If a static variable is in RIWO (Read Indirectly Write Only) state. the static variable can not be accessed directly.
here is the code
class Test {
static{
System.out.println(x);
}
static int x = 10;
public static void main(String[] args) {
}
}
in this case illegal forward reference compile time error is coming.
but if you are using the class name to access the static variable, it can be accessed.
here is the code example
class Test {
static{
System.out.println(Test.x);
}
static int x = 10;
public static void main(String[] args) {
}
}
answer is : 0
how is this possible ? isn't this a direct access ?
As per JLS 12.4.1. When Initialization Occurs and this answer:
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
In your case reading Test.x falls under point 4, a non-constant static field. Your code reads and output 0 which is the default int value, however you change it by marking the field final as
static {
System.out.println(Test.x);
}
final static int x = 10;
The code will now output 10. You can see it by comparing output of javap -c Test.class for both non-final and final field cases, the order of bytecode will be reversed around:
6: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
9: bipush 10
To me it looks like the Java compiler's forward reference error is a workaround for gotchas in static initialization in JVM.
This could be a java compiler bug.
In your first case, compiler successfully find out the bad usage.
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.
Use the variable before declare it of course should be forbidden.
In your second case, unfortunately, compiler don't find the bad usage.
The following things happens step by step:
JVM load the Test class, now Test.class object is accessable
Someone trigger the Test class static's initlization
JVM run in textual order, the most front static block will be invoked first
JVM try to get the Test.x. Since it's not constant, jvm go to METASPACE to get the value. int is 0 by default. So you get 0 printed.
JVM run the next line x = 10, set the data into METASPACE
By the way, Karol's answer has a little mistake. Only add final is not sufficient, the other necessary condition is it's really constant. The following code will still print 0.
static {
System.out.println(JustTest.x);
}
static final int x = Integer.valueOf(1);

Can we access static members and static functions of a class with the help of instance variables of that class in java? [duplicate]

This question already has answers here:
What is a class literal in Java?
(10 answers)
Closed 5 years ago.
To illustrate the contrast. Look at the following java snippet:
public class Janerio {
public static void main(String[] args) {
new Janerio().enemy();
}
public static void enemy() {
System.out.println("Launch an attack");
}
}
The above code works very fine and seems to be yes as answer to this question as the output turns to be as follows.
Launch an attack
But at the very next moment when I run the following snippet
public class Janerio {
public static void main(String[] args) {
System.out.println(new Janerio().class);
}
}
I get the compile time error
/Janerio.java:3: error: <identifier> expected
System.out.println(new Janerio().class);}
^
/Janerio.java:3: error: ';' expected
System.out.println(new Janerio().class);}
^
2 errors
I don't see why such a situation comes up because in the previous snippet I was able to access the static "enemy" function with the help of an instance of the class but here it's proving false. I mean why can't I access the ".class" static method with the help of the instance of the class. Am I wrong to consider ".class" to be a static function or member of the class Janerio and is it wrong to be analogous to the static features of both the snippets?
But as soon as I call the ".class" with the class name things appear to be that ".class" is static in nature but it deviates to the be static on calling ".class" with an instance of the class.
public class Janerio {
public static void main(String[] args) {
System.out.println(Janerio.class);
}
}
Output we get:
class Janerio
.class references the Class object that represents the given class. it is used when there isn't an instance variable of the class. Hence it doesn't apply to your usage
Read more here:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.8.2
With .class you do not select a field (besides class is a keyword).
It is a pseudo operation, usable with a class name, yielding a Class instance:
int.class, Integer.class, java.util.List.class
Am I wrong to consider ".class" to be a static function or member of the class Janerio?
Yes, it's not a variable and it's definitely not a method. You have to use the Object#getClass method when you want to get the class of an instance.
Yes, you can access these static members of classes that way, but the better practise is to use name of that class instead of the name of specific referece to object of that class. It makes your code clearer to understand and to read as static members of class do not belong to specific object but to whole class. For example:
class MyClass {
static int count = 0;
}
It is better to access this field that way:
MyClass.field = 128;
instead of changing that value using the name of specific reference, for example:
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
obj1.field = 128;
Because it can be confusing when you realize that this way even obj2.field has assigned new value of 128. It might look a bit tricky, so again, I would suggest the first presented method of calling methods or changing values assigned to fields.

Why do methods on arrays have to be static (Java)?

I don't understand why methods on arrays, in Java, have to be static. Static methods can only be used on static variables right? So this would mean arrays are static variables, variables shared by a class? But what class would this be?
Can someone help me understand this?
Edit: to be more specific, I am creating methods to act on arrays but if I just write "public int[] expandArr(int[]a, int v)" and I try to use this method in the main method, I get an error saying I can't make a static reference to a non-static method. When I write "public static int[] expandArr(int[]a, int v)" it works then.
I understand you cannot change the size of an array, the method I wrote makes a new array with increased size and copies the first one into it.
Thank you.
You say you tried to write this:
public int[] expandArr(int[]a, int v)
The thing is, you had to write it in some class, since you can't just have free-floating methods in your program. Therefore, it must operate on a instance of the class. For example:
public class MyProgram {
public int[] expandArr(int[]a, int v) { ... }
public static void main(String[] args) { ... }
}
expandArr requires an instance of MyProgram, since you didn't declare it to be static. And that has nothing to do with arrays. It would be the same if you wrote
public class MyProgram {
public String expandString(String s, int v) { ... }
public static void main(String[] args) {
String s = expandString(args[0], 1); // ILLEGAL
String s2 = args[0].expandString(1); // ILLEGAL
}
}
Although the first parameter of expandString is a String, this actually operates on a MyProgram, and you cannot use expandString without an instance of MyProgram to operate on. Making it static means that you can (the first use of expandString in my example would become legal.)
In general, you can't add methods to a class without modifying the source of that class. If you want to write a new method that does something with objects of a certain class C, and you can't modify class C (perhaps because it's in the Java library or someone else's library), then you'll need to put the method in some other class C2, and most of the time you will need to make the method static since it doesn't involve objects of class C2.
You can't call a non-static method from a static method unless you first instantiate the an object of the class.
e.g.
In class Whatever...
public boolean ok() {
return true;
}
public static void main(String[] args) {
Whatever w = new Whatever();
System.out.println(w.ok());
}
You cant call a non static method from a static context. A static method belongs to the class, non static or instance methods are copied to each instance of the class (they each have their own). If I have 10 instances of class A, and class A has a static method, which all of them share, then I try to invoke a non static method in class A from class A's static method, which instance of class A gets its method invoked? The behavior is undefined.
The question really has nothing to do with arrays.
This question is related: Can't call non static method
I think what you're referring to is the fact that you can't extend an array class and hence can't add a method to it:
// No way to do this
int[] array;
array.myMethod();
This means your only option is to make a static helper method somewhere:
// So you have to do this
int[] array;
Utils.myMethod(array);
class Utils {
static void myMethod(int[] array) {
...
}
}
An example of this is the Arrays class, which has lots of static methods for operating on arrays. Conceptually it would be clearer if these methods could be added to the array classes, but you can't do that in Java (you can in other languages like Javascript).
That is why we use other classes like the ArrayList to make them grow dynamically in size. At the core of an arraylist you will simply find an array that is renewed in size whenever the class figures out it necessary. If I'm understanding your question right.

How are field variables initialized in Java?

I tried to run this program but this gives a runtime error(StackOverflowError). If in class Static I make reference object ob, static, then no error occurs. Can anyone please explain me why is this happening and please explain me how are field variables(whether static or non static and whether reference or non reference variables) initialized?
public class Static {
public Static ob = new Static();
private int a;
public void win(Static obj) {
//System.out.printf("ob.a = %d\n", ob.a);
obj.a = 15;
System.out.printf("ob.a = %d", ob.a);
}
}
public class StaticTest {
public static void main(String args[])
{
Static obj=new Static();
//Static obj1=new Static();
// obj.win(obj1.ob);
}
}
Each time you instantiate an object of Static class (very confusing name BTW) you create an object of Static and instantiate it, which create another object of Static and instantiate it and so on... (so you get a StackOverflow error):
public Static ob = new Static();
Your code creates an instance of Static class.
When the instance is create their attributes are initialized. What your code does is to initialize the 'ob' attribute with pointing to a new Static instance.
Then the new instance of Static class is created, and ... you have an "infinite initialization loop".
If you attach 'static' keyworkd to an attribute you are creating a "class attribute", that is, an attributed shared among all instances of that class.
This means when you execute code and the first instance of Static is goind to be created JAva initialize the ob attribute. Subsequent instances of Static doesn't initialize it because it is shared among all.
See this sample: http://www.roseindia.net/java/beginners/staticvariable.shtml
static fields are initialized once for all instances of the class. This is why changing the type to static stops it from infinite recursion.
When the field is not static you create an infinite recursion which leads to a stack overflow; when you instantiate the object, it instantiates another, which instantiates another, and so on.
Static is at the class level and hence it is initialized when the class is loaded in the memory for the first time. Also static blocks are init in order of there declaration.
As against, the class variables (non static) are per object and are init when the object of that class is created, not in any specific order, I believe.
In your case, if you don't make ob static, it will try to init the Static class object and when try to inti the ob, it again go and create another Static (as it calls new Static()) and this goes on for ever until you run out of stack (StackoverFlow).
if you make ob static, this is init only once (when Static class is loaded in memory) and you are good to go.
If you create an instance level of a field, you are causing never-ending recursion, which ultimately ends up to StackOverFlow memory error.
If on the other hand you define your field as static you are avoiding the recursion, since the static field variables belong to the Class, not to the object instance. Classes in the JVM are only created once as opposed to Object instances, which can be numerous.

Scope of static variable and methods in Java

I have some doubts about usage of static method in Java.
I read many places static variables are instance independent so be comes global.
public class ThirdClass {
public static var = "Java";
}
public class Second {
public static void main(String[] args) {
ThirdClass ob1 = new ThirdClass();
System.out.println(ob1.var); // prints Java
ob1.var="Ruby";
ThirdClass ob2 = new ThirdClass();
System.out.println(ob2.var); // prints Ruby
}
}
public class First {
public static void main(String[] args) {
ThirdClass ob3 = new ThirdClass();
System.out.println(ob1.var); // prints Java again!!!
}
}
As you see in second class multiple instance of ThirdClass sharing same instance of variable var. But a separate instance in class First don't access the final value "Ruby" but show original "Java". It means the static variable are NOT global variable but only global to single execution!!!
Also do is creating static variable resource intensive compared to instance variable?
Please suggest.
It means the static variable are NOT global variable but only global to single execution!!!
Of course they are. All variables that are not persisted to some kind of storage (like the hard disk) do not retain their values between distinct executions of the program.
The value is initialized when the class is loaded. Therefore each time you execute the code, it is initialized to the value "Java" as is defined in the class. The new value is not saved, it is only changed in memory and is "reset" when the code is executed again.
The term global has nothing to do with the variables persistence, and scope is defined only within the running program.
#eternal
I think I am getting the point you wanna ask.
I tested this (with some minor compile changes) on Jboss. The results were:
Once deployed the scope of class ThirdClass seems to be application deployment level.
And the static value of var was retained while multiple method calls.
Here is the basic structure i used.
public class ThirdClass {
public static var = "Java";
}
public class Second class{
public void testA {
ThirdClass ob1 = new ThirdClass(); // not needed , just kept for clarity.
System.out.println(ThirdClass.var);
ThirdClass.var="Ruby";
ThirdClass ob2 = new ThirdClass();
System.out.println(ThirdClass.var);
}
public class First {
public void testB {
ThirdClass ob3 = new ThirdClass();
System.out.println(ThirdClass.var);
ThirdClass.var="CSHARP";
}
public void testC {
ThirdClass ob4 = new ThirdClass();
System.out.println(ThirdClass.var);
}
By webservices calls ( i have a setup) called these methods in secquence
testA() --> Display var = "Ruby"
testB() --> Display var = "Ruby"
testC() --> Display var ="CSHARP"
So the new changed values were shared by DIFFERENT METHOD CALLS throught application deployment. So scope of ThirdClass was deployment level.
Static variables are "per class". So it doesn't matter if your static variable in this class has same name/type as some other.
It's global in the sense that no matter how many object of that class you have, if you have them use a static variable, they'll all be using one var.
You have two different mains, meaning it will have 2 different execution paths. You either start with one or with the other, the value of the changed static variable is only changed for the current execution, on a different execution it always reset to the default value.
Try not to have a second main but rather a static method and then call it on the first main after the change, you will see a different result then.
You can Only execute one class at one time from the command line and in your program there are two classes which have main method if you run Second class at one time then it will not execute the main method of the Third class and vice versa. I have tested it on my system.

Categories

Resources