Static vs New Object - java

public class A
{
public void doSomething()
{ /*code*/}
}
The doSomething method is in no way referencing the state of object A so by that logic it could be static.
What is the difference between option 1 and 2:
new A().doSomething()
Assuming doSomething is static; A.doSomething()
I want to say that option 2 is better because the first would be creating a new object everytime it is used.

Option 1 creates a new instance of A in order to call the method doSomething() which according to your question it sounds like it doesn't need to (there is nothing in doSomething() that requires an instance of A). Option 2 skips the unneeded instance creation while producing the same effect, so it would be better (assuming that this is the only design requirement). Now there might be other reasons to not use static, for instance, if A implemented in interface, or if the nature of doSomething could conceivably change at some point in the future where it might need information established outside of it.

You're entering into the "expression" part of programming. What do you want to express?
Three cases are under discussion:
your method is an action any A can take, or a message any given A can respond to,
your method is an action the class of A's should respond to, and
A is a singleton, and your method receives messages for that singleton.
Now ask yourself: what do you intend to express? Is "doSomething" appropriate for the class A? Or is it, rather, just something that every instance of A should be able to do, regardless of its internals? Does "A" represent something which, in the world of your program, should only have 1 instance?
As a practical point, you can't overload static methods, so aside from "expression of intent", you need to be aware of that.
A lot of basic utilities fall in the "static" category, and there's a (small) time penalty for creating a new instance of A, but overall--you're most likely to get it right, and more importantly, the later life of that method will have the least impact on other code, if you can answer the questions above correctly, and thus pick the implementation that matches the intent of the object most closely.

There is a third option.
Create one instance of A, then reuse it for each call.
e.g., in the class or Application that is using A,
A myA = new A(); // you can consider making this static if that makes sense...
...
then, as needed later on
...
myA.soSomething();
The advantage is that, in the future, if you do need to change the behavior of doSomething, you could change the first line to
A myA = new SubclassOfAThatDoesSomethingDifferent();
Or, if doSomething() eventually does need to reference the state of A, it can.

You'd have to declare the method as static:
public class A {
public static void doSomething() {
// code
}
}
This allows you to do A.doSomething() and also prevents doSomething() from looking at any instance methods or fields (because how would you know which A instance to use?), which shouldn't be a problem if it doesn't reference them anyway.
See The Java Tutorial's Article on Instance and Class Methods for details.

Related

Is it preferable to pass the whole object or call a method on it and pass the returned value?

I am providing the examples below to further illustrate my point:
Example 1:
public class A {
public String getTheNeededString() {
String returnedString;
//logic goes here
return returnedString;
}
}
public class B {
public void doSomething(A objectA) {
String neededString = objectA.getTheNeededString();
//proceed to do something that needs the above String
}
}
public class Client {
public static void main(String[] args) {
A objectA = new A();
B objectB = new B();
objectB.doSomething(objectA);
}
}
Example2:
public class A {
//stays the same
}
public class B {
public void doSomething(String neededString) {
//proceed to do something that needs the above String
}
}
public class Client {
public static void main(String[] args) {
A objectA = new A();
String neededString = objectA.getTheNeededString();
B objectB = new B();
objectB.doSomething(neededString);
}
}
I guess that there might not be a "better" approach and it might be a matter of preference.
If that's the case, then I would really appreciate any opinion/preference on the matter.
It is always preferable to pass only the required info for following reasons:
Single-responsibility principle : Each class/method should have one and only one responsibility. In this case, the method doSomething() should only know how to transform a string input into the desired output. It should not be the responsibility of this method to get the string by calling other methods.
Loosely coupled design: Imagine you decide to change the getTheNeededString() method in a way that you have to change all the calls to this method in your project. You'll have to make changes in doSomething() method as well. Here, the doSomething() method is tightly coupled to getTheNeededString() method. This is not a good design.
I believe it really is a matter of preference, and dependent on what exactly you need the program to do.
I would advise with Example 2, as it just makes more sense to me. If I were to come across your code at a later date and trying to interpret it, the second approach would be much more intuitive, at least for me.
It also makes the code reusable in the case you need to perform that same operation with any String outside of Object A. That may not be the case, but I still do not see the need to pass in the entire object. Pass the bare minimum input needed to produce the output needed.
Assume the method is to, say, count the number of occurences of the letter 'Z' and is called with countOccurencesOfLetterZ(objectA). Now, any person just exposed to this code will have to inspect this method to find out what it does - sure, the name is very intuitive.. but you're passing in the entire object, which needlessly creates uncertainty/confusion as to what you're trying to accomplish.
Now, assume you have countOccurencesOfLetterZ(objectA.getUsername()). I no longer have to inspect that method to figure out what you're trying to accomplish. Even better, if this method ends up being something you can utilize outside of Object B, then you can put it in a utility class and reuse that code for any string.
It depends on what is the goal of each class in your design.
Just an example.
Suppose class A represents a product and provides some details based on which class B creates product description. Suppose this logic is more complex that just getting a string. If you encapsulate such logic into the class B (approach 1), then if the logic changes later on, the only place to adjust will be the class B. The effort will be small and the number of bugs also small, if any. In case of the 2nd approach you will have to find all places where you pass data of object of class A to the object of class B and adjust all of them. It will take more time. Also it can happen, that you do these changes slightly differently and introduce more bugs. In such cases 1st approach is preferable.
Suppose the goal of the class B is to translate a given message key to some language, e.g. according to the default locale. In such case this class does not need to know where this key comes from (to reduce dependency on other classes). Suppose you have also other classes that provide keys that need to be translated, but they are in different class hierarchies and such objects cannot be passed to the method of class B. Then the 2nd approach is better. Each place where B is called implements its specific logic and passes to B only the common part, String key.

