Problems understanding static modifier - java

I am having difficulty understanding what a "static" method and "static" variable is and it is causing me problems with my code. Here is the code I am having difficulty with:
public class Document{
public void NewBlank(){
Resources.openRawResource(R.raw.blank);
}
}
Why do I get the error "Cannot make a static reference to the non-static method Resource.openRawResource(int) from the type Resources"? Why can't I reference a non-static method?

openRawResources is not a static method, it needs to be invoked in an object, not a type. In order to get an instance of Resources you could call getResources in an activity. Then the resulting code would be
Resources resources = myactivity.getResources();
resources.openRawResource(R.raw.blank);
A static method/variable is one that belongs to the class type, and not to the instances/objects of such type.

Cannot make a static reference to the non-static method
This means that for invoking that method you are trying to, you need a reference to an instance of that class.
Here's an example illustrating the difference:
public class Foo{
public static int staticVariable = 5;
public static void methodStatic(){}
public void nonStaticMethod(){}
}
here's how you can use them:
Foo.nonStaticMethod(); //can call static method referring to the class itself without having an instance
Foo f = new Foo();
f.nonStaticMethod(); //you need an instance of a Foo class in order to call a non-static method
For what concern static variables, these are variables that doesn't belong to a single instance of a class, but are shared between all different instances of the same class:
Foo a = new Foo();
Foo b = new Foo();
System.out.println(a.staticVariable); //print 5
System.out.println(b.staticVariable); //print 5
a.staticVariable = 10;
System.out.println(b.staticVariable); //print 10
(Please, look at the example above just to understand the concept of what a static variable is. You'll get the warning "access a static field in a non-static way" because that's not a proper way to access those variables)

Related

Instance methods can access instance methods directly. What does this mean?

After going through Java documentation I understand that a field declared with 'static' keyword is class variable (or static field) and similarly when using 'static' during method declaration, is a static method (or class method). Class variable and Class methods are reference by class name itself.
Read this and this topics however could not understand following sentences from Java documentation.
What does it mean when it says.....
Not all combinations of instance and class variables and methods are allowed:
Instance methods can access instance variables and instance methods
directly.
Instance methods can access class variables and class methods
directly.
Class methods can access class variables and class methods directly.
The Java doc clearly explains about Class variables and Class methods but above 3 points are confusing to me.
Example Execution
1.Instance methods can access instance variables and instance methods directly.
Some Info:
Instance method are methods which require an object of its class to be
created before it can be called.To invoke a instance method, we have to
create an Object of the class in within which it defined.
Instance variables are declared in a class, but outside a method, constructor
or any block.
class Example1 {
int a = 100; // instance variable
public void printData() { // this an instance method called using an object of class Example1
getData(); // accessing another instance method directly without any object
}
public void getData() {
System.out.println(a); // accessing instance variable 'a' directly without any object
}
}
public class InstanceDemo {
public static void main(String[] args) {
Example1 obj1 = new Example1();
obj1.printData(); // will print 100
}
}
2.Instance methods can access class variables and class methods directly.
Class variables also known as static variables are declared with the static
keyword in a class, but outside a method, constructor or a block.
class Example2 {
static int a = 20; // 'static' / class variable
public void printData() { // instance method
setData(); // accessing class method directly
System.out.println(a); // accessing class variable directly
}
public static void setData() { // class method 'static'
a = 200; // setting value of class variable 'a'
}
}
public class InstanceDemo {
public static void main(String[] args) {
Example2 obj2 = new Example2();
obj2.printData(); // will print 200
}
}
3.Class methods can access class variables and class methods directly.
Static methods are the methods in Java that can be called without creating an
object of class. They are referenced by the class name itself or reference to
the Object of that class.
Memory Allocation: They are stored in Permanent Generation space of heap as
they are associated to the class in which they reside not to the objects of
that class. But their local variables and the passed argument(s) to them are
stored in the stack. Since they belong to the class so they can be called to
without creating the object of the class.
class Example3 {
static int a = 300;
public static void printData() {
getData(); // accessing class method
}
public static void getData() {
System.out.println(a); // accessing class variable 'a'
}
}
public class InstanceDemo {
public static void main(String[] args) {
//calling class method : class method are called using class name.
Example3.printData(); // will print 300
}
}
I think you just need to practice programming, so you can experience how the language works. Understanding the quirks of static access is one of the hardest things to grasp initially. Static members are generally geared towards providing class utility.
An instance method gets a pointer to the instance it's operating on, on the stack, therefore it can access the members of the instance. A static method isn't associated with any particular instance. There's no 'this' reference, thus it can't access instance members.
Instance methods can access instance variables and instance methods
directly.
This means a method that doesn't have a static modifier i.e. an instance method can access any non-static variable as well as call any non-static method.
Instance methods can access class variables and class methods
directly.
This means a method that doesn't have a static modifier i.e. an instance method can access a static variable or call a method with the static modifier.
Class methods can access class variables and class methods directly.
This means a static method can access any static variable as well as call any other method that has a static modifier.
To put it simply, an instance method i.e. a method without the static modifier can access both a static variable as well as a non-static variable and it can also directly call a static method and a non-static method.
On the other hand, a static method can only access static variables and call static methods. it cannot, however, access an instance variable or instance methods directly without an object.

