I was helping a friend on his Java homework today, and I guess I didn't realize there being a difference between plain Java and Java in Android. Quick write up of the program:
public class myClass{
public static void Main (String[] args){
doThis();
}
public void doThis(){
System.out.println("Did this");
}
}
But when running that, I got a complaint that I needed to make the doThis() method to be static. Why is that? When I develop some basic things in Android, I never have to use the static keyword.
Note: This could stem from the fact that I'm intimidated by what static actually means.
Why is that?
Because Main() is static.
If Main() was an instance method, and you had called Main() on an instance of myClass (e.g., new myClass), then doThis() could also be an instance method. Or, if your static Main() created an instance of myClass, it could call doThis() on that instance.
When I develop some basic things in Android, I never have to use the static keyword.
That is because your entry points in Android tend to be instance methods on components (e.g., onCreate() of an Activity.
A static method is a method that is not invoked on any Object instance. A non-static method belongs to an object, and needs an object instance in order to be invoked. It's thus not legal to call an instance method from static method, since the static method is not invoked on any object.
You need to instanciate an object to call an instance method:
public static void main(String[] args){
MyClass object = new MyCLass();
object.doThis();
}
public void doThis(){
System.out.println("Did this");
}
Android code is Java code, and has exactly the same rule.
Read the Java tutorial about instance and static members.
The issue is you need to rewrite it like so:
public class MyClass{ //fixed camel casing, classes start with upper case
public static void main (String[] args){ //fixed lettering
MyClass mc = new MyClass();
mc.doThis();
}
public void doThis(){
System.out.println("Did this");
}
}
This is nothing special about the difference between Android and Java, both will fail. The problem is you are trying to reference a non-static method from a static context, this could cause issues, as static indicates that the class does not need to be instantiated to invoke a function.
Static methods can be called without having an instance of the owning class, so therefore you can do:
myClass.doThis();
Since your doThis() method isn't static, you'd have to create an instance object like so:
myClass instance = new myClass();
instance.doThis();
The main() method that is calling your doThis() method is a static method, and an instance of myClass isn't required for it to be called. This means that any methods being called by your main method must be static, or called on an instance object (see 2nd example above).
Related
I have created anonymous class by implementing interface I inside public static void main() method. So, by java 8 for the abstract method test(), the implementation is provided from imple() method of class C.
So, inside public static void main() method, printing _interface.getClass(), I got
package_path.Main$$Lambda$1/310656974 which is absolutely fine. Bacause it print's the anonymous class name.
Also, _interface is pointing to an anonymous object in heap and hence I'm doing _interface.test();
So, the first statement that test() method has now is to print the class name,
But eventually what it print was,
package_path.C (telling me C is the class name). How is that possible? Shouldn't package_path.Main$$Lambda$1/310656974 be printed again? Because 'this' means anonymous inside the test method right?
#java.lang.FunctionalInterface
interface I {
void test();
}
class C {
void imple() {
System.out.println(this.getClass());
System.out.println("Inside Implementation");
}
}
class Main {
public static void main(String[] args) {
I _interface = new C()::imple;
System.out.println(_interface.getClass());
_interface.test();
}
}
Hopefully, this might help you understand, that when you declare
I _interface = new C()::imple;
you've actually implemented the interface somewhat similar to (though not same as):
I _interface = new I() {
#Override
public void test() {
new C().imple(); // creating an instance of class `C` and calling its 'imple' method
}
};
Hence when the test method is called, it first creates an instance of C which prints
class x.y.z.C
as the class.
Because 'this' means anonymous inside the test method right?
Now as you can see above, there is no more anonymous class from which imple
is being called from, hence this is not representing the anonymous class anymore.
As Holger clarified in comments further, despite the representation as lambda or anonymous class at the calling site, the this.getClass() inside a method of class C will evaluate to C.class, regardless of how the caller looks like.
Recommend: Continue to read and follow on Is there any runtime benefit of using lambda expression in Java?
I know this is reference variable which holds the reference for object and static method loads when the class is first accessed by class loader, either to create an instance, or to access a static method or field.
Why its not allowed for this but for instance itself? For e.g.
Class A{
public static void main(String... args){
this.method(); //not allowed
new A().method(); //allowed, how?
}
void method(){
System.out.println("Class A");
}
}
this.method(); //not allowed
You have no instance this in static context so you can't invoke method.
new A().method(); //allowed, how?
You have instance created by new operator so that you can invoke a method.
To invoke a method without having a real instance you have to declare it as static. i.e.:
static void method(){
System.out.println(“Class A”);
}
this will work when calling just method() and via instance:
public class A {
public static void main(String[] argv) {
method(); //works because method is static
new A().method(); //still ok, we can call static method using an instance
this.method(); //not allowed, there is no 'this' in static context
}
static void method(){
System.out.println("Class A");
}
}
static variables and instance variables follow the initialization order you mention when they are initialized in their declarations. Also static initializer blocks follow that order.
Methods (including constructors) on the other hand need no initialization at runtime. They are fully defined at compile-time and therefore exist and can be called as soon as the class is loaded, also before the initialization is complete. Therefore there is no problem in your main method instantiating the class (calling the default constructor) and calling a method that is declared later, as method is declared below main.
In addition, the main method is also only executed after any static initialization is complete.
So I know that in Java when you have a static method you are supposed to call it with the format ClassName.method() rather than use the same structure as you would for instance methods, namely:
ClassName myObject = new ClassName();
myObject.method();
However, if you were to do it this way it would still be valid code and would work. Let's say I decide to do this where the method in question is static, and have the following setup:
public SuperClass {
public static int foo(int x) {
return x;
}
}
public SubClass extends SuperClass {
public static int foo(int x) { // Overriding foo() in SuperClass
return x + 1;
}
}
public MyDriver {
public static void main(String[] args) {
SuperClass myObject = new SubClass(); // Upcasting.
System.out.println(myObject.foo(5)); // This should polymorphically print 6
}
}
What prints out on the screen, however, is 5 rather than 6. Why?
Static methods apply only to the class they are defined in, and they cannot be overridden.
When you call myObject.foo(5), you are calling SuperClass.foo(5) in reality, because you declared myObject as a SuperClass, regardless of whether you instantiated it as one.
The proper way to call a static method is to call it directly from the class it is declared in, so if you wanted to call SubClass.foo(), you must call it from an explicitly declared SubClass instance (meaning no upcasting), or you need to call SubClass.foo() like so.
The simple answer is that calling static methods from instances evaluates to calling those same methods from the declared type with no instance rather than the instance type.
I am not certain of this, but I would not be surprised if when the code is compiled into byte-code, that the instance static method call would actually be compiled into a direct call to the declared type.
Edit: An upvote brought my attention back to this and I cleaned up the explanation to make it more clear and fix some negligible grammatical mistakes on my part. I hope this helps future readers.
Using instances of a class to call that class's static methods is something you should avoid, since it can cause confusion. If you need to call any method polymorphically, make it an instance method. You cannot polymorphically call a static method. The reason the SuperClass invocation is called is because that is the apparent class of myObject at compile-time. This effect can also be seen in the following scenario:
public void doSomething(SuperClass param) {
System.out.println("SuperClass");
}
public void doSomething(SubClass param) {
System.out.println("SubClass");
}
public void test() {
SuperClass myObject = new SubClass();
doSomething(myObject);
}
If test() is called, SuperClass will be printed.
Static methods don't depends on the instance, they belong to the class and only to the class, in fact if you have a static method you'll always access to one unique instance always.
myObject.foo(5)
is only a shortcut, what you really are doing is
SuperClass.foo(5)
Static methods are treated as global by the JVM, they are not bound to an object instance at all. By the way, you can only overload static methods, but you can not override. So check for "Oracle Documentation for Overriding and Hiding Documents".
Defining a Method with the Same Signature as a Superclass's Method:
-----------------------------------------Superclass Instance MethodSuperclass Static Method
Subclass Instance Method Overrides Generates a compile-time error
Subclass Static Method Generates a compile-time error Hides
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can we override static method in Java?
We cannot override the static methods of the base class.
Actually I tried something like this:
// Base class
public class StaticExampleImpl {
protected String name="overriding";
public static void display(){
System.out.println("static method display : base class");
}
}
Then the derived class is as follows:
//derived class
public class StaticDemo extends StaticExampleImpl {
// cannot override the static methods...
//#Override
public static void display(){
System.out.println("child!!! static method display");
}
public static void main(String[] args) {
StaticDemo d=new StaticDemo();
d.display(); // derived class display is called rather than Base class.
}
}
So, when I uncomment the #Override method, it gives error as "Static methods cannot be overriden". But with commenting it works fine. So, when we create the Objects and call the static methods with the instances, those work fine. so what is the difference??
because static methods are not get inherited.
When you uncomment #Override it means you are trying to override the
static method which is not possible thats why you are getting an
error.
But when you comment //#Override it means you are declaring a new
method in child class.
Static methods does not belong to an instance of a class, it belongs to the actual class.
When you call d.display();, you are really calling the static method of the StaticDemo d reference's static method.
if you did :
StaticExampleImpl d2 = new StaticDemo();d2.display(), you will find that it calls the base class's display.
However, don't do this. It leads to confusing code, and is a bad way to implement inheritance poorly.
Overriding depends the an instance of a class. polymorphismis that you can subclass a class and the objects implementing those subclasses will have different behaviors for those method defined in the superclass (and overridden in the subclasses) .static methods does not belong to an instance of a class so the concept is not applicable.
Static methods cannot be inherited. If you want to call the 'base' class static method, you have to explicitely call StaticExampleImpl.display().
Static methods are bound to class they can't be inherited thats why you can't have base class static method in derived class.
If you are trying to override a static method, there is probably something wrong with your design.
OOP and Polymorphism allows you to do the following:
public class MyClass1 {
public String toString() { return "MyClass1 Instance"; }
}
public class MyClass2 extends MyClass1 {
#Override
public String toString() { return "MyClass1 Instance"; }
}
public void printSomething(MyClass1 myclass1){
System.out.println(myclass1);
}
Inside printSomething, the toString method which is going to be called is the one on the runtime type of myClass1: when you pass inside printSomething an instance of MyClass2, its compile-type will be MyClass1 but its runtime type will be MyClass2
It is clear that to use polymorphism you need objects instances, where the actual runtime type could different from the compile type. Static methods however do not belong to any object instance, but to the class. Why don't you explain us what you are trying to achieve?
The following code:
StaticExampleImpl one = new StaticExampleImpl();
StaticDemo two = new StaticDemo();
StaticExampleImpl three = two;
one.display();
two.display();
three.display();
Will yield the following output:
static method display : base class
child!!! static method display
static method display : base class
As you can see, the method does not get inherited. This is why they are called 'static methods': they are called statically, not dynamically, as instance methods would be. The compile-time type of the class is what matters when calling static methods, not the runtime type.
This is also why you shouldn't call static methods through object instances. Always call them like this:
StaticExampleImpl.display();
StaticDemo.display();
This completely takes away the confusion that might (will) come up when people expect inheritance to work for these methods.
any static block in java, may be static variables, methods are loaded when the class is loaded. You probably know about class loader in java. So thing is static block (methods, variables or anything is static) is loaded once. So you can’t actually override any static block.
Commenting #Override means that you are writing another static method in sub class, but not just overriding base class method.
I've been programming for years using .NET and I'm taking the plunge into Java with some simple starter programs.
I'm having a bit of trouble though...
When I create my start-up class with public void main, the compiler won't let me instantiate any of the classes I've written?
The error I'm getting is "non-static variable _processor cannot be referenced from a static context" where _processor is the object I'm trying to instantiate from the Processor class that I wrote.
The program will compile and run just fine when I change Processor to a static class, but I don't want to have to make all of my classes static.
Any way around this?
Thanks in advance!
Here's everything I've written. It won't compile in the current state:
class Lab
{
public static void main(String[] args)
{
Processor proc = new Processor();
proc.Go();
}
private class Processor
{
private Random _rand = new Random();
public void Processor() {}
public void Go()
{
}
}
}
Is Processor an inner class of Lab by any chance? (yes, now that you published your code, my suspicion is confirmed).
In Java, nonstatic inner classes contain an implicit reference to the containing object of the outer class, so they can't be instantiated from static context (from your main method).
So
either create an instance of Lab (e.g. myLab), and then call myLab.new Processor(), or
declare Processor static (as you did), or
turn Processor into a top level class.
Is this your problem, by any chance?
public class DemoClass{
String field;
public static void main(String[] args){
field = "Hey"; //forbidden - can't access instance field from static context
DemoClass dc = new DemoClass();
dc.field = "Hey"; //this is ok
}
}
You should call a constructor from main:
public static void main(String[] args){
new MyClass();
}
And put your instantiations in the constructor.
but I don't want to have to make all of my classes static.
Most inner classes in Java are static, in my experience. If you can write an inner class in a separate file (it does not use directly the members of the containing class), it should then be defined as static. It really is only for convenience that Java lets you write inner static classes inside other classes.
Your process class is an inner class of your lab class, you can't create an instance of your process class until you instantiate an instance of you lab class, unless that inner class is static or something.
Main will run in your lab class, because it is static, but when you attempt to create an instance of the private inner class, you can't because this class is a "private inner" class of Lab, and you don't have a lab instance, so you can't reference it directly.
You can try making your processor class static, or at the very least public, or better yet you can instantiate an instance of your lab class first, and reference creation of the processor class through your instantiate lab class.