Shared instance variable vs local variable

Is there a reason to prefer using shared instance variable in class vs. local variable and have methods return the instance to it? Or is either one a bad practice?
import package.AClass;
public class foo {
private AClass aVar = new AClass();
// ... Constructor
public AClass returnAClassSetted() {
doStuff(aVar);
return avar;
}
private void doStuff(AClass a) {
aVar = a.setSomething("");
}
}
vs.
import package.AClass;
public class foo {
// ... Constructor
public AClass returnAClassSetted() {
AClass aVar = new AClass();
aVar = doStuff();
return aVar;
}
private AClass doStuff() {
AClass aVar1 = new AClass();
aVar1.setSomething("");
return aVar1;
}
}
First one makes more sense to me in so many ways but I often see code that does the second. Thanks!
Instance variables are shared by all methods in the class. When one method changes the data, another method can be affected by it. It means that you can't understand any one method on its own since it is affected by the code in the other methods in the class. The order in which methods are called can affect the outcome. The methods may not be reentrant. That means that if the method is called, again, before it finishes its execution (say it calls a method that then calls it, or fires an event which then a listener calls the method) then it may fail or behave incorrectly since the data is shared. If that wasn't enough potential problems, when you have multithreading, the data could be changed while you are using it causing inconsistent and hard to reproduce bugs (race conditions).
Using local variables keeps the scope minimized to the smallest amount of code that needs it. This makes it easier to understand, and to debug. It avoids race conditions. It is easier to ensure the method is reentrant. It is a good practice to minimize the scope of data.
Your class name should have been Foo.
The two versions you have are not the same, and it should depend on your use case.
The first version returns the same AClass object when different callers call returnAClassSetted() method using the same Foo object. If one of them changes the state of the returned AClass object, all of them will get see the change. Your Foo class is effectively a Singleton.
The second version returns a new AClass object every time a caller calls returnAClassSetted() method using either the same or different Foo object. Your Foo class is effectively a Builder.
Also, if you want the second version, remove the AClass aVar = new AClass(); and just use AClass aVar = doStuff();. Because you are throwing away the first AClass object created by new AClass();
It's not a yes/no question. It basically depends on the situation and your needs. Declaring the variable in the smallest scope as possible is considered the best practice. However there may be some cases (like in this one) where, depending on the task, it's better to declare it inside/outside the methods. If you declare them outside it will be one instance, and it will be two on the other hand.
Instance properties represent the state of a specific instance of that Class. It might make more sense to think about a concrete example. If the class is Engine, one of the properties that might represent the state of the Engine might be
private boolean running;
... so given an instance of Engine, you could call engine.isRunning() to check the state.
If a given property is not part of the state (or composition) of your Class, then it might be best suited to be a local variable within a method, as implementation detail.
In Instance variables values given are default values means null so if it's an object reference, 0 if it's and int.
Local variables usually don't get default values, and therefore need to be explicitly initialized and the compiler generates an error if you fail to do so.
Further,
Local variables are only visible in the method or block in which they are declared whereas the instance variable can be seen by all methods in the class.