Can non-static methods modify static variables

I am wondering how a non static method can modify a static variable. I know that static methods can only access other static methods and static variables. However, is the other side true? Can non-static methods access only non-static variables? For example:
public class SampleClass {
private static int currentCount = 0;
public SampleClass() {
currentCount++;
}
public void increaseCount() {
currentCount++;
}
}
This code compiles and I would like to know why in terms of static access privledges.
I have found this from The Java Tutorials
Instance methods can access instance variables and instance methods directly.
Instance methods can access class variables and class methods directly.
Class methods can access class variables and class methods directly.
Class methods cannot access instance variables or instance methods directly—they must use an object reference. Also, class methods cannot use the this keyword as there is no instance for this to refer to.
So the answer is yes, non-static methods CAN modify static variables
No, any non-static method has access to static members. The only way this would be false is if the non-static context did not have access to the static member (ex. the static member is private to a class and the non-static code is not in that class). static variables exist to provide an instance free variable/method, so for example if we have a Game class and a highscore variable, the highscore would be static (accessible without an instance), and after every game (an instance of the Game class) completes we could alter the highscore from our non-static context if our score is greater than the high score.
Non static methods can access static variables.
Static methods can access only static variables or methods directly without creating object.ex:public static void main(String arg[])
Non-Static Methods can access both Static Variables & Static Methods as they Members of Class
Demo Code
public class Static_Class {
protected static String str;
private static int runningLoop;
static{
str = "Static Block";
}
/**
* Non-Static Method Accessing Static Member
*/
public void modifyStaticMember(){
str = "Non-Static Method";
}
/**
* Non-Static Method invoking Static Method
*/
public void invokeStaticMethod(){
String[] args = {};
if(runningLoop == 0){
runningLoop++;
main(args);
}
//Exiting as it will lead to java.lang.StackOverflowError
System.exit(0);
}
public static void main(String[] args) {
Static_Class instance = new Static_Class();
System.out.println(str);
instance.modifyStaticMember();
// Changed Value persists
System.out.println(str);
//Invoking Static Method
instance.invokeStaticMethod();
}
}
Look at it this way. A static variable can be accessed in many ways. One of the most common is to precede the var name with the class name, since static vars are per class.
Since you refer to this variable in the same class, you are exempt from having to precede it with the class name. It does not matter where you call the static variable.
Also this is a private static var not accessible by any other class.
Static variables are class variable not instance or local variable . that is why we can use static variable in non static method also. and static variables are not per object . static variables have one copy that will be used in entire program.
Static methods cannot modify Non-static fields since - For using a Non-Static field (outside the class) you must instantiate a class object,
But for using a Static method there is no need for object instantiation at all.
This is why it's not reasonable for a Non-Static Method (which not demands an object instantiation)
to modify a field that should be instantiated.
For this - Static methods can touch only static fields (or call other static methods).
But as you mentioned the other way around is possible,
A Non-Static method can modify a static field which is static for all objects of its class.
Static members are not instance members , these are shared by class , so basically any instance method can access these static members .
Yes, a static method can access a non-static variable. This is done by creating an object to the class and accessing the variable through the object. In the below example main is a static method which accesses variable a which is a non-static variable.
demo code:
public class Sample {
private int a;
void method()
{
System.out.println("i am a private method");
}
public static void main(String[] args)
{
Sample sample=new Sample();
sample.a=10;
System.out.println(sample.a);
}
}

