This is related to the below thread :
https://stackoverflow.com/questions/18402564/how-do-static-methods-work
Suppose I have a static method in a class (TestClass), which queries the DB and stored it in a static variable, and returns it.
public static List<MyClass> getMyData()
{
setMyDataList(getMyNewData.execute());//DB Call and assigns the result to the static variable.
return myDataList;// returns the static variable
}
In this case, say class A calls TestClass.getMyData() which fetches the data and stores in the myDataList, and then class B calls TestClass.getMyData(), will the DB be hit again ?
Static block is not equals to static method.
In case of static block:
That static block loads when class loader loads that class. Unless you have multiple class loaders, only once it executes and that data you inserted will be shared across all the instances.
Incase of static method :
It's almost like an instance method and you'll be hit those many times you call that method. Diff is only you don't need an instance to invoke it.
You not at all need that method. Put your code in a static block an hit DB there and insert into list. You can access that list with static and don't forget to make that list static.
yes it will be 'hit' again...
If you don't want that you might want to have a flag in your static class that indicates if the method was already called:
private static boolean methodAlreadyCalled = false;
public static List<MyClass> getMyData()
{
if (!methodAlreadyCalled)
{
setMyDataList(getMyNewData.execute());
methodAlreadyCalled = true;
}
return myDataList;
}
Related
I'm trying to create a subclass which auto creates itself. I defined Base which holds a list of instances. Then I defined Derived with a static member reg. reg is in place initialized by calling Base.Register(), which adds it to the instances list.
In the main() I'm printing the instances list of Base. But there is no initialization and I get an error - the instances list is null.
In a further attempt, I added a list of Booleans to Base. Whenever I register an instance, I'm changing this list. I also print this list in the program. I expected it to force the execution of the Base.register(), but to no avail.
I did find a solution that worked, but I don't appreciate - I could print the result of the Base.register() as saved in the Derived. That would force the static initialization. However, I intend to use the solution for a bunch of derived classes, and I wouldn't want to have to call each derived class directly.
Is there a way to force the static init?
I guess I could use reflections, I'm trying to avoid that at the moment.
EDIT what I am actually trying to do, is to build a set of derived classes (for unit testing). All classes derive Base. I want to avoid the need to create instances separately for each. I'm trying to get a generic solution, in each derived class code (only). Such a solution would be easy to copy & paste.
public class StaticTest {
private static class Base{
private static ArrayList<Base> _instances = null;
private static ArrayList<Boolean> _regs = null;
public static int _count = 0;
public static void init(){
_regs = new ArrayList<>();
for (int i=0;i<10;i++)
_regs.add(false);
}
protected static boolean register(Base b)
{
if (_instances == null)
_instances = new ArrayList<>();
_regs.set(_count++, true);
return _instances.add(b);
}
public static void printAll(){
for (Boolean b: _regs)
System.out.printf("hello %s%n", b.toString());
for (Base b: _instances)
System.out.printf("hello %s%n", b.toString());
}
}
private static class Derived extends Base{
public static boolean _reg = Base.register(new Derived());
}
public static void main(String[] args) {
//System.out.print(Derived._reg ? "0" : "1");
Base.init();
System.out.printf("Base._count = %d%n",Base._count);
Base.printAll();
}
}
Short answer is that static initialization occurs only when a class is first used. When you invoke Base.init(), Derived hasn't been yet used and so register hasn't been called.
Medium answer is that if you uncomment the line System.out, you get a NullPointerException because the static code in Derived calls to register before init initializes the Arraylist. Moving the init to the first line solves it and it works as you wanted.
Final answer, if you're trying to understand how a Java classes initializes and it's limitations, it's ok, but the mechanism you're trying to write is a very bad design. Please provide the real problem you're trying to solve and someone can point you in the right direction.
I have a class that may need a large, but unchanging, data-structure based on the contents of an enum class.
What I'm interested to know is whether it is better for me to initialise this in a static block, or should I only initialise it within the method that actually accesses the data (in case it's never actually used)?
Here's an example:
public enum MyEnum {
FOO ("foo"),
BAR ("bar"),
FOOBAR ("foo_bar");
private final String otherName;
private MyEnum (String otherName) {
this.otherName = otherName;
}
private static final Map<String, MyEnum> otherNames = new HashMap<String, MyEnum>();
}
Now, I have two options for initialising the otherNames map, first being to use a static block like so:
static {
for (MyEnum entry : MyEnum.values())
otherNames.put(entry.otherName, entry);
}
public static MyEnum valueByOtherName (String otherName) {
return otherNamesStatic.get(otherName);
}
Or alternatively I can initialise the map the first time a lookup is actually requested like-so:
public static MyEnum valueByOtherName(String otherName) {
if (otherNames.isEmpty()) { // Or test against null or whatever
for (MyEnum entry : MyEnum.values())
otherNames.put(entry.otherName, entry);
}
otherNames.get(otherName);
}
In particular I'm interested to know whether Java will optimise the static block such that it can pre-generate the map on future runs (since it's based on the enum so if it hasn't changed, then neither has the map) or will it run the static code every time the class loads, in which case only doing it when needed may be more efficient?
Static blocks are executed every time the class is loaded (not every time an object is instantiated). So, unless your environment uses several class loaders, your static initialization block will run only once.
Having that said, I'd suggest to use the static block which is cleaner (IMHO).
Also check this answer for your reference.
As long as I understand Java, the ClassLoader calls the static initialization block at the moment it loads the class and only at that moment. So :
if using a static block, you are sure it is called at least once if you use class MyEnum even if you do not use valueByOtherName and it will never be called again until the jvm is closed (unless you have independant ClassLoaders loading same class which should be at least strange). But you have no extra test in valueByOtherName
if using initialization on first lookup, the block will be called only if you call valueByOtherName and by construction will never be called again. But you have an extra test in each call to valueByOtherName
IMHO it is far better to use a static block. And it is far more readable ...
I don't understand why methods on arrays, in Java, have to be static. Static methods can only be used on static variables right? So this would mean arrays are static variables, variables shared by a class? But what class would this be?
Can someone help me understand this?
Edit: to be more specific, I am creating methods to act on arrays but if I just write "public int[] expandArr(int[]a, int v)" and I try to use this method in the main method, I get an error saying I can't make a static reference to a non-static method. When I write "public static int[] expandArr(int[]a, int v)" it works then.
I understand you cannot change the size of an array, the method I wrote makes a new array with increased size and copies the first one into it.
Thank you.
You say you tried to write this:
public int[] expandArr(int[]a, int v)
The thing is, you had to write it in some class, since you can't just have free-floating methods in your program. Therefore, it must operate on a instance of the class. For example:
public class MyProgram {
public int[] expandArr(int[]a, int v) { ... }
public static void main(String[] args) { ... }
}
expandArr requires an instance of MyProgram, since you didn't declare it to be static. And that has nothing to do with arrays. It would be the same if you wrote
public class MyProgram {
public String expandString(String s, int v) { ... }
public static void main(String[] args) {
String s = expandString(args[0], 1); // ILLEGAL
String s2 = args[0].expandString(1); // ILLEGAL
}
}
Although the first parameter of expandString is a String, this actually operates on a MyProgram, and you cannot use expandString without an instance of MyProgram to operate on. Making it static means that you can (the first use of expandString in my example would become legal.)
In general, you can't add methods to a class without modifying the source of that class. If you want to write a new method that does something with objects of a certain class C, and you can't modify class C (perhaps because it's in the Java library or someone else's library), then you'll need to put the method in some other class C2, and most of the time you will need to make the method static since it doesn't involve objects of class C2.
You can't call a non-static method from a static method unless you first instantiate the an object of the class.
e.g.
In class Whatever...
public boolean ok() {
return true;
}
public static void main(String[] args) {
Whatever w = new Whatever();
System.out.println(w.ok());
}
You cant call a non static method from a static context. A static method belongs to the class, non static or instance methods are copied to each instance of the class (they each have their own). If I have 10 instances of class A, and class A has a static method, which all of them share, then I try to invoke a non static method in class A from class A's static method, which instance of class A gets its method invoked? The behavior is undefined.
The question really has nothing to do with arrays.
This question is related: Can't call non static method
I think what you're referring to is the fact that you can't extend an array class and hence can't add a method to it:
// No way to do this
int[] array;
array.myMethod();
This means your only option is to make a static helper method somewhere:
// So you have to do this
int[] array;
Utils.myMethod(array);
class Utils {
static void myMethod(int[] array) {
...
}
}
An example of this is the Arrays class, which has lots of static methods for operating on arrays. Conceptually it would be clearer if these methods could be added to the array classes, but you can't do that in Java (you can in other languages like Javascript).
That is why we use other classes like the ArrayList to make them grow dynamically in size. At the core of an arraylist you will simply find an array that is renewed in size whenever the class figures out it necessary. If I'm understanding your question right.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
When should a method be static?
Usually when writing a static method for a class, the method can be accessed using ClassName.methodName. What is the purpose of using 'static' in this simple example and why should/should not use it here? also does private static defeat the purpose of using static?
public class SimpleTest {
public static void main(String[] args) {
System.out.println("Printing...");
// Invoke the test1 method - no ClassName.methodName needed but works fine?
test1(5);
}
public static void test1(int n1) {
System.out.println("Number: " + n1.toString());
}
//versus
public void test2(int n1) {
System.out.println("Number: " + n1.toString());
}
//versus
private static void test3(int n1) {
System.out.println("Number: " + n1.toString());
}
}
I had a look at a few tutorials. E.g. http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
My understanding of it is that instead of creating an instance of a class to use that method, you can just use the class name - saves memory in that certain situations there is no point in constructing an object every time to use a particular method.
The purpose of the static keyword is to be able to use a member without creating an instance of the class.
This is what happens here; all the methods (including the private ones) are invoked without creating an instance of SimpleTest.
In this Example,Static is used to directly to access the methods.A private static method defeats the purpose of "Data hiding".
Your main can directly call test1 method as it is also Static,it dosn't require any object to communicate.Main cannot refer non-static members,or any other non-static member cannot refer static member.
"non-static members cannot be referred from a static context"
You can refer This thread for more info about Static members.
static means that the function doesn't require an instance of the class to be called. Instead of:
SimpleTest st = new SimpleTest();
st.test2(5);
you can call:
SimpleTest.test1(5);
You can read more about static methods in this article.
A question about private static has already been asked here. The important part to take away is this:
A private static method by itself does not violate OOP per se, but when you have a lot of these methods on a class that don't need (and cannot*) access instance fields, you are not programming in an OO way, because "object" implies state + operations on that state defined together. Why are you putting these methods on that class, if they don't need any state? -eljenso
static means that the method is not associated with an instance of the class.
It is orthogonal to public/protected/private, which determine the accessibility of the method.
Calling test1 from main in your example works without using the class name because test1 is a static method in the same class as main. If you wanted to call test2 from main, you would need to instantiate an object of that class first because it is not a static method.
A static method does not need to be qualified with a class name when that method is in the same class.
That a method is private (static or not) simply means it can't be accessed from another class.
An instance method (test2 in your example) can only be called on an instance of a class, i.e:
new SimpleTest().test2(5);
Since main is a static method, if you want to call a method of the class without having to instantiate it, you need to make those methods also static.
In regards to making a private method static, it has more readability character than other. There isn't really that much of a difference behind the hoods.
You put in static methods all the computations which are not related to a specific instance of your class.
About the visibility, public static is used when you want to export the functionality, while private static is intended for instance-independent but internal use.
For instance, suppose that you want to assign an unique identifier to each instance of your class. The counter which gives you the next id isn't related to any specific instance, and you also don't want external code to modify it. So you can do something like:
class Foo {
private static int nextId = 0;
private static int getNext () {
return nextId ++;
}
public final int id;
public Foo () {
id = getNext(); // Equivalent: Foo.getNext()
}
}
If in this case you want also to know, from outside the class, how many instances have been created, you can add the following method:
public static int getInstancesCount () {
return nextId;
}
About the ClassName.methodName syntax: it is useful because it specifies the name of the class which provides the static method. If you need to call the method from inside the class you can neglect the first part, as the name methodName would be the closest in terms of namespace.
is Calling a static Java method ( a factory class method ) creates an object of that Class ?
I mean a static method returns a value let's say an Array's size ( array is variable of class )
I've checked the code but couldn't see that the Object of that class never instantiated before calling the static method. ?
public static boolean isFiveInstance() {
return _instances.size() == 5;
}
and _instances is class variable
private static ArrayList<LocalMediaPlayer> _instances;
and is being created and filled in the constructer.
No it does not. That is the point behind creating static methods. Static methods use no instance variables of any object of the class they are defined in either, so everything you refer to inside your static method must be static also.
That is why you call a static method like Class.StaticMethod() instead of:
new Class().StaticMethod();
the new will instantiate that class, thus creating a new instance of that object.
No, static invocations do not instantiated objects (because they do not require one).
The first time you refer to a class, including static method invocation, the class is loaded. by the classloader.
That's where the static initializer comes into play:
static {
// do something
}
this block is called whenever the class is initialized (once per classloader)
No, calling a static method does not create an instance of the class. That's where static methods differ from instance methods. They don't need an instance of the class they belong to to be instantiated to be run.