Using superclass type for subclass instance

I know this question has been asked a lot, but the usual answers are far from satisfying in my view.
given the following class hierarchy:
class SuperClass{}
class SubClass extends SuperClass{}
why does people use this pattern to instantiate SubClass:
SuperClass instance = new SubClass();
instead of this one:
SubClass instance = new SubClass();
Now, the usual answer I see is that this is in order to send instance as an argument to a method that requires an instance of SuperClass like here:
void aFunction(SuperClass param){}
//somewhere else in the code...
...
aFunction(instance);
...
But I can send an instance of SubClass to aFunction regardless of the type of variable that held it! meaning the following code will compile and run with no errors (assuming the previously provided definition of aFunction):
SubClass instance = new SubClass();
aFunction(instance);
In fact, AFAIK variable types are meaningless at runtime. They are used only by the compiler!
Another possible reason to define a variable as SuperClass would be if it had several different subclasses and the variable is supposed to switch it's reference to several of them at runtime, but I for example only saw this happen in class (not super, not sub. just class). Definitly not sufficient to require a general pattern...
The main argument for this type of coding is because of the Liskov Substituion Principle, which states that if X is a subtype of type T, then any instance of T should be able to be swapped out with X.
The advantage of this is simple. Let's say we've got a program that has a properties file, that looks like this:
mode="Run"
And your program looks like this:
public void Program
{
public Mode mode;
public static void main(String[] args)
{
mode = Config.getMode();
mode.run();
}
}
So briefly, this program is going to use the config file to define the mode this program is going to boot up in. In the Config class, getMode() might look like this:
public Mode getMode()
{
String type = getProperty("mode"); // Now equals "Run" in our example.
switch(type)
{
case "Run": return new RunMode();
case "Halt": return new HaltMode();
}
}
Why this wouldn't work otherwise
Now, because you have a reference of type Mode, you can completely change the functionality of your program with simply changing the value of the mode property. If you had public RunMode mode, you would not be able to use this type of functionality.
Why this is a good thing
This pattern has caught on so well because it opens programs up for extensibility. It means that this type of desirable functionality is possible with the smallest amount of changes, should the author desire to implement this kind of functionality. And I mean, come on. You change one word in a config file and completely alter the program flow, without editing a single line of code. That is desirable.
In many cases it doesn't really matter but is considered good style.
You limit the information provided to users of the reference to what is nessary, i.e. that it is an instance of type SuperClass. It doesn't (and shouldn't) matter whether the variable references an object of type SuperClass or SubClass.
Update:
This also is true for local variables that are never used as a parameter etc.
As I said, it often doesn't matter but is considered good style because you might later change the variable to hold a parameter or another sub type of the super type. In that case, if you used the sub type first, your further code (in that single scope, e.g. method) might accidentially rely on the API of one specific sub type and changing the variable to hold another type might break your code.
I'll expand on Chris' example:
Consider you have the following:
RunMode mode = new RunMode();
...
You might now rely on the fact that mode is a RunMode.
However, later you might want to change that line to:
RunMode mode = Config.getMode(); //breaks
Oops, that doesn't compile. Ok, let's change that.
Mode mode = Config.getMode();
That line would compile now, but your further code might break, because you accidentially relied to mode being an instance of RunMode. Note that it might compile but could break at runtime or screw your logic.
SuperClass instance = new SubClass1()
after some lines, you may do instance = new SubClass2();
But if you write, SubClass1 instance = new SubClass1();
after some lines, you can't do instance = new SubClass2()
It is called polymorphis and it is superclass reference to a subclass object.
In fact, AFAIK variable types are meaningless at runtime. They are used
only by the compiler!
Not sure where you read this from. At compile time compiler only know the class of the reference type(so super class in case of polymorphism as you have stated). At runtime java knows the actual type of Object(.getClass()). At compile time java compiler only checks if the invoked method definition is in the class of reference type. Which method to invoke(function overloading) is determined at runtime based on the actual type of the object.
Why polymorphism?
Well google to find more but here is an example. You have a common method draw(Shape s). Now shape can be a Rectangle, a Circle any CustomShape. If you dont use Shape reference in draw() method you will have to create different methods for each type of(subclasses) of shape.
This is from a design point of view, you will have one super class and there can be multiple subclasses where in you want to extend the functionality.
An implementer who will have to write a subclass need only to focus on which methods to override

