The question arose while reading a answer to this question - How do I join two lists in java. This answer gave the solution
List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } };
Reading the comments, users said it was evil and ugly and should not be used in production.
I would like to know what's the harm in using this? Why is it ugly, evil or bad to use in production?
Except for the already mentioned issues regarding good programming style and inheritance misuse, there is one more subtle problem - inner classes and (non-static) anonymous class instances act as closures. This means that they keep an implicit reference to the enclosing class instance. This can result in preventing of garbage collection and in the end, a memory leak.
Given an example piece of source code:
public interface Inner {
void innerAction();
}
public class Outer {
public void methodInOuter() {}
private Inner inner = new Inner() {
public void innerAction() {
// calling a method outside of scope of this anonymous class
methodInOuter();
}
}
}
What happens at compilation time, is that the compiler creates a class file for the new anonymous subclass of Inner which gets a so-called synthetic field with the reference to the instance of the Outer class. The generated bytecode will be roughly equivalent to something like this:
public class Outer$1 implements Inner {
private final Outer outer; // synthetic reference to enclosing instance
public Outer$1(Outer outer) {
this.outer = outer;
}
public void innerAction() {
// the method outside of scope is called through the reference to Outer
outer.methodInOuter();
}
}
Such capture of reference to the enclosing instance happens even for anonymous classes that never actually access any of methods or fields of the enclosing class, such as the double-brace initialized (DBI) list in your question.
This results in the fact that the DBI list keeps a reference to the enclosing instance as long as it exists, preventing the enclosing instance from being garbage collected. Suppose the DBI list happens to live for a long time in the application, for example as a part of the model in MVC pattern, and the captured enclosing class is for example a JFrame, which is quite a large class with lots of fields. If you created a couple of DBI lists, you would get a memory leak very quickly.
One possible solution would be using DBI only in static methods, because there is no such enclosing instance available in their scope.
On the other hand, I would still argue that using DBI is still not necessary in most cases. As for the list joining, I would create a simple reusable method, which is not only safer, but also more concise and clear.
public static <T> List<T> join(List<? extends T> first, List<? extends T> second) {
List<T> joined = new ArrayList<>();
joined.addAll(first);
joined.addAll(second);
return joined;
}
And then the client code becomes simply:
List<String> newList = join(listOne, listTwo);
Further reading:
https://stackoverflow.com/a/924536/1064809
The "ugly" and "do not use in production" comments refer to this specific use of anonymous classes, not to anonymous classes in general.
This specific use assigns newList an anonymous subclass of ArrayList<String>, an entirely new class created with a single purpose in mind - namely, initializing a list with the content of two specific lists. This is not very readable (even an experienced reader would spend a few seconds figuring it out), but more importantly, it can be achieved without subclassing in the same number of operations.
Essentially, the solution pays for a small convenience with creating a new subclass, which may result in problems down the road, for example, in situations when you try to persist this collection using an automated framework that expects collections to have specific types.
This particular use of anonymous classes has several problems:
it's a little-known idiom. Developers that don't know it (or know it an don't use it a lot) will be slowed down when reading and/or modifying code that uses it.
it's actually misusing a language feature: you're not trying to define a new kind of ArrayList, you just want some array list with some existing values in it
it creates a new class that takes up resources: disk space to hold the class definition, time to parse/verify/... it, permgen to hold the class definition, ...
even if the "real code" is slightly longer, it can easily be moved into an aptly-named utility method (joinLists(listOne, listTwo))
In my opinion #1 is the most important reason to avoid it, closely followed by #2. #3 is usually not that much of a problem, but should not be forgotten.
Because you don't need a separate subclass - you just need to create a new ArrayList of the normal class, and addAll() both lists into it.
Like so:
public static List<String> addLists (List<String> a, List<String> b) {
List<String> results = new ArrayList<String>();
results.addAll( a);
results.addAll( b);
return results;
}
It's evil to create a subclass, that isn't needed. You don't need to extend or subclass behaviour - just change data values.
It's not a bad approach per se, say, in performance or anything like that, but the approach is a bit obscure and when using something like this, you always (say, 99%) have to explain this approach. I think that's one of the biggest reasons not to use this approach, and while typing:
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
is a little more typing, it's a bit easier to read, which helps a lot in understanding or debugging code.
In your example it really looks evil and ugly, at least to me - it's difficult to understand what's going on in the code. But there are some patterns of using anonymous classes that people are used to because they see them very often, eg
Arrays.sort(args, new Comparator<String>() {
public int compare(String o1, String o2) {
return ...
}});
I would call the above a best practice case.
Related
I've read articles talking about static class variables loading and static methods loading but very few about returned instantiated objects from static methods and their footprint.
Returning an instance from a static method is actually how singletons are created however singletons are supposed to be created once and then accessed by some getInstance method.
If I voluntarily want to break the singleton pattern, what happens if I write something like the following for example? (note the RandomSumBuilder build() method static access modifier)
public class Service {
public void doSomething() {
for (int i = 0; i < 1000; i++) {
System.out.println("Random sum : " + RandomSumBuilder.add().build());
}
}
}
public class RandomSumBuilder {
private List<Integer> aList = new ArrayList<>();
public RandomSumBuilder() { }
public static RandomSumBuilder add() {
RandomSumBuilder randomSumBuilder = new RandomSumBuilder();
randomSumBuilder.aList.add(new Random().nextInt(11));
return randomSumBuilder;
}
public int build() {
return aList.stream()
.reduce(Integer::sum)
.orElse(0);
}
}
To me it's clear RandomSumBuilder can't be considered as singletons but I can't get my head around these questions and I can only make assumptions so far.
Are the different RandomSumBuilder instances static?
(I'd say yes, like singletons)
Can these objects be elected for garbage collection?
(given my answer to question 1, I'd say no)
Does it put unnecessary work on the class loader?
(if it has to load that many RandomSumBuilder to instantiate these static objects, I'd say yes since I don't see the point in keeping them global. My quick local test with visualvm couldn't help me decide)
What would the builder pattern (with a nested class) bring here instead?
(I'd say way less static objects created and class loading work but being at my 4th consecutive assumption I'm not even sure)
I hope I'm not too lost in this subject, please correct me if I'm wrong.
Note that your example is not compilable and it is not possible to be sure about what the
Are the different RandomSumBuilder instances static?
That question is meaningless.
There is no such thing as a static instance. Seriously.
For example:
public class Test {
public static Test myTest = new Test();
}
The myTest variable is a static variable, but the instance that it points to is no different from any other instance of Test.
It is not a "static instance". There is no such thing.
The second issue is that your example is not creating any RandomSumBuilder instances at all.
Can these objects be elected1 for garbage collection?
Yes. Assuming that they are not assigned to something that makes it reachable.
Does it put unnecessary work on the class loader?
No. Unless you are creating multiple classloaders, the class only loaded once. The classloader doesn't get involved in creating instances.
What would the builder pattern (with a nested class) bring here instead?
How an object is created makes no difference to its reachability. It makes no difference that the method that creates it is static, or inner or nested.
On the other hand your code does this:
instanceB.aList.add(new Random().nextInt(11));
This doesn't compile because instanceB is not declared. But if instanceB was declared, and it was static, then that would be sufficient to make the Integer that you are (possibly) creating reachable.
But that is nothing to do with the build method being static ...
1 - English mistake: you are equating "candidates" with "election". Garbage collection is not democratic. And even in the real world, candidate has a broader meaning than that. Look it up in a dictionary ...
Is there any difference in efficiency (e.g. execution time, code size, etc.) between these two ways of doing things?
Below are contrived examples that create objects and do nothing, but my actual scenarios may be creating new Threads, Listeners, etc. Assume the following pieces of code happen in a loop so that it might make a difference.
Using anonymous objects:
void doSomething() {
for (/* Assume some loop */) {
final Object obj1, obj2; // some free variables
IWorker anonymousWorker = new IWorker() {
doWork() {
// do things that refer to obj1 and obj2
}
};
}
}
Defining a class first:
void doSomething() {
for (/* Assume some loop */) {
Object obj1, obj2;
IWorker worker = new Worker(obj1, obj2);
}
}
static class Worker implements IWorker {
private Object obj1, obj2;
public CustomObject(Object obj1, Object obj2) {/* blah blah */}
#Override
public void doWork() {}
};
The only practical difference between the anonymous classes and the top-level classes is that the anonymous classes will hold an implicit reference to the outer class.
This won't manifest itself in performance, but will impact you if you ever serialise these classes.
There should be little if any performance difference. If there is a difference it will be at a level where it is not worth worrying about.
IMO, you should focus on writing code that is readable and maintainable, and ignore "micro" performance issues until you have clear evidence that they are significant ... based on profiling the application.
(For the record, when an anonymous inner class refers to a final in an enclosing scope, this is implemented at the bytecode level by means of hidden constructor arguments and hidden instance attributes. The bytecodes will be almost the same as the bytecodes that you get from your other implementation.)
It's important to realize that anonymous classes are still classes that were known and fully-compiled at compile time. The fact that, say, you're defining an anonymous class body, perhaps with many methods and fields etc within a loop, doesn't mean that the runtime has to compile that type on every iteration.
Thus, any difference in performance between the two approaches are negligible. The important factors to consider are things like readability, reusability, testability, etc.
I actually HAVE noticed a significance performance hit when instantiating many instances of an anonymous class.
Thinking if might be due to the local class being static I removed that and it made no difference.
In my case, I was doing something 1000 choose 3 times which is 499,500. The version with the local class (regardless of static or not) took 26 seconds and the version with the anonymous functionally identical class took 2 minutes 20 seconds.
Regarding performance you should consider if an inner class should be created or not at all.
An example for bad practice is something like:
public List<String> someMethod() {
return new ArrayList<String>() {{
add("Item one");
add("Item two");
}};
}
While this syntactical convenience looks smart at a first glance, this (often unnoticed) creates an anonymous inner class whose object keeps a reference to the outer instance.
As this object is also given to the outside as result value of someMethod, you cannot be sure what your caller does with this list.
If he puts the resulting ArrayList instance into some static variable, your current Object will be kept forever too!
Speculating about code performance is an excellent way of wasting your time. Nothing compares to actually benchmarking the code. If you're worried about performance, measure the code. If you suspect that your code is sub-optimal, profile the code to figure out where the time is spent, then try to improve those parts. At this time it may be appropriate to actually study the byte code to see if that may give you a hint which implementation is more efficient.
When you've done that, measure the code again to make sure that you didn't make things worse, for example by making the code uglier and more difficult to maintain.
I'm reading J. Bloch's Effective Java and now I'm at inheritance vs composition section. As far as I understood he said that inheritance is not always good.
A related cause of fragility in subclasses is that their superclass
can acquire new methods in subsequent releases. Suppose a program
depends for its security on the fact that all elements inserted into
some collection satisfy some predicate. This can be guaranteed by
subclassing the collection and overriding each method capable of
adding an element to ensure that the predicate is satisfied before
adding the element. This works fine until a new method capable of
inserting an element is added to the superclass in a subsequent
release.
But why doesn't it work? The superclass is just the Collection interface and if we add a new method we just a compile-time error. That's not harmful ever...
Suppose you have a Collection superclass in some library v1.0:
public class MyCollection {
public void add(String s) {
// add to inner array
}
}
You subclass it in order to only accept Strings that have length 5:
public class LimitedLengthCollection extends MyCollection {
#Override
public void add(String s) {
if (s.length() == 5) {
super.add(s);
}
}
}
The contract, the invariant of this class is that it will never contain a String that doesn't have length 5.
Now version 2.0 of the library is released, and you start using it. The base class is modified to:
public class MyCollection {
public void add(String s) {
// add to inner array
}
public void addMany(String[] s) {
// iterate on each element and add it to inner array
}
}
and your subclass is left unmodified. Now users of your subclass can do
LimitedLengthCollection c = new LimitedLengthCollection();
c.addMany(new String[] {"a", "b", "c"});
and the contract of your subclass is thus broken. It was supposed to only accept Strings of length 5, and it doesn't anymore, because an additional method has been added in the superclass.
The problem is not that inheritance could not work.
The problem is that with inheritance the developer can not enforce some behaviour (like the example of the collection that satisfy some predicate) .
When we create a new class rarely it really is a specialized type of another. More often it is something new that use other classes.
So rarely we need inheritance and more often we need to create a class that use other classes to so something.
The IS A vs HAS A
You have to ask yourself:
Class B IS A new sub type of Class A that do the same things of A in different ways ?
or
Class B HAS A class inside to do something different from
what A is intented to do ?
And know that more often the right answer the latter.
if we add a new mehtod we just a compile-time error
That is true only when an abstract method is added to the superclass/interface. If a non-abstract method is added, it is perfectly valid not to override that new method.
Because it (in general) will break the client code that has implemented the Collection class.
In this particular example the security will be broken because malicious users would be able to insert items by using the non yet overridden method that was added after you have shipped your code.
Basing your code on inheriting classes you do not control may bite you in the future.
I have read Item 16 from Effective Java and
Prefer composition over inheritance? and now try to apply it to the code written 1 year ago, when I have started getting to know Java.
I am trying to model an animal, which can have traits, i.e. Swimming, Carnivorous, etc. and get different type of food.
public class Animal {
private final List<Trait> traits = new ArrayList<Trait>();
private final List<Food> eatenFood = new ArrayList<Food>();
}
In Item 16 composition-and-forwarding reuseable approach is suggested:
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) {this.s = s;}
//implement all interface methods
public void clear() {s.clear();}
//and so on
}
public class InstrumentedSet<E> extends ForwardingSet<E> {
//counter for how many elements have been added since set was created
}
I can implement ForwardingList<E> but I am not sure on how I would apply it twice for Animal class. Now in Animal I have many methods like below for traits and also for eatenFood. This seems akward to me.
public boolean addTrait (Trait trait) {
return traits.add(trait);
}
public boolean removeTrait (Trait trait) {
return traits.remove(trait);
}
How would you redesign the Animal class?
Should I keep it as it is or try to apply ForwardingList?
There is no reason you'd want to specialize a List for this problem. You are already using Composition here, and it's pretty much what I would expect from the class.
Composition is basically creating a class which has one (or usually more) members. Forwarding is effectively having your methods simply make a call to one of the objects it holds, to handle it. This is exactly what you're already doing.
Anyhow, the methods you mention are exactly the sort of methods I would expect for a class that has-a Trait. I would expect similar addFood / removeFood sorts of methods for the food. If they're wrong, they're the exact sort of wrong that pretty much everyone does.
IIRC (my copy of Effective Java is at work): ForwardingSet's existence was simply because you cannot safely extend a class that wasn't explicitly designed to be extended. If self-usage patterns etc. aren't documented, you can't reasonably delegate calls to super methods because you don't know that addAll may or may not call add repeatedly for the default implemntation. You can, however, safely delegate calls because the object you are delegating to will never make a call the wrapper object. This absolutely doesn't apply here; you're already delegating calls to the list.
When should I use a constructor and when should I use static method?
Can you explain above with small snippet? I skimmed through a few threads but I'm still not clear with this.
Joshua Bloch advises to favor static factory methods instead of constructors (which I think is a good practice). Couple of advantages and disadvantages :
Advantages of static factory methods :
unlike constructors, they have names
unlike constructors, they are not required to create a new object each time they're invoked (you can cache instances : e.g. Boolean.valueOf(..)
unlike constructors, they can return an object of any subtype of their return type (great flexibility)
Disadvantages of static factory methods :
They are not really distiguishable from other static methods (it's hard to find out how to initialize an object if you are not familiar with the API)
The main disadvantage (if you use only static factory methods, and make constructors private) is that you cannot subclass that class.
Use a public constructor when you only ever want to return a new object that type and you want simplicity.
A good example is StringBuilder as it's mutable and you are likely to want a new object each time.
public String toString() {
StringBuilder sb = new StringBuilder();
// append fields to the sb
return sb.toString();
}
Use a static factor method when you might want to re-use objects (esp if immutable), you might want to return a sub-class or you want descriptice construction. A good example is EnumSet which has a number of static factories which do different things even though some have the same arguments.
EnumSet.noneOf(RetentionPolicy.class);
// has the same arguments, but is not the same as
EnumSet.allOf(RetentionPolicy.class);
In this case, using a static factory makes it clear what the difference between these two ways of construction the set.
Also EnumSet can return two different implementations, one optimised for enums with a small number of values (<= 64) RegularEnumSet and another for many values called JumboEnumSet
Always use a constructor if your class has a state (even for a single instance; singleton pattern ).
Only use static for utility methods like in java.lang.Math
Example:
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
Doesn't change any state (instance variables) of an object, thus it can be declared static.
Use constructor when you need an object and other stuffs like functions and variables having one copy for every object.
when you want to do something without creating object then use static method.
Example:
public class Test {
public int value;
public static int staticValue;
public int getValue() {
return ++value;
}
public static int getStaticValue() {
return ++staticValue;
}
}
public class TestClass {
public static void main(String[] args) {
Test obj = new Test();
Test obj1 = new Test();
S.o.p(obj.getValue());
S.o.p(obj1.getValue));
S.o.p(Test.getStaticValue());
S.o.p(Test.getStaticValue());
}
}
Static factory methods have names, constructors don't. Thus factory methods can carry natural documentation about what they do that constructors can't. For example, see the factory methods in the Guava Libraries, like ImmutableMap.copyOf(otherMap). While this might have little effect on behaviour of construction, it has a huge effect on readability of the code. Definitely consider this if you're publishing an API.
Also you can use a factory when you need to do any more complicated configuration of the object you're creating, especially if you need to publish to other threads (registering in pools, exposing as an MBean, all manner of other things...) to avoid racy publication. (See e.g. Java Concurrency In Practice section 3.2)
Static methods that do something (e.g. Math.min) are not really the same thing as static factories, which can be considered direct replacements for constructors, with added flexibility, evolvability and (often) clarity.
Whenever you need to create an instance of an object you will have to use the constructor.
So, if you want to create a Car object, then you will need a constructor for that.
The keyword static means, that your method can be called without creating an instance.
class Car
{
private int num_of_seats;
public Car(int number_of_seats)
{
this.num_of_seats = number_of_seats;
}
// You want to get the name of the class that has to do with
// this class, but it's not bounded with any data of the class
// itself. So you don't need any instance of the class, and
// you can declare it as static.
static String getClassName()
{
return "[Car]";
}
}
In general you will use static class with data that are not correlated with the instance of the object.
Another example is:
class Ring
{
private List nodes;
public Ring(List nodes)
{
this.nodes = nodes;
}
// You want to calculate the distance of two ids on the ring, but
// you don't care about the ring. You care only about the ids.
// However, this functionality logical falls into the notion of
// the ring, that's why you put it here and you can declare it
// as static. That way you don't have to manage the instance of
// ring.
static double calculateDistance(int id_1, int id_2)
{
return (id_1 - id_2)/383; // The divisor is just random just like the calculation.
}
}
As the posts above say, it's just a matter of what you want to do and how you want to do it. Also, don't try to understand everything rightaway, write some code then try different approaches of that code and try to understand what your code does. Examples are good, but you need to write and then understand what you did. I think it's the only way you will figure out
why you do staff the way you have to do.
Static methods do not have to instantiate new objects everytime. Since object instantiation is expensive it allows instances to be cached within the object. So, it can improve performance.
This is the explanation from the Effective Java :
This allows immutable classes (Item 15) to use preconstructed
instances, or to cache instances as they’re constructed, and dispense
them repeatedly to avoid creating unnecessary duplicate objects. The
Boolean.valueOf(boolean) method illustrates this technique: it never
creates an object. This technique is similar to the Flyweight pattern
[Gamma95, p. 195]. It can greatly improve performance if equivalent
objects are requested often, especially if they are expensive to
create.
i.e. if you want to use a singleton, which means that you have only one instance of the object, which might be shared with others, then you need a static method, which will internally will call the constructor. So, every time someone wants an instance of that object you will return always the same, thus you will consume memory only for one. You always need a constructor in object oriented programming, in every OO language. In java an in many other languages the default constructor of an object is implied, and built automatically. But you need some custom functionality you have to make your own.
Above you see a few good examples of the usage. However, if you have something specific in your mind, please let us know. I mean if you have a specific case where you are not sure if you should use a static method or a constructor. Anyhow, you will definitely need a constructor, but I am not sure about the static method.