Can we call a static method without mentioning the class name in Java?
Yes you can. Check out static imports. You have to mention the class name in the import statement, but after that you don't have to.e.g. from the linked article:
import static java.lang.Math.abs;
import static java.lang.Math.max;
int xDist = abs(destination.getX() - x);
int yDist = abs(destination.getY() - y);
return max(xDist, yDist);
Introduced in Java 5.
Yes, you can call a static method without mentioning the class name. There's the import static (see JLS 7.5.4 for exact mechanism), but even without it, if the name can be resolved (see JLS 15.12.1 for exact mechanism) without fully qualifying the class, it will work.
The following code compiles and prints "Hello world!" as expected.
import static java.lang.System.out;
public class Test {
static String greeting() {
return "Hello world!";
}
public static void main(String[] args) {
out.println(greeting());
}
}
out in the println statement is actually a static field access of the class java.lang.System, not a static method, but it's a static member access nonetheless. greeting() is a static method invocation, and the class name can be omitted since its reference can be resolved without fully qualifying the name.
Now let's ask if this is a good idea. Unless you're calling a static method from within its class, IT'S NOT a good idea generally to omit the class name!!!
Let's focus on static import first. A quote from the guide:
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Readers of your code (including you, a few months after you wrote it) will not know which class a static member comes from. Importing all of the static members from a class can be particularly harmful to readability; if you need only one or two members, import them individually. Used appropriately, static import can make your program more readable, by removing the boilerplate of repetition of class names.
The case is made stronger by the following example:
class Base {
void task1() {
System.out.println("Base.task1");
}
static void task2() {
System.out.println("Base.task2");
}
}
class Child extends Base {
void task1() {
System.out.println("Child.task1");
}
static void task2() {
System.out.println("Child.task2");
}
}
//....
Base sweetChildOMine = new Child();
sweetChildOMine.task1(); // prints "Child.task1"
sweetChildOMine.task2(); // prints "Base.task2"
What a surprise! You'd think that since sweetChildOMine has a reference to an instance of Child, sweetChildOMine.task2() should print "Child.task2" because it's overridden by Child class, right?
WRONG! A static method can not be overridden! It can only be hidden by a subclass! In fact, if you tried to do the right thing and add the #Override annotation to task2, it would not compile!
From JLS 15.12.4.4 Locate method to invoke:
If the invocation mode is static, no target reference is needed and overriding is not allowed. Method m of class T is the one to be invoked.
In fact, this problem is covered in Java Puzzlers Puzzle 48: All I Get Is Static. The conclusion given at the end of the puzzle is this:
In summary, qualify static methods invocations with a class name, or don't qualify them at all if you're invoking them from within their own class, but never qualify them with an expression. Also, avoid hiding static methods. Together, these guidelines help eliminate the misleading appearance of overriding with dynamic dispatch for static methods.
It is best to follow all these recommendations together, so:
If you're calling a static method within its own class, don't qualify
Otherwise, qualify with the class name
If you're doing this a lot within one class, consider static import of that specific method
Try not to static import all members with *
Never qualify with an expression
Don't hide a static method; you can't #Override it, it'll only cause confusion
See also:
Why doesn’t Java allow overriding of static methods ?
When do you use Java’s #Override annotation and why?
Yes, adding to Brian Agnew you can call static methods through an instance of that class type as well.
Yes you can call a static method without the class name. For example, if you are calling it within another static method of the same class.
public class TestStatic{
static void hello()
{
System.out.println("Hello World");
}
static void hello2()
{
hello();
System.out.println("Welcome to java");
}
public static void main(String[] args)
{
hello2();
}
}
Yes.
class CallStaticMethodTest {
public static void staticMethodOne() {
System.out.println("Static method one");
}
// Invoke from a non-static method
public void instanceMethodOne() {
staticMethodOne();// Calling static method without mentioning the class name
}
// Invoke from another static method:
public static void staticMethodTwo() {
staticMethodOne();
}
}
Related
I was facing an error before, but when I made an object in this class the and called for the method, it worked flawlessly. Any explanation? Do I always have to make an object to call for methods outside of the main method (but in the same class)?
here:
public class A{
public static void main(String[] args){
A myObj= new A();
System.out.println(myObj.lets(2));
}
public int lets(int x){
return x;
}
}
You need to understand static. It associates a method or field to the class itself (instead of a particular instance of a class). When the program starts executing the JVM doesn't instantiate an instance of A before calling main (because main is static and because there are no particular instances of A to use); this makes it a global and an entry point. To invoke lets you would need an A (as you found), or to make it static (and you could also limit its' visibility) in turn
private static int lets(int x) {
return x;
}
And then
System.out.println(lets(2));
is sufficient. We could also make it generic like
private static <T> T lets(T x) {
return x;
}
and then invoke it with any type (although the type must still override toString() for the result to be particularly useful when used with System.out.println).
There are a importance concept to consider an is static concept. In your example you have to create an instance of your class because the main method is static and it only "operate" with other statics methods or variable. Remember that when you instantiate a class you are creating a copy of that class an storing that copy in the instance variable, so as the copy (That was create inside of a static method in your case) is also static so it can access the method which is not static in that context.
In order to not create an instance and access to your method you need to make your lets method static(due to the explanation abode)
public static int lets(int x){
return x;
}
And in your main you don't need to instantiate the class to access to this method.
public static void main(String[] args){
System.out.println(lets(2));
}
Check this guide about static in java: https://www.baeldung.com/java-static
Hope this help!
I am studying for my BS, and my professor has given me a task, he said: Create a class without using any access modifier or interface keyword whose object can't be created.
I went through Google but can't find the solution. How can this be done in Java?
Enums are classes (JLS§8.9) that cannot be instantiated and cannot be subclassed; just create one without any values:
enum Foo {}
Other possibilities depending on interpretation:
JonK and T.J. Crowder considered throwing an exception from the constructor:
final class Example {
Example() {
throw new Exception();
}
}
But nick zoum pointed out that an instance is still created and exists, briefly, prior to the exception, even though it cannot (in the example above) be retained.
nick zoum considered abstract:
abstract class Example {
}
...but T.J. Crowder pointed out that abstract classes can be subclassed (they cannot be final), and a subclass instance "is a" superclass instance.
I'm not a Java person, but other answers gave me this idea:
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Object o = new Problematic();
// unreachable
}
}
class Problematic
{
static
{
int i = 1 / 0 ;
}
}
Try it on ideone
I'm pretty sure there's no way of making a Problematic and surviving...
(Note that when I tried throw new Exception(); in the static initializer it wouldn't compile)
Have you tried the keyword abstract?
For example:
abstract class Test{}
Of course this can be overwritten, so please check this answer for a more foolproof design.
Without hearing exactly how your professor phrased it, "without using any access-modifier" might mean they are attempting to teach you how the "default" access modifier works?
In which case:
package mypackage.nocreate;
class MyClass {
}
And then:
package mypackage;
import mypackage.nocreate.MyClass;
public class Test {
public static void main(String[] args) {
new MyClass(); // not allowed - in a different package
}
}
You could argue that - in the source code at least - that doesn't use any access modifier :)
Anonymous inner class should be the answer.
Example:
public abstract class HelloWorld{
abstract void x();
public static void main(String []args){
System.out.println("Hello World");
HelloWorld h = new HelloWorld(){
void x(){
System.out.println(" ");
}
};
h.x();
}
}
A class is created, but it's name is decided by the compiler which extends the HelloWorld class and provides the implementation of the x() method.
Seems like a very basic query but I was pondering how the static method main() below is able to execute a non static method(the constructor obviously) from it using the new keyword. Though I understand that new brings onto the table a few other things as well but how should I convince myself that this isn't an exception to the rule that static and non static methods can't using non static and static context respectively?
Below is the sample code:
public class ConstructorTest {
ConstructorTest(String str)
{
System.out.println("Constructor Printing "+str);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ConstructorTest cnst=new ConstructorTest("here");
}
}
The above code actually prints --> Constructor Printing here
or in other words executing the body of a Non static method from a Static method?
Any plausible explanations are welcome.
The Java Tutorial states that
[...] Constructors are not members.
Therefore, there is no problem in calling them, since they are not bound to instances of your class. This would not make sense - hence, you cannot do the following:
Thing thing = new Thing();
Thing anotherThing = thing.Thing();
A constructor is not a method, so you cannot apply "method logic" to them.
In case you want to know more, the whole instantiation process is very well documented in the JLS. See 12.5. Creation of New Class Instances.
Actually constructor is compiled into the static method, this is how JVM internally creates instances of classes.
You are executing non-static code, but you are not doing it in a static context.
for instance:
public class C1{
private int x;
public String do(){ System.out.println("x = " + x);}
public static void main(String[] args){
do();
}
}
This can not work, since do is an instance method, which might run code that is specific to the instance. So, how would the VM know which instance to use, or what value x should have?
Now, to first use a constructor, which is possible from any context:
public class C1{
private int x;
public String do(){ System.out.println("x = " + x);}
public static void main(String[] args){
C1 t = new C1();
t.do();
}
}
Here, even though you are calling the method from within a static method, you are using it through an instance, so not in a static context.
ConstructorTest is not a method.
its an constructor,and you can use the constructor for initialize class property.
you can also initialize the static variable from the constructor like that :-
public class XYZ
{
static int i=0;
public XYZ() {
i=1;//not an compile time error
}
public static void doSome(){}
public static void main(String[] args) {
}
}
On a formal language level you should read the line
ConstructorTest cnst = new ConstructorTest("here")
as a class instance creation expression. As a matter of fact, this is not a call to a constructor or any other method.
The instance creation does many steps, like allocating memory for the new object, initializing the fields, calling constructors and initializer blocks. See JLS §12.5 for a detailed step-by-step description. Thus being said, the constructor invocation is only a part of the instance creation.
Additionally, you might see constructors as being static parts of the class. In fact, constructor declaration are not members (see JLS §8.8) and thus they are not overridable (as static methods also). Beware: This is only half true. When being inside the constructor you already have the instance created, and you are able to call other instance methods and/or access instance fields.
can a static method be invoked before even a single instances of the class is constructed?
absolutely, this is the purpose of static methods:
class ClassName {
public static void staticMethod() {
}
}
In order to invoke a static method you must import the class:
import ClassName;
// ...
ClassName.staticMethod();
or using static imports (Java 5 or above):
import static ClassName.staticMethod;
// ...
staticMethod();
As others have already suggested, it is definitely possible to call a static method on a class without (previously) creating an instance--this is how Singletons work. For example:
import java.util.Calendar;
public class MyClass
{
// the static method Calendar.getInstance() is used to create
// [Calendar]s--note that [Calendar]'s constructor is private
private Calendar now = Calendar.getInstance();
}
If you mean, "is it possible to automatically call a specific static method before the first object is initialized?", see below:
public class MyClass
{
// the static block is garanteed to be executed before the
// first [MyClass] object is created.
static {
MyClass.init();
}
private static void init() {
// do something ...
}
}
Yes, that is exactly what static methods are for.
ClassName.staticMethodName();
Yes, because static methods cannot access instance variables, so all the JVM has to do is run the code.
Static methods are meant to be called without instantiating the class.
Yes, you can access it by writing ClassName.methodName before creating any instance.
Not only can you do that, but you should do it.
In fact, there are a lot of "utility classes", like Math, Collections, Arrays, and System, which are classes that cannot be instantiated, but whose whole purpose is to provide static methods for people to use.
Yes, that's definitely possible. For example, consider the following example...
class test {
public static void main(String arg[]) {
System.out.println("hello");
}
}
...if then we run it, it does execute, we never created a instance of the class test. In short, the statement public static void main(String arg[]) means execute the main method without instantiating the class test.
Once a class is loaded is there a way to invoke static initializers again?
public class Foo {
static {
System.out.println("bar");
}
}
Edit:
I need to invoke the static initializer because I didn't write the original class and the logic I need to invoke is implemented in the static initializer.
Put the initalisation code in a separate public static method, so you can call it from the static initializer and from elsewhere?
One circumstance in which the logic would be run more than once is if the class is loaded multiple times by different ClassLoaders. Note that in this instance, they are essentially different classes.
Generally, though, these are one-shot deals. If you want to be able to invoke the logic multiple times, do as others have suggested and put it in a static method.
I agree with Earwicker's answer. Just extract the static initialization to a separate static method.
public class Foo {
static {
Foo.initialize();
}
public static void initialize() {
System.out.println("bar");
}
}
In case you really want the exact answer to your exact question, the answer is no. It's not possible to invoke a static initializer or an instanceInitializer via reflection.
The docs clearly says :
for getDeclaredMethod(String name) :
If the name is "<init>" or "<clinit>" a NoSuchMethodException is raised.
for getDeclaredMethods() :
The class initialization method is not included in the returned array.
So no, it's not possible to invoke it, even via reflection.
you could try extending the class which contains the static code, and then put in your own static initializer. Not quite sure if it works, but :
public class OldBadLibraryClass {
static {
System.out.println("oldBadLibrary static init");
}
}
//next file
public class MyBetterClass extends OldBadLibraryClass {
static {
System.out.println("MyBetterClass init");
}
}
public class Test {
public static void main(String[] args) {
new MyBetterClass();
}
}
see if the above prints in the order you expect. On my machine, it worked.
Though this is totally a hack, and is quite brittle. It would really be much better to modify the old class to have an init() method that can be overridden.
Here https://stackoverflow.com/a/19302726/2300018 is a post from me, where I re-load a utility class to re-run the static initializer for unit testing.