Is calling static methods via an object "bad form"? Why?

In a recent question, someone asked about static methods and one of the answers stated that you generally call them with something like:
MyClassName.myStaticMethod();
The comments on that also stated that you could also call it via an object with:
MyClassName myVar;
myVar.myStaticMethod();
but that it was considered bad form.
Now it seems to me that doing this can actually make my life easier so I don't have to worry about what's static or not (a).
Is there some problem with calling static functions via an object? Obviously you wouldn't want to create a brand new object just to call it:
Integer xyzzy;
int plugh = xyzzy.parseInt ("42", 10);
But, if you already have an object of the desired type, is there a problem in using it?
(a) Obviously, I can't call a non-static method with:
MyClassName.myNonStaticMethod();
but that's not the issue I'm asking about here.
In my opinion, the real use case that makes this so unreadable is something like this. What does the code below print?
//in a main method somewhere
Super instance = new Sub();
instance.method();
//...
public class Super {
public static void method() {
System.out.println("Super");
}
}
public class Sub extends Super {
public static void method() {
System.out.println("Sub");
}
}
The answer is that it prints "Super", because static methods are not virtual. Even though instance is-a Sub, the compiler can only go on the type of the variable which is Super. However, by calling the method via instance rather than Super, you are subtly implying that it will be virtual.
In fact, a developer reading the instance.method() would have to look at the declaration of the method (its signature) to know which method it actually being called. You mention
it seems to me that doing this can actually make my life easier so I don't have to worry about what's static or not
But in the case above context is actually very important!
I can fairly confidently say it was a mistake for the language designers to allow this in the first place. Stay away.
The bad form comment comes from the Coding Conventions for Java
See http://www.oracle.com/technetwork/java/codeconventions-137265.html#587
The reason for it, if you think about it, is that the method, being static, does not belong to any particular object. Because it belongs to the class, why would you want to elevate a particular object to such a special status that it appears to own a method?
In your particular example, you can use an existing integer through which to call parseInt (that is, it is legal in Java) but that puts the reader's focus on that particular integer object. It can be confusing to readers, and therefore the guidance is to avoid this style.
Regarding this making life easier for you the programmer, turn it around and ask what makes life easier on the reader? There are two kinds of methods: instance and static. When you see a the expression C.m and you know C is a class, you know m must be a static method. When you see x.m (where x is an instance) you can't tell, but it looks like an instance method and so most everyone reserves this syntax for instance methods only.
It's a matter of communication. Calling a method on an instance implies you're acting on/with that particular instance, not on/with the instance's class.
It might get super confusing when you have an object that inherits from another object, overriding its static method. Especially if you're referring to the object as a type of its ancestor class. It wouldn't be obvious as to which method you're running.

public static factory method

