I have this code
public class TupleSpace implements aTupleSpace {
private Collection<aTuple> theSpace;
public TupleSpace() {
theSpace
}
public void out(aTuple v) {
theSpace.add(v);}
the .add causes an error, I think its either because .add is not defined for a generic collection type? or because im not properly understanding the line:
private Collection<aTuple> theSpace;
i have to keep this line the same but can make any changes to the out method or the rest of the class
I just want to be able to add things to a collection and search the collection for them
A Collection is just an Interface.
It defines what you can do with theSpace and is somewhat independent of what theSpace actually is. It may be a List or a Map or something entirely different.
Collection.add(E e) is indeed a method that is common to all Collections. Still the actual implementation might differ.
However, private Collection<aTuple> theSpace; is just declaring the variable.
It will be set to null when you create an instance of TupleSpace.
This is the reason for the NullPointerException that is thrown when you try to use theSpace.
Hence, you will need to create a concrete Collection instance and assign it to theSpace before you can use it (e.g. add objects).
There are plenty of Collection types that come ready to use with the SDK.
Choose one that fits your use case. Here is an example, using an ArrayList:
// ...
public TupleSpace() {
this.theSpace = new ArrayList<aTuple>();
}
// ...
Related
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'm trying to make a collection of observables and then add an observable into that collection.
Right now in this code, it's saying = new Observable<ArrayList<DMRegistration>>(); has protected access in rx.Observable and will not instantiate.
Also with dmRegistrations.add(dmRegistration); it complaining about add saying that it cannot resolve method 'add(rx.Observable)'
I'm very new with observables and have Googled around but have found nothing that provided information leading to a possible solution. Am I approaching this the wrong way?
#Override
public Observable<Collection<DMRegistration>>getAllRegistrations() throws DMException{
try{
Observable<Collection<DMRegistration>> dmRegistrations = new Observable<ArrayList<DMRegistration>>();
Observable<DMRegistration> dmRegistration = execute(get(baseUrl + "registrations"), DMRegistration.class);
dmRegistrations.add(dmRegistration);
return dmRegistrations;
}catch(RestException e){
throw new DMException(e);
}
}
Well, if the Observable constructor has protected access, then you can't use it unless you're working in the Observable class or a subclass of Observable. So if you want to make this work with minimal changes you'll have to either make this class a subclass of Observable or make the constructor public, but depending on your situation that may or may not be possible.
The reason the compiler is complaining about being unable to resolve add(rx.Observable) is because it means exactly what it says. It can't find a method matching that combination of name/parameter in the Observable class. Could be because the way you have Observable parameterized, as it appears that add() is looking for a different type than you want to put in.
I'm making a bit of a guess here as to the structure of Observable, but the type of element that you're trying to add doesn't seem to match the type of element that dmRegistrations takes. You declared that dmRegistrations is Observable<Collection<DMRegistration>>, which (I assume) means that you're observing Collection<DMRegistration>. You're trying to add an object of type Observable<DMRegistration>, which isn't what add() is looking for, unless Observable implements Collection.
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.
public static void main(String[] args) {
Set vals = new TreeSet();
vals.add("one");
vals.add(1);
vals.add("two");
System.out.println(vals);
}
(i)-What does it mean to define a collection without giving it a type?For what purpose
does it made for?
(ii)-Can I add different type to the collection any way?
Here's an example- There's no compilation error, though it's warning me.
But, as excepted, there's a run time error.
Defining a collection (or any typed class) without specifying a type argument is called using a raw type. It exists only for backwards compatibility and should not be used in new code. If effectively removes all effects of generics on the type.
Generally, you could define your set to accept Object: it would then accept all values: Set<Object> vals = new HashSet<Object>(). However this won't work for TreeSet, because it needs its values to be Comparable with each other. If you want to add arbitrary types to the same TreeSet (which is usually a sign of some architecture problems, i.e. a design smell), then you'll need to implement your own Comparator that can compare arbitrary elements and pass that into the appropriate TreeSet constructor.
i) It means it can have any object. If you want to add any type. (Generally a design problem)
ii) Using type erasure you can.
But, as excepted, there's a run time error.
Getting an error at compile time is usually better than getting a runtime error. (Easier to find and fix)
Upto Java 1.4 there were no Generics. All collections could only contain Object and you would have to classcast the object when using the object after taking it out of the collection. So you would do
Set vals = new Treeset();
String s = (String)vals.get(0);
instead of
Set<String> vals = new Treeset<String>();
String s = vals.get(0);
Putting different types of objects that have no shared interface or superclass is very bad practice since you wont know how to handle the object when you take it out of the collection.
private Set<JPanel> s1;
public void run() {
aMethod(s1);
}
/* line 7 */ public void aMethod(Set panels) {
}
If you refactor the above code by changing the 7th line to
public void aMethod(Set<Object> panels) {
it will no longer compile. If you refactor that line to
public void aMethod(Set<?> panels) {
it will still compile as before, and as an extra bonus you will no longer have the "Set is raw..." warning
considering i have a method which gets a List passed as an param. Within this method i want to use for instance an ArrayList specific function on that list (lets say trimToSize()). What would be the general approach to deal with a problem like this ?
Here two example:
First approach (i don't think this is good)
private void doSomething(final List<T> list) {
// ... do something
((ArrayList<T>) list).trimToSize();
// ... do something
}
Second approach (i think this one is better)
private void doSomething2(final List<T> list) {
final List<T> myList = new ArrayList<T>();
// Collections.copy(myList, list); or
myList.addAll(list);
((ArrayList<T>) myList).trimToSize();
//..do something
}
I'm curious whats the best solution for a problem like this.
Well, the preferred option is to just write the method to take an ArrayList in the first place. If you need ArrayList specific functionality, the method has no business taking a List. Transfer the responsibility of ensuring that the parameter is of the right type to the caller and don't fiddle around with it inside the method.
Why not just declare method as a private void doSomething(final ArrayList<T> list), if you want only ArrayList as parameter?
If you're accepting any object implementing the List interface then your function should only invoke methods implemented from the interface.
If you want to invoke functions from ArrayList class then have ArrayList as your parameter. Much safer than either of your options.
The second we have huge overhead with big lists, but is safer. I would go for the first, but with check whether the provided List is ArrayList and then make a cast.
You should have a strong reasons to not take an ArrayList as a parameter though.
The first option you've shown only works for ArrayLists so it's not an option if you want to support any type of List. If you want to support any type of List you must convert (not cast) it to an ArrayList.
I think there might be some confusion because the List and ArrayList are so closely related (by inheritance). It is only coincidence that the parameter type and the class we need to call the function on are related in this way.
If we abstract the requirements a bit:
We need to act on a series of values
We need to use trimToSize() on the
series of values.
If the values were coming as an array there would be no question but to create a new ArrayList with the values from the array and then use trimToSize(), because casting would not be an option. It is just bad luck that the method we need trimToSize() happens to be on a subclass of List, and the author wants to pass the values as a List.
What about
private void doSomething(final List<T> list) {
final ArrayList<T> arrayList;
if (list instanceof ArrayList) {
arrayList = (ArrayList<T>) list;
} else {
arrayList = new ArrayList<T>(list);
}
...
arrayList.trimToSize();
}
Of course, I agree with Chinmay Kanchi: for a private method, it makes no sense to accept a more general type than necessary. My approach is only feasible if it causes no problems to modify the given list.
Your first method changes the List passed to the method while the other one doesn't. Two methods are not comparable.
Since it is a private method, the convention of using the List interface is not overly important. There is no public API affected so use whichever method is the most convenient for its usage in the class.
For example, if 5 other methods call this method with potentially varying types of List, then use your second option and centralize the conversion in 1 method (you can even throw in a check for type and not convert if you like). If your class only deals with ArrayList internally anyway, and you know that is what it will be when called, then declare it as a ArrayList and make your life easy for yourself.