Related
I already tried to search for an answer on the "using the new keyword" but didn't found an answer on my specific question.
Why do some classes have to be created with the keyword new and some don't
For example :
import java.io.BufferedReader
If you want to use this you have to create a new instance
BufferedReader read = new BufferedReader (..............)
But for example with system.console which also needs an import java.io.console. when you want to use this you can just type Console c = system.console()
i'm a beginner in Java and OO programming and found a couple of this examples troughout my book.
Thx for the help
In java, fields(aka Attributes) are always associated to either instance or to class.
There could be many instances of a class and to create instance you have to use new operator. To access instance related attributes, you will need to create one and this will be accessed as
ClassName instanceName = new ClassName();
instanceName.methorOrAttributeNameGoesHere
For class associated attribute aka Static attribute can be direcly accessed as ClassName.methorOrAttributeNameGoesHere
These are very basics of Java and probably you should first read some good book on Java and OOP like 'Head First Java'
The simple answer to this is that instantiation like new BufferedReader() always creates a different instance each time you call it; invoking a method like System.console() might or might not give you different instance.
Ultimately, all objects are instantiated via new; you just might not see it in your code.
Here are a couple of ways in which System.console() might be implemented (totally simplified, not actually like it is):
// (1) Returns new instance each time
class System {
static Console console() {
return new Console();
}
}
or
// (2) Returns same instance each time
class System {
private static final Console CONSOLE = new Console();
static Console console() {
return CONSOLE;
}
}
(There are infinitely more ways to implement it, these are just two examples. You can see the way it is implemented in OpenJDK by looking at the source code - it is similar to (2), in that the same instance is returned each time, just with a few more complications that I don't want to describe here)
In (1), if you invoke System.console() twice, you will get back two different instances of Console:
System.console() != System.console()
In (2), if you invoke System.console() twice, you will get back the same instance of Console:
System.console() == System.console()
The question I would ask here is do I need to care if I get back different instances or the same instance? The answer is probably not, if the API designer has done a reasonable job.
The decision as to whether expose the creation of a new Console was made by the person who wrote the classes. There are a number of reasons why he/she might not want you to create a different instance each time you invoke that method, e.g.:
The thing you are creating might be very expensive (slow, takes up lots of resources etc), so you don't want to create lots of them;
The thing you want has logically just one instance (it is a singleton).
There are a number of reasons why he/she might want you to create a separate instance each time you invoke that method, e.g.:
You don't want all of the places using that instance to share state. You have to worry about things like thread safety when instances of mutable classes are shared.
And there are a number of reasons why you might not want the user to invoke the constructor directly:
new Console() creates an instance of Console exactly; things like consoles are often platform-dependent, so you might actually want an instance of WindowsConsole, MacConsole etc to be returned when run on Windows, MacOS etc. If WindowsConsole and MacConsole extend Console, either of these can be returned from the System.console() method.
Prior to the introduction of the diamond operator <> in Java 7, it was necessary to include the full generic parameters in the new statement, e.g. ArrayList<HashMap<String, List<String>>> list = new ArrayList<HashMap<String, List<String>>>();; however, generic methods allowed this to be written as ArrayList<HashMap<String, List<String>>> list = newList():
<T> List<T> newList() { return new ArrayList<T>(); }
(Sometimes, you need a lot of parameters to pass to the constructor, and it is convenient to use the Builder Pattern. This isn't relevant to the cases in the question, but it is a reason for not invoking the constructor directly.)
The thing is that these are internal implementation details, and should be encapsulated: you, as a user of the Console class, shouldn't need to care about how expensive it is to create, or whether there is shared state: you just want a Console.
This encapsulation is effected by providing a method like System.console(): you don't need to know whether the method is implemented like (1) or (2) above (or any other method).
Additionally, if the class is originally written like (1), and that proves to be problematic, its implementation can be changed to (2) without you, as a user of the System class, needing to update your code.
This might be a bit too much detail for a beginner, and I can try to help you understand more; the long and short of it is that sometimes it is be better if you don't create instances directly.
System.console,console is static thats why we are calling it with class name directly,and to call the non static method we generally used the objectname.methodname .
The java.io.Console class is attached with system console internally.System class provides a static method console() that returns the unique instance of Console class.Thats why we used to do as Console c = system.console();
Please read about Static classes and non static classes method invocation/instance creation for more details.
Static methods don't require an instance, but non-static methods do. System.console() is static, butnew BufferedReader(...).read(...) is not
Static methods are typically used when the outcome of the method will never change based on the context. For instance:
Math.abs(-3); //will always be 3, no matter what
However consider this class:
public class Person {
private String name;
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
/*
* In this world, no special characters are allowed in a person's name
*/
public static boolean isValidName(String name) {
if (name.contains("!#$%&(=?") {
return false;
}
return true;
}
}
Person mySister = new Person("Mary");
Person myBrother = new Person("David");
Calling Person.getName() doesn't make any sense; this is like asking "What is a person's name?" without specifying who the person is. Now if you ask me "What is your sister's name?", then I can call mySister.getName() and give you a sensible answer.
Re: your comment "how do you know when to not use new"
If you are trying to create a new Person object (imagine you just had a baby), but you are wondering whether or not that amazing name you found on the internet will be accepted by the authorities:
boolean validName1 = Person.isValidName("LordVoldeMort!!!!!"); //returns false
boolean validName2 = Person.isValidName("HarryPotter2016"); //returns true
Person myLittleBabySon = new Person("HarryPotter2016"); //Accepted by authorities
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.
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.
They cannot make it an error anymore, because of all the code that is already out there.
I am with you on that it should be an error.
Maybe there should be an option/profile for the compiler to upgrade some warnings to errors.
Update: When they introduced the assert keyword in 1.4, which has similar potential compatibility issues with old code, they made it available only if you explicitly set the source mode to "1.4". I suppose one could make a it an error in a new source mode "java 7". But I doubt they would do it, considering that all the hassle it would cause. As others have pointed out, it is not strictly necessary to prevent you from writing confusing code. And language changes to Java should be limited to the strictly necessary at this point.
Short answer - the language allows it, so its not an error.
The really important thing, from the compiler's perspective, is that it be able to resolve symbols. In the case of a static method, it needs to know what class to look in for it -- since it's not associated with any particular object. Java's designers obviously decided that since they could determine the class of an object, they could also resolve the class of any static method for that object from any instance of the object. They choose to allow this -- swayed, perhaps, by #TofuBeer's observation -- to give the programmer some convenience. Other language designers have made different choices. I probably would have fallen into the latter camp, but it's not that big of a deal to me. I probably would allow the usage that #TofuBeer mentions, but having allowed it my position on not allowing access from an instance variable is less tenable.
Likely for the same logical that makes this not an error:
public class X
{
public static void foo()
{
}
public void bar()
{
foo(); // no need to do X.foo();
}
}
It isn't an error because it's part of the spec, but you're obviously asking about the rationale, which we can all guess at.
My guess is that the source of this is actually to allow a method in a class to invoke a static method in the same class without the hassle. Since calling x() is legal (even without the self class name), calling this.x() should be legal as well, and therefore calling via any object was made legal as well.
This also helps encourage users to turn private functions into static if they don't change the state.
Besides, compilers generally try to avoid declaring errors when there is no way that this could lead to a direct error. Since a static method does not change the state or care about the invoking object, it does not cause an actual error (just confusion) to allow this. A warning suffices.
The purpose of the instance variable reference is only to supply the type which encloses the static. If you look at the byte code invoking a static via instance.staticMethod or EnclosingClass.staticMethod produces the same invoke static method bytecode. No reference to the instance appears.
The answer as too why it's in there, well it just is. As long as you use the class. and not via an instance you will help avoid confusion in the future.
Probably you can change it in your IDE (in Eclipse Preferences -> Java -> Compiler -> Errors/Warnings)
There's not option for it. In java (like many other lang.) you can have access to all static members of a class through its class name or instance object of that class. That would be up to you and your case and software solution which one you should use that gives you more readability.
It's pretty old topic but still up-to-date and surprisingly bringing higher impact nowadays. As Jon mentioned, it might be just a mistake Java's designers made at the very beginning. But I wouldn't imagine before it can have impact on security.
Many coders know Apache Velocity, flexible and powerful template engine. It's so powerful that it allows to feed template with a set of named objects - stricly considered as objects from programming language (Java originally). Those objects can be accessed from within template like in programming language so for example Java's String instance can be used with all its public fields, properties and methods
$input.isEmpty()
where input is a String, runs directly through JVM and returns true or false to Velocity parser's output). So far so good.
But in Java all objects inherit from Object so our end-users can also put this to the template
$input.getClass()
to get an instance of String Class.
And with this reference they can also call a static method forName(String) on this
$input.getClass().forName("java.io.FileDescriptor")
use any class name and use it to whatever web server's account can do (deface, steal DB content, inspect config files, ...)
This exploit is somehow (in specific context) described here: https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
It wouldn't be possible if calling static methods from reference to the instance of class was prohibited.
I'm not saying that a particular programming framework is better than the other one or so but I just want to put a comparison. There's a port of Apache Velocity for .NET. In C# it's not possible to call static methods just from instance's reference what makes exploit like this useless:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
I just consider this:
instanceVar.staticMethod();
to be shorthand for this:
instanceVar.getClass().staticMethod();
If you always had to do this:
SomeClass.staticMethod();
then you wouldn't be able to leverage inheritance for static methods.
That is, by calling the static method via the instance you don't need to know what concrete class the instance is at compile time, only that it implements staticMethod() somewhere along the inheritance chain.
EDIT: This answer is wrong. See comments for details.
Is there any way to get a classes declared fields (and methods) in the order of declaration using reflection? According to the documentation, the ordering of Methods and Fields returned by getFields(), getDeclaredFields(), etc. is undefined.
Specifying something like an index would be possible using annotation as suggested in Java reflection: Is the order of class fields and methods standardized?
Are there any better options, i.e. not having to specify the index manually?
Now before you ask what I need this for: we have a method that takes a quite big data structure as input and performs a lengthy calculation on it. To create unit tests, we made a method that takes an input object and an output instance and creates the Java source code (setting up input, invoking the calculation method, and asserting the correct results afterwards) as output. This code is much more readable when fields are written in declaration order.
With jdk 6, the reflected fields are in deed in their declaration order. In early jdk that wasn't the case. Apparently enough people have nagged.
Although not guaranteed by javadoc, I would still take this order as granted, and I assume the order will be kept in future jdks too.
In your app, like in most apps, the dependency on the declaration order is mostly vanity - your app won't fail if the order screws up, it just become a little uglier.
I had this as an isolated problem, look at
https://github.com/wmacevoy/kiss/blob/master/src/main/java/kiss/util/Reflect.java
and the method
public static Method[] getDeclaredMethodsInOrder(Class clazz)
It gets the order by looking at the bytecode of the class. If you just want to use the libray, is would be
kiss.util.Reflect.getDeclaredMethodsInOrder(Test.class)
No, not possible with reflection. You could however solve it using a ProcessBuilder and the javap command:
Given a Test.java:
public abstract class Test {
public void method1() {
}
public void method2() {
}
public static void main(String[] args) {
}
public String method3() {
return "hello";
}
abstract void method4();
final int method5() {
return 0;
}
}
The command javap Test prints:
...
public Test();
public void method1();
public void method2();
public static void main(java.lang.String[]);
public java.lang.String method3();
abstract void method4();
final int method5();
...
I'm afraid it's impossible without modifying the compilation process. Normally, the field get written into the classfile in any order and the information about the declaration order gets lost.
Most probably you could use an annotation processor to write the order in an auxiliary file.
It should be quite easy. Look e.g. at interfacegen for an example, how an annotation processor can work. You may want to put the information in the same file, but this is much harder.
You may think about using Javadoc with a custom Doclet, but this requires the source to be available.
There still is no guarantee about the order in the API (methods, fields, but every javadoc output I've ever seen has them in the right order, so I suppose the doclets get them in declaration order.
You won't be able to get the information from the class file. As Adam said in an answer to the refrenced other question:
The elements in the array returned are not sorted and are not in any particular order.
And "no order" includes "no declaration order".
I once used a Java source file parser to get input data for code generators. And this way you'll have fields and methods in declaration order.
I have long java class and method names
LONGGGGGGGGGGGGGGGClass.longggggggggggggggggggggggggMethod();
I want to alias it to
g.m(); in another class
can this be done?
No.
Wrap it in a method with a name you like better.
For one thing, you should rarely be typing the class name. You might have something like this:
import DamnLongPackageNameThatIDontLikeTyping;
class MyCoolClass()
{
DamnLongClassNameThatIDontLikeTyping dlc=new DamnLongClassNameThatIDontLikeTyping();
dlc.this();
dlc.that();
dlc.tOther();
dlc.damnLongAnnoyingMethodNameStillHasToBeTypedEveryTime();
}
Okay, so that's not great, but you shouldn't be typing the entire class name very often, just when you first declare it; and the package import makes it so you don't have to type: DamnLongPackageNameThatIDontLikeTyping.DamnLongClassNameThatIDontLikeTyping every time.
Still, that can be annoying to type. Enter the editor. If you aren't using Eclipse, Netbeans or IntelliJ then you really need to stop reading right now and go install it--load up your project. I'll wait....
Seriously. Go get it. The rest of this won't be any fun without it.
Now, the really neat thing is that to get what I typed above, you just do this:
class MyCoolClass()
{
DLC<ctrl-space>
After typing that, your file will look like this:
import DamnLongPackageNameThatIDontLikeTyping;
class MyCoolClass()
{
DamnLongClassNameThatIDontLikeTyping<your cursor here>
Note that you didn't type damn long ANYTHING, just DLC It figured out what class you wanted to import, added an import for it and stuck the class in there. (You may have to choose from a list of classes if there is more than one match).
On top of that, once you have an object named dlc instantiated you can type:
dlc.<ctrl-space> and get a list of methods in that class. NEVER AGAIN TYPE A METHOD NAME. If there are a kagillion methods in your class, don't scroll over them, type: dlc.dLAM<ctrl-space> to get dlc.damnLongAnnoyingMethodNameStillHasToBeTypedEveryTime();
Never type a long method name again.
No long method names, no long class names, no long package names. Yet you get extremely readable methods, packages and classes. This is why java programmers tend to use these long names, we also try to remember that we are coding for the next guy and don't want him to have to run all over our code trying to figure out what:
g.m(); refers to -- forcing them to remember that in this class it means GreatClass.motion, but in the next class it means Grey.modifyColor -- that would be really cruel.
Java being statically typed places a LOT of power into the editor. It can do things that you can't even dream of doing with dynamically typed languages, and you should play to the strength of your language to be an effective programmer -- not try to fit each language into some style you learned from using another language.
Note that this works for static methods as well...
DLC<ctrl-space>.dLM<ctrl-space> would be replaced by a call to DamnLongClass.damnLongMethod(), and it would even include the parens for you in 9 keystrokes.
The Java language provides no aliasing mechanism.
However, you could ease your "pain" somewhat by some combination of the following:
For static methods, you can use static imports to avoid having the long class name.
You could declare your own convenience class with a short name and short method names, and implement the static methods to delegate to the real methods like:
public static void shortName(...) {
VeryLongClassName.veryLongMethodName(...);
}
For regular methods, you could implement a Wrapper class, or a subclass with more convenient method names. However, both have downsides from the maintenance and (depending on your JVM) performance perspectives.
In Java 8 and later, you could potentially take a method reference, assign it to a named variable, and use that to make your calls.
But lets step back:
If the real problem is that you are just fed up with typing long names, a solution is to use a modern IDE that supports completion of names as you type them. See #BillK's answer for example.
If the real problem is that you are fed up with the long names taking to much space, a solution is to use a wider screen / longer lines. Most monitors are big enough to display 120 character (or more) wide source code with no eye strain.
If neither of the above is the answer, consider just refactoring the offending code to use sensible (i.e. shorter) class and method names. Once again, a modern IDE can handle this kind of refactoring quickly and safely.
On the last point, I would consider that the overly long class names and method names are bad style. IMO, you are justified in taking the time to fix them yourself, or suggesting that they be fixed, especially if they constitute a "public" API for some library or module.
To those who would argue that long identifiers are good style because they convey more information, the counter argument is that they don't actually improve readability. But if you say that they do improve readability, then it follows that using aliases instead of the long identifiers would be reducing readability!
Actually there is a way to get 1/2 of what you're after.
Looking at your example:
LONGGGGGGGGGGGGGGGClass.longggggggggggggggggggggggggMethod();
It appears that longggggggggggggggggggggggggMethod is static. (If it weren't, you'd be prefixing it with a variable name, which you control the size of.)
You can use Java's static import feature to 'alias' or import the static methods of the LONGGGGGGGGGGGGGGGClass into your own class' namespace. Instead of the above code, you would only have to write this:
longggggggggggggggggggggggggMethod();
You can use inheritance or encapsulation to wrap the original class.
class g extends LONGCLASS
{
void a() { super.loooonnng(); }
}
or
class g
{
private LONGCLASS lc;
void a() { lc.loooonnng(); }
}
Not supported in Java.
There is an enhancement ticket (7166917) for adding aliases for imports which would be helpful. The idea is this :
import a.very.lng.pckage.* as shortpckg
import my.pckage.IsAVeryLongClassName as MyShort
public class Shorten
{
public static final Shorten m = new Shorten();
public int a(params)
{
return some_method_with_long_name(params);
}
public void b()
{
// whatever static code you want
}
}
In your main code then:
import static mypackage.Shorten.m;
...
int res = m.a(params);
m.b();
...
This way you effectively alias any static stuff you want, while avoiding warnings.
I only ran a simple test but I defined an inner class variable. I'm not an expert nor do I know the consequences of doing this but I obtained positive results.
package a.b;
public class Library {
public static String str;
}
Now write a class to access the static variables from Library
package a.b;
public class Access {
public class Short extends Library {}
Short.str;
}
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.
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.
They cannot make it an error anymore, because of all the code that is already out there.
I am with you on that it should be an error.
Maybe there should be an option/profile for the compiler to upgrade some warnings to errors.
Update: When they introduced the assert keyword in 1.4, which has similar potential compatibility issues with old code, they made it available only if you explicitly set the source mode to "1.4". I suppose one could make a it an error in a new source mode "java 7". But I doubt they would do it, considering that all the hassle it would cause. As others have pointed out, it is not strictly necessary to prevent you from writing confusing code. And language changes to Java should be limited to the strictly necessary at this point.
Short answer - the language allows it, so its not an error.
The really important thing, from the compiler's perspective, is that it be able to resolve symbols. In the case of a static method, it needs to know what class to look in for it -- since it's not associated with any particular object. Java's designers obviously decided that since they could determine the class of an object, they could also resolve the class of any static method for that object from any instance of the object. They choose to allow this -- swayed, perhaps, by #TofuBeer's observation -- to give the programmer some convenience. Other language designers have made different choices. I probably would have fallen into the latter camp, but it's not that big of a deal to me. I probably would allow the usage that #TofuBeer mentions, but having allowed it my position on not allowing access from an instance variable is less tenable.
Likely for the same logical that makes this not an error:
public class X
{
public static void foo()
{
}
public void bar()
{
foo(); // no need to do X.foo();
}
}
It isn't an error because it's part of the spec, but you're obviously asking about the rationale, which we can all guess at.
My guess is that the source of this is actually to allow a method in a class to invoke a static method in the same class without the hassle. Since calling x() is legal (even without the self class name), calling this.x() should be legal as well, and therefore calling via any object was made legal as well.
This also helps encourage users to turn private functions into static if they don't change the state.
Besides, compilers generally try to avoid declaring errors when there is no way that this could lead to a direct error. Since a static method does not change the state or care about the invoking object, it does not cause an actual error (just confusion) to allow this. A warning suffices.
The purpose of the instance variable reference is only to supply the type which encloses the static. If you look at the byte code invoking a static via instance.staticMethod or EnclosingClass.staticMethod produces the same invoke static method bytecode. No reference to the instance appears.
The answer as too why it's in there, well it just is. As long as you use the class. and not via an instance you will help avoid confusion in the future.
Probably you can change it in your IDE (in Eclipse Preferences -> Java -> Compiler -> Errors/Warnings)
There's not option for it. In java (like many other lang.) you can have access to all static members of a class through its class name or instance object of that class. That would be up to you and your case and software solution which one you should use that gives you more readability.
It's pretty old topic but still up-to-date and surprisingly bringing higher impact nowadays. As Jon mentioned, it might be just a mistake Java's designers made at the very beginning. But I wouldn't imagine before it can have impact on security.
Many coders know Apache Velocity, flexible and powerful template engine. It's so powerful that it allows to feed template with a set of named objects - stricly considered as objects from programming language (Java originally). Those objects can be accessed from within template like in programming language so for example Java's String instance can be used with all its public fields, properties and methods
$input.isEmpty()
where input is a String, runs directly through JVM and returns true or false to Velocity parser's output). So far so good.
But in Java all objects inherit from Object so our end-users can also put this to the template
$input.getClass()
to get an instance of String Class.
And with this reference they can also call a static method forName(String) on this
$input.getClass().forName("java.io.FileDescriptor")
use any class name and use it to whatever web server's account can do (deface, steal DB content, inspect config files, ...)
This exploit is somehow (in specific context) described here: https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
It wouldn't be possible if calling static methods from reference to the instance of class was prohibited.
I'm not saying that a particular programming framework is better than the other one or so but I just want to put a comparison. There's a port of Apache Velocity for .NET. In C# it's not possible to call static methods just from instance's reference what makes exploit like this useless:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
I just consider this:
instanceVar.staticMethod();
to be shorthand for this:
instanceVar.getClass().staticMethod();
If you always had to do this:
SomeClass.staticMethod();
then you wouldn't be able to leverage inheritance for static methods.
That is, by calling the static method via the instance you don't need to know what concrete class the instance is at compile time, only that it implements staticMethod() somewhere along the inheritance chain.
EDIT: This answer is wrong. See comments for details.