I'm sure you all know the behaviour I mean - code such as:
Thread thread = new Thread(); int activeCount = thread.activeCount();
provokes a compiler warning. Why isn't it an error?
EDIT:
To be clear: question has nothing to do with Threads. I realise Thread examples are often given when discussing this because of the potential to really mess things up with them. But really the problem is that such usage is always nonsense and you can't (competently) write such a call and mean it. Any example of this type of method call would be barmy. Here's another:
String hello = "hello"; String number123AsString = hello.valueOf(123);
Which makes it look as if each String instance comes with a "String valueOf(int i)" method.
Java syntax allows calling static methods from an instance. For example, we could create this code and it would compile and run correctly: public static void main(String args) { Example ex = new Example();
A static method cannot access a class's instance variables and instance methods, because a static method can be called even when no objects of the class have been instantiated. For the same reason, the this reference cannot be used in a static method.
In order to call an instance method, you need an instance. So a static method can call an instance method as long as it has a reference to an instance to call it on.
Within a static method, you do not have an instance of the class. So it will be impossible to call an instance method on an instance when no instance exists.
Basically I believe the Java designers made a mistake when they designed the language, and it's too late to fix it due to the compatibility issues involved. Yes, it can lead to very misleading code. Yes, you should avoid it. Yes, you should make sure your IDE is configured to treat it as an error, IMO. Should you ever design a language yourself, bear it in mind as an example of the kind of thing to avoid :)
Just to respond to DJClayworth's point, here's what's allowed in C#:
public class Foo { public static void Bar() { } } public class Abc { public void Test() { // Static methods in the same class and base classes // (and outer classes) are available, with no // qualification Def(); // Static methods in other classes are available via // the class name Foo.Bar(); Abc abc = new Abc(); // This would *not* be legal. It being legal has no benefit, // and just allows misleading code // abc.Def(); } public static void Def() { } }
Why do I think it's misleading? Because if I look at code someVariable.SomeMethod()
I expect it to use the value of someVariable
. If SomeMethod()
is a static method, that expectation is invalid; the code is tricking me. How can that possibly be a good thing?
Bizarrely enough, Java won't let you use a potentially uninitialized variable to call a static method, despite the fact that the only information it's going to use is the declared type of the variable. It's an inconsistent and unhelpful mess. Why allow it?
EDIT: This edit is a response to Clayton's answer, which claims it allows inheritance for static methods. It doesn't. Static methods just aren't polymorphic. Here's a short but complete program to demonstrate that:
class Base { static void foo() { System.out.println("Base.foo()"); } } class Derived extends Base { static void foo() { System.out.println("Derived.foo()"); } } public class Test { public static void main(String[] args) { Base b = new Derived(); b.foo(); // Prints "Base.foo()" b = null; b.foo(); // Still prints "Base.foo()" } }
As you can see, the execution-time value of b
is completely ignored.
Why should it be an error? The instance has access to all the static methods. The static methods can't change the state of the instance (trying to is a compile error).
The problem with the well-known example that you give is very specific to threads, not static method calls. It looks as though you're getting the activeCount()
for the thread referred to by thread
, but you're really getting the count for the calling thread. This is a logical error that you as a programmer are making. Issuing a warning is the appropriate thing for the compiler to do in this case. It's up to you to heed the warning and fix your code.
EDIT: I realize that the syntax of the language is what's allowing you to write misleading code, but remember that the compiler and its warnings are part of the language too. The language allows you to do something that the compiler considers dubious, but it gives you the warning to make sure you're aware that it could cause problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With