Java error "Non static variable cannot be referenced from a static context" [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
java : non-static variable cannot be referenced from a static context Error
My aim is to create a program for client server chat.I wrote the following code https://github.com/jinujd/Java-networking/blob/master/Server.java
for the server.. After compilation I got the following error.
non-static variable this cannot be referenced from a static context.
What is the problem there?
My another doubt is that
/*A.java*/
class A {
String a;
class B {
}
public static void main() {
}
}
Is the variable a accessible to B and main() ?
Static functions/variables are associated with the class definition itself while class variables(non-static) are associated with class instance i.e. they are normally initialized when you instantiate an object from the class.
Static functions/variables can be used without class instance as:
A.main();
While to access non-static functions/variables, you need to create object instance first:
A a = new A();
a.getA();
Since static scope is up in the hierarchy(at definition level), and it doesn't have visibility of instance level methods/variables and hence complains. But opposite is OK i.e. you should be able to access static methods/variables from non-static methods.
Having explained the reason, I believe you would be able to correct the scope of the class/method/variable yourself.
You need
static class ClientReceiver extends Thread {
Not
class ClientReceiver extends Thread {
non-static variable this cannot be referenced from a static context. What is the problem there?
you need an instance of the class to access the non-static data from static context.
public class Sample {
String var="nonstatic variable";
public static void main(String...args){
Sample s= new sample();
system.out.println(s.var);
}
}
your class B can access your string a directly, but your static main method needs an instance of class A to access it.

Why can't we use 'this' keyword in a static method

class Sub {
static int y;
public static void foo() {
this.y = 10;
}
}
I understand that this represents the object invoking the method and that static methods are not bound to any object. But in the above mentioned case, the variable y is also static.
If we can invoke static method on class object, why can't we allow static methods to set the static variables of the class.
What is the purpose of this additional constraint?
Because this refers to the object instance. There is no object instance in a call of a static method. But of course you can access your static field (only the static ones!). Just use
class Sub {
static int y;
public static void foo() {
y = 10;
}
}
If you want to make sure you get the static field y and not some local variable with the same name, use the class name to specify:
class Sub {
static int y;
public static void foo(int y) {
Sub.y = y;
}
}
The main reason why we can not use "this" in static method context:-
this :- "this" means current class OBJECT , so its clear that "this" only come in
the picture once we intended to create an Object of that class.
static method:- there is no need to create an object in order to use static method.
means "instance" or object creation doesn't any sense with "static" as per Java rule.
So There would be contradiction,if we use both together(static and this) .
That is the reason we can not use "this" in static method.
this is referring to this instance of the object Sub. As the method is static, there is not an instance of Sub.
To make your code work write it like this:
class Sub {
static int y;
public static void foo() {
Sub.y = 10;
}
}
You can set static fields in static methods, but you don't have access to this in static method because this represents the current instance of the object, and in a static method you have no instance.
This means "this" object but there isn't one. In your case you can use the class name as #tibtof suggests.
"this" keyword is only applicable where an instance of an object is created. And in static method no instance is created because static method belongs to class area.
There is no problem with static methods setting values for static fields.
The only issue is usage of this keyword. Please note that since static methods are processed at the time of class loading, it's all but certain that no "this" exists at the point of time, which is why its only logical the usage of this keyword isn't allowed in a static context.
On the other hand, static method can be invoked from an object because it is made accessible to the object. The intention behind static data members and behaviours is to make it common to all the instances of that class.
Keyword "this" refers to the object that you are operation with. In your case this inside any non-static methods or constructor (if you have one and and if you use "this" inside that), then "this" refers to that particular instance of the class Sub.So it is applicable only when the object is created. But anything in the static context of a class, you can use without even creating object for that as it is resolved during the class loading. "this" resolved only when object is created ( you can even say dynamically for which object). So "this" make sense in static context. Hope it helps. God bless.
when we declare variable and method is static then this is share by among object where this keyword only pointing to current object. suppose you have created five object of class foo then only one copy of made of (int y) shred by all object.so if you access int y using this keyword then compiler get a ambiguity which object have to point because static int y is shared by all object . you have access static variable using class name.

Confusion with a class level and instance level

I have the following class:
public class B {
public void print() {
}
public static void main(String[] args) {
B B = new B();
B.print();
}
}
I was wondering why the compiler didn't give an error saying it's not a static method. How will it distinguish between the class level and instance level when we have the object with the same as the class?
Because you are accessing the method on an instance of the class. Incidentally the name of the instance is the same as the class name, but since you don't have a static method with this name, the compiler assumes the correct - i.e. an instance method.
If you define the method to be static, then it will again assume the only possible thing - calling a static method on the B class, because the instance doesn't have such a method.
And ultimately, you can't have both a static and a non-static method with the same name.
The JLS discusses and defines the precedence of scoping rules for such cases:
6.3.2 Obscured Declarations
A simple name may occur in contexts where it
may potentially be interpreted as the
name of a variable, a type or a
package. In these situations, the
rules of §6.5 specify that a variable
will be chosen in preference to a
type, and that a type will be chosen
in preference to a package. Thus, it
is may sometimes be impossible to
refer to a visible type or package
declaration via its simple name. We
say that such a declaration is
obscured.
There are other border cases, where variable can be shadowed or hidden. Example:
class Test {
static int x = 1;
public static void main(String[] args) {
int x = 0;
System.out.print("x=" + x);
System.out.println(", Test.x=" + Test.x);
}
}
Again, the compiler follows the JLS and resolves the name according to the spec. The compiler is not smart and does not "figure out" anything, it just follows the spec.
Your question is about the print() method? It works because your variable name is "hiding" the type name, so when you do B.print() it looks at the variable B, which is an instance of class B.
You really shouldn't be calling your variable the same name as the class, at least not with the same case. Things would be clearer for you if you renamed the variable, even if just to 'b'. So:
public class B{
public void print(){
}
public static void main(String[] args){
B b = new B();
b.print(); // This works
B.print(); // this fails
}
}
Because in that example, print() is a instance method. It is being called from an instance of the class B. If your main looked like this:
public static void main(String[] args){
print():
}
then print() would have to be a static method.
It also doesn't matter that your instance is named the same as the class. Since print() is an instance method, it will expect it to be called from an object. It just so happens that you have an object named B that is an instance of class B. Thus there is no problem.
I guess class names and instance variables do not share the same namespace; to the compiler, it is clear that B.print() is being called on the instance and not on the class.
No need to say that this is confusing and should be avoided in real code ;)

Categories