Java static method this reference

Why can a Java static method call a constructor, but not refer to this?

If it was impossible to call a constructor from a static method, then you could not construct any object ever.

3 Answers 3

1 — Static method cannot cannot call non-static methods.

Sure they can, but they need an object to call the method on.

In a static method, there’s no this reference available, so foo() (which is equivalent to this.foo() ) is illegal.

2 — Constructors are kind of a method with no return type.

If they should be compared to methods, I would say constructors are closer to non-static methods (since there is indeed a this reference inside a constructor).

Given this view, it should be clear to you why a static method can call a constructor without any problems.

is okay, since new Main() does not rely on any existing object.

is not okay since it is equivalent to this.k() and this is not available in your (static) main method.

What confuses people all the time is the fact that new main() is NOT a simple constructor call — it is the application of the unary operator new while specifying which constructor to call as a part of a much broader allocation+initialization procedure.

Do you really need it, since it’s obvious? Applying new allocates memory from the heap — that’s not written in the constructor, for one. It also calls all instance initializers — another fact surely obvious to you. That’s also not written anywhere in constructor code. It also calls the constructor with this suddenly defined — not by the caller, but by implicit code. Constructor is nothing but a callback, really.

I’m asking because I suspect that you’re making implementation specific assumptions regarding how Java is compiled and executed. Surely constructing an object involves running the instance initializers etc, but allocation procedure, how it ends up on something called the heap and how this suddenly materializes, I’m not sure is defined in the language specification. (I may be wrong though.)

OK, but the JLS also does not specify that new X() is a mere function call — and that’s the core of the point, since people routinely visualise it that way and make misguided comparisons to other types of functions in Java.

No. Constructors aren’t ordinary methods in this respect. The whole point of the constructor is to, well, construct a new instance of the class.

So it can be invoked in static scope too. Just think about it: if you needed an existing instance of your class in order to create a new instance of it, you would simply never be able to instantiate it ever.

Static method cannot cannot call non-static methods.

Not quite. You can call a nonstatic method from inside a static method, just you need to scope it to a specific object of that class. I.e.

would work perfectly in your code sample above.

would be fine inside an instance (nonstatic) method. And it would be equivalent to

The implied this refers to the current instance of the class. Whenever the compiler sees an unqualified call like k() within an instance method, it will automatically scope it with this. . However, since static methods aren’t tied to any instance of the class, you (and the compiler) can’t refer to this inside a static method. Hence you need to explicitly name an instance of the class to call an instance method on.

Rules are simple:
1 — Static method cannot cannot call non-static methods.

That’s simply not true. A static method can call a non-static method, just via a «target» reference. For example, this is fine in a static method:

Integer x = Integer.valueOf(10); int y = x.intValue(); // Instance method! 

The real point is «there’s no this reference within a static method».

2 — Constructors are kind of a method with no return type.

That’s not a really useful model, to be honest. It makes more sense (from the caller’s point of view) to consider a constructor as a static method with a return type that’s the same as the declaring class, but even that’s not a perfect model by any means.

I suggest you think of a constructor as a different type of member. Embrace the differences between constructors and methods, instead of trying to hide them.

Источник

Why can’t we use ‘this’ keyword in a static method

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?

I realize this is an ancient question but I want to +1 it as a pretty valid point. Although for fields the answer is simple (leave the qualifier out), for static inner classes it becomes relevant, and is also relevant when what you want is a reference to the runtime instance of the class itself. For example I can type ‘MyClass.class’ to get the singleton Class, but just ‘class’ by itself is invalid and there’s no similar workaround. This leads to the class name potentially being repeated through the unit which is not very DRY.

9 Answers 9

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

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:

The downvoters may have thought that this doesn’t really answer the question, because you basically repeated what the OP has already known and only provided a verbose workaround. If the class is named ThisClassHasAQuiteLongName , wouldn’t it be nicer to refer the class as this in static methods?

That’s not really true though, I have provide an explanation for why this can’t be used in static methods (because there is no instance of the class to be named this ) and showed two ways of accessing the fields. Being able to use this in a static context as a replacement of the class name would be missleading and inconsistent (at least imho). Thanks for your feedback though, that might as well have been the reason for the downvotes.

The question, as I understood it and which I also want to know, is why Java does not overload the meaning of this in a static context to mean the class, So instead of Sub.y one could type this.y . It would seem like an obvious design choice, because it eliminates the need to explicitly mention the class name, which could change. In general, when someone asks «why is x defined to be y but not also z in a different context» it is not satisfactory, and indeed kinda toxic and condescending to reply «because it’s defined to be y.» It made me feel dumb for wondering the same, as I still am.

@AndrewCone thanks for the feedback. You are making a very good point (on why I got downvoted). And on the topic: I think the reason is Java’s focus on having (or at least trying to have) a clean object oriented structure. When you overload a keyword, readability suffers. With the current definition, when you read this.y , you know, it’s a local variable and not a static variable. So it is cleaner.

Источник

How to access a static method via a class reference

It is only possible to access those methods using reflection. You cannot reference a class directly, only an instance of type Class.