First of all please forgive me if its a really dumb question, I am just trying to learn this language to its core. I am reading Effective Java and the very first chapter talks about Static factory methods vs. Constructors. Their pros and cons. Few things that are confusing to me are:
class of an object returned by static factory method is nonpublic - what exactly does it mean?
unlike constructors static factory methods are not required to create a new object each time they are invoked - How does this happen? I am invoking factory method only to obtain a new object and do we put a check in factory method for checking if object already exists?
Thanks.
class of an object returned by static factory method is nonpublic -
what exactly does it mean?
It means that the actual class of the objects returned by a static factory method can be a subclass of the declared type, and this subclass does not have to be public. It's just another implementation detail that client code should not care about.
unlike constructors static factory methods are not required to create a new object each > time they are invoked - How does this happen? I am invoking factory method only to obtain a new object and do we put a check in factory method for checking if object already exists?
Yes, that's one way this could be done. But really, anything is possible.
First off, kudos to you for your choice in Java-lit: Bloch's book is an excellent primer.
To answer your 2nd question ('unlike constructors static factory methods are not required to create a new object each time they are invoked'), it's important to realize that what Bloch is saying here is that with a static factory you have the option of either: returning a new object or returning a pre-existing one. It all depends on what you want to do.
For example, let's suppose you have a really simple value class of type Money. Your static factory method probably should return a new instance -- that is, a new object with a specific value for Money. So, like this:
public class Money {
private Money(String amount) { ... } /* Note the 'private'-constructor */
public static Money newInstance(String amount) {
return new Money(amount);
}
}
But let's say you have some object that manages some resource and you want to synchronize access to that resource through some ResourceManager class. In that case you probably want your static factory method to return the same instance of itself to everyone -- forcing everyone to go through that same instance, so that that 1 instance can control the process. This follows the singleton-pattern. Something like this:
public ResourceManager {
private final static ResourceManager me = new ResourceManager();
private ResourceManager() { ... } /* Note the 'private'-constructor */
public static ResourceManager getSingleton() {
return ResourceManager.me;
}
}
The above method forces your user to only ever be able to use a single instance, allowing you to precisely control who(and when) has access to whatever it is you are managing.
To answer your first question, consider this (admittedly not the best example, it's pretty ad-hoc):
public class Money {
private Money(String amount) { ... }
public static Money getLocalizedMoney( MoneyType localizedMoneyType, String amount ) {
switch( localizedMoneyType ) {
case MoneyType.US:
return new Money_US( amount );
case MoneyType.BR:
return new Money_BR( amount );
default:
return new Money_US( amount );
}
}
}
public class Money_US extends Money { ... }
public class Money_BR extends Money { ... }
Note how I can now do this:
Money money = Money.getLocalizedMoney( user_selected_money_type );
saveLocalizedMoney( money );
Again, a really contrived-example but hopefully it helps you see more or less what Bloch was getting at with that point.
The other answers were good -- I just think that, as a beginner, sometimes it helps to see some actual code.
When you use the new keyword then you as the developer know that the JDK will create a new instace of that object. What the author is saying, when you use a static method, the developer no longer knows if the method is creating a new instance or possibly doing something else. Something else can be, reusing cached data, object pooling, creating a private implementation and returning a subclass of the class.
class of an object returned by static factory method is nonpublic
Frequently a static factory method will return either an an object typed as an interface (most common), or sometimes some base class (less common). In either case, you don't know the exact class of the returned object.
The advantage of this is getting an object whose behaviour you know without worrying about the messy details of what class it instantiates.
unlike constructors static factory methods are not required to create a new object each time they are invoked
To understand this, consider the case of working with a singleton. You may call .getInstance() on some factory classes to get the singleton instance of an certain object. Typically, what this does is create an instance of the object if it doesn't already exist, or give you the existing instance if it already does. In either case, you get back a copy of the object. But you don't (and won't) know if this singleton had to be created, or if one had already been constructed previously.
The advantage of this is that the lifecycle of the object and when it is created is managed for you.
Both of your questions can be answered by looking at some code that makes use of both of these properties of static factory methods. I suggest looking at Guava's ImmutableList.
Note how the no-arg factory method of() always returns the same instance (it doesn't create a new instance each time). If you look carefully, you'll also notice that its copyOf(Iterable) factory method actually returns the object that is passed to it if that object is itself an ImmutableList. Both of these are taking advantage of the fact that an ImmutableList is guaranteed to never change.
Notice also how various factory methods in it return different subclasses, such as EmptyImmutableList, SingletonImmutableList and RegularImmutableList, without exposing the types of those objects. The method signatures just show that they return ImmutableList, and all subclasses of ImmutableList have package-private (default) visibility, making them invisible to library users. This gives all the advantages of multiple implementation classes without adding any complexity from the user's perspective, since they are only allowed to view ImmutableList as a single type.
In addition to ImmutableList, most instantiable classes in Guava utilize static factory methods. Guava also exemplifies a lot of the principles set forth in Effective Java (not surprising, given that it was designed by those principles and with guidance from Josh Bloch himself), so you may find it useful to take a look at it more as you're working through the book.

Categories