To use reflection to invoke methodname(int a, String b):

Method m = clazz.getMethod("methodname", Integer.class, String.class); m.invoke(null, 1, "Hello World!"); 

You may want to think about your design again, to avoid the need to dynamically call static methods.

You can invoke a static method via reflection like this :

Method method = clazz.getMethod("methodname", argstype); Object o = method.invoke(null, args); 

Where argstype is an array of arguments type and args is an array of parameters for the call. More informations on the following links :

In your case, something like this should work :

Method method = clazz.getMethod("foo", null); method.invoke(null, null); // foo returns nothing 

You can leave the last null s in the last two lines away, as those methods are now declared as var-args methods.

You cannot access static methods without an explicit reference to the class.

No inheritance here, sorry, so you must either do:

If you really need it, you will have to do a check:

Object o = . // eith an A or B instance. if( o instanceof A ) < A.foo() >else

But why don’t you just make those functions instance functions, and let them implement an interface?

Okey, you have a class object. Then do:

Class c = . ; c.getMethod("foo").invoke(null); // null to invoke static methods 

I had the logic originally written for interfaces and my derived classes (‘A’ or ‘B’) cannot be instantiated since they were defined as inner classes and didn’t have a public class identifier, hence I had to resort to this technique.

@user339108 interfaces are the way to proceed here, just make sure A and B are not inner classes.

Interfaces can’t declare static methods. And for the last part, it’s better explained in at least two answers

According to my lack of knowledge the need for the requested construct is given by the fact that an interface doesn’t offer the possibility of static abstract methods. Here is an example:

public enum Cheese implements Yumy < GOUDA(49), ESROM(40), HWARTI(38); private int percentage; private Cheese(int fat100) constructor public void yamyam() // as in Yumy public static Cheese getByFat(int fat100) // no chance to be part of interface >; 

I hope this isn’t making too many assumptions or deviating too far from your question, but if your two classes share a common supertype and creating an instance is tolerable then you can:

  1. Implement a common interface
  2. Create an instance of the object via myClass.newInstance() (class must have an empty constructor)
  3. Call the static method from the instance object.
interface Foo < void foo(); >class A implements Foo class B implements Foo  public void something(Class clazz) < T myInstance = clazz.newInstance(); myInstance.foo(); >. something(A.class); 

It’s a little bizarre but in my case it proved to be useful, and I began by asking the very same question that you did.

Источник

how is this a static reference?

I am trying to access method moveThat from this class, but it keeps telling me cant access non static method moveThat from a static reference. I don’t see how this is a static reference?

4 Answers 4

How is CubeGui defined? The spelling suggests it’s a class name, in which case moveThat would have to be static to be accessed, since you didn’t create an instance of CubeGui .

it’s defined like this «public class CubeGui extends javax.swing.JFrame» CubeGui is a swing interface so I don’t want to create another instance of it. I thought it would be accesible from another public non static class without making another instance. Is there any way other than make moveThat() static?

I think what he means is, «How is the moveThat method defined?» If moveThat is non-static, you will need to either make it static, or create an instance of CubeGui in order to call it.

It sound like you want to pass the instance of CubeGui to this other class rather than make «moveThat» static.

To expand on one of my comments left on Konrad Rudolph’s answer.

My guess is that your CubeGui class declaration looks something like this:

public class CubeGui extends javax.swing.JFrame < public void moveThat() < // do stuff >>

It should look like this (notice the static reference on the moveThat method):

public class CubeGui extends javax.swing.JFrame < public static void moveThat() < // do stuff >>

Or you need the implementation of Solver to look like this:

If I don’t want to make it static, and go with the second option wouldn’t I end up with two different instances of Gui, then solver won’t be acting on my original Gui at all? Is there some way in which I can make outside public classes access public methods of the same instance of my Gui??

Yes, that is correct, my apologies for shortcut-ing my example. To operate on the same instance of CubeGui , you would need to pass in the instance as a parameter to the moveThat method.

moveThat is an instance method.

From your comments it sounds like CubeGui is a swing frame that you only open once, and you want to get a reference to that frame to call the moveThat method. The best way would be to pass a reference to your solver class:

private CubeGui gui; public Solver(CubeGui gui) < this.gui = gui; >void solveIt()

If that is really difficult in practice, you could consider making CubeGui a singleton (as much as that is rightly discouraged, sometimes it makes sense, as in this case where you don’t have more than one frame showing). To do this, you make the constructor of CubeGui private, and then add a method to CubeGui like this:

 private static CubeGui singleInstance; public static CubeGui getInstance() < if (singleInstance == null) < singleInstance = new CubeGui(); >return singleInstance; > 

Then in your solver you can do:

 CubeGui.getInstance().moveThat(); 

I’ll probably get a downvote for suggesting a Singleton. I might even deserve it, but it sounds like the question needs to know what that looks like. To counter balance that, see here.

So if at all possible, pass the object in as a parameter, either to the constructor, or to the method.

Источник

Читайте также:  Рамка вокруг таблицы
Оцените статью