I've never had the chance to play much with generics before (as in writing classes that are generics), but now the need arises, and I've come across some confusion.
There's this interface, that is meant to be a wrapper of something. The implementations are not collections, so, every instance has access only to one something.
public interface Resource<T> {
// Expected operations:
void write(ResourceState state);
ResourceState read();
}
As implementations, I expect to have an ExclusiveResource<T>, and a ShareableResource<T>, that differ mainly/only in the locking scheme used (regular lock, and read-write lock, respectively).
As to how the read and write are performed, I'm planning on using the Strategy pattern.
For instance, I might have
// This would implement a Strategy<File>.
FileStrategy fs = new FileStrategy();
Resource<File> r = new ExclusiveResource<File>(fs);
Now, I've also got some sort of collection of these resources, say, a resource pool.
I'd like to map a key to each resource, in the resource pool, and I'd like to add, retrieve and remove resources, but I'm not sure how to declare the map and the methods. I've tried the following:
public class ResourcePool {
// instance variables
private final Map<String, Resource<?>> map;
/** Empty constructor of objects of class ResourcePool. */
public ResourcePool() {
map = new HashMap<String, Resource<?>>();
}
/** */
public Resource<?> get(String s) {
return map.get(s);
}
/** */
public void add(String s, Resource<?> r) {
map.put(s, r);
}
// ...
}
This does not seem to be the most appropriate way to do it, and, quoting Josh Bloch, on Effective Java Reloaded:
User should not have to think about wildcards to use your API.
I've tested this code with the following method:
public static void test() {
ResourcePool rp = new ResourcePool();
Resource<String> r1 = new ShareableResource<>("test");
Resource<Integer> r2 = new ShareableResource<>(1);
Resource<List<String>> r3 = new ShareableResource<>(
Arrays.asList(new String[]{"1", "2"})
);
// These are all ok.
rp.add("1", r1);
rp.add("2", r2);
rp.add("3", r3);
// This results in a compiler error (incompatible types).
Resource<String> g1 = rp.get("1");
// This results in a compiler warning (unsafe operation).
Resource<String> g2 = (Resource<String>) rp.get("1");
}
I don't like it, when the code compiles with warnings. Makes me feel guilty, and seems to be a hint at bad coding.
So, my question is how should I handle this situation.
Is this the right way to do what I'm trying to do?
Can this be done in such a way that there are no unsafe operations?
I don't think there's any way to avoid unchecked casts using your design. That said, you can avoid having to do a cast every time you retrieve a Resource:
#SuppressWarnings("unchecked")
public <T> Resource<T> get(String s, Class<T> c) {
return (Resource<T>) map.get(s);
}
When you want to retrieve a Resource, you pass in the desired class, like so:
Resource<String> g1 = rp.get("1", String.class);
You should be careful with this design, though, since there will be no runtime guarantee that the returned Resource is actually a Resource<String>.
You could create different collections for each type of resource you want, and make ResourcePool generic also:
ResourcePool<String> stringpool = new ResourcePool<String>();
ResourcePool<Integer> intpool = new ResourcePool<Integer>();
This would give you the benefits of compile-time checking on your types. And it seems that you know what type you want whenever you get something out of the ResourcePool, so you can select the appropriate collection.
Related
I want to modify list of already created objects in stream. I realized three approaches that may do that, but I not sure about their performance and possible downsize.
Return same object - not waste of time to creating new object, but object is mutable
Create new object - parameter is not modified, but for huge object creation is time consuming
Modify parameter - can only use ForEach, no parallel usage
Code below code with explaining comments.
public class Test {
public static void main(String[] args) {
//Already created objects
List<Foo> foos0 = Arrays.asList(new Foo("A"));
//However I need to apply some modification on them, that is dependent on themselves
//1. Returning same object
List<Foo> foos1 = foos0.stream().map(Test::modifyValueByReturningSameObject).collect(Collectors.toList());
//2. Creating new object
List<Foo> foos2 = foos0.stream().map(Test::modifyValueByCreatingNewObject).collect(Collectors.toList());
//3. Modifying param
foos0.stream().forEach(Test::modifyValueByModifyingParam);
}
//Lets imagine that all methods below are somehow dependent on param Foo
static Foo modifyValueByReturningSameObject(Foo foo) {
foo.setValue("fieldValueDependentOnParamFoo");
return foo;
}
static Foo modifyValueByCreatingNewObject(Foo foo) {
Foo newFoo = new Foo("fieldValueDependentOnParamFoo");
return newFoo;
}
static void modifyValueByModifyingParam(Foo foo) {
foo.setValue("fieldValueDependentOnParamFoo");
return;
}
}
public class Foo {
public String value;
public Foo(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
So the question is which is the most stream approach?
EDIT:
By stream approach I mean, that the most advantages in sense of performence.
EDIT2:
1. Which is functional approach?
2. Which is best in sense of performance?
The javadoc states that Streams should avoid side effects :
Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.
So, you should prefer the solution where you create new objects instead of modifying existing ones.
The different aproaches will in your case most likely result in no difference regarding performance.
Reason: optimization. Java will not really create new classes and will use direct access to fields. It might(and will if analysis sugests it) even skip a whole chain of calls and replace it by a precalculated value. Java runtime even utilizes a profiler to optimize and find hotspots...
Also: Regarding performance it is in general(particular cases may differ) more important to create a simple structure and help the runtime to make the right assumptions.
So if you hide what you are doing in unesseary manual "optimization", that hides optimization posibilities(lots of branches/decisions, unnecessary pinning, chain of "unknown" methods ...) from the runtime you might end up with a slower result.
For clarity and sideffects(see also other answer) I rather use the version that creates new instances.
If an object reference is passed to a method, is it possible to make the object "Read Only" to the method?
Not strictly speaking. That is, a reference that can mutate an object can not be turned into a reference that can not mutate an object. Also, there is not way to express that a type is immutable or mutable, other than using conventions.
The only feature that ensure some form of immutability would be final fields - once written they can not be modified.
That said, there are ways to design classes so that unwanted mutation are prevented. Here are some techniques:
Defensive Copying. Pass a copy of the object, so that if it is mutated it doesn't break your internal invariants.
Use access modifiers and/or interface to expose only read-only methods. You can use access modifieres (public/private/protected), possibly combined with interface, so that only certain methods are visible to the other object. If the methods that are exposed are read-only by nature, you are safe.
Make your object immutable by default. Any operation on the object returns actually a copy of the object.
Also, note that the API in the SDK have sometimes methods that return an immutable version of an object, e.g. Collections.unmodifiableList. An attempt to mutate an immutable list will throw an exception. This does not enforce immutability statically (at compile-time with the static type system), but is is a cheap and effective way to enforce it dynamically (at run-time).
There has been many research proposals of Java extension to better control of aliasing, and accessibility. For instance, addition of a readonly keyword. None of them is as far as I know planned for inclusion in future version of Java. You can have a look at these pointers if you're interested:
Why We Should Not Add ''Read-Only'' to Java (yet) -- it lists and compare most of the proposals
The Checker Framework: Custom pluggable types for Java -- a non intrusive way to extend the type system, notably with immutable types.
The Checker Framework is very interesting. In the Checker Framework, look at Generic Universe Types checker, IGJ immutability checker, and Javari immutability checker. The framework works using annotations, so it is not intrusive.
No, not without decorating, compositing, cloning, etc.
There's no general mechanism for that. You'll need to write special-case code to achieve it, like writing an immutable wrapper (see Collections.unmodifiableList).
You could achieve a similar thing in most cases by cloning the Object as the first statement of the method, such as this...
public void readOnlyMethod(Object test){
test = test.clone();
// other code here
}
So if you called readOnlyMethod() and pass in any Object, a clone of the Object will be taken. The clone uses the same name as the parameter of the method, so there's no risk of accidentally changing the original Object.
No. But you could try to clone the object before passing it, so any changes made by the method won't affect the original object.
making it implement a interface which has only read only methods (no setter methods) this gives a copy of an object (road-only copy) and returning the read only instance of interface instead of returning the instance of an object itself
You could define all parameters of the objects as final but that makes the object read only to everyone.
I believe your real question is about avoiding escape references.
As pointed out in some answers to extract an Interface from class and expose only get methods. It will prevent modification by accident but it is again not a foolproof solution to avoid above problem.
Consider below example:
Customer.java:
public class Customer implements CustomerReadOnly {
private String name;
private ArrayList<String> list;
public Customer(String name) {
this.name=name;
this.list = new ArrayList<>();
this.list.add("First");
this.list.add("Second");
}
#Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public ArrayList<String> getList() {
return list;
}
public void setList(ArrayList<String> list) {
this.list = list;
}
}
CustomerReadOnly.java:
public interface CustomerReadOnly {
String getName();
ArrayList<String> getList();
}
Main.java:
public class Test {
public static void main(String[] args) {
CustomerReadOnly c1 = new Customer("John");
System.out.println("printing list of class before modification");
for(String s : c1.getList()) {
System.out.println(s);
}
ArrayList<String> list = c1.getList();
list.set(0, "Not first");
System.out.println("printing list created here");
for(String s : list) {
System.out.println(s);
}
System.out.println("printing list of class after modification");
for(String s : c1.getList()) {
System.out.println(s);
}
}
}
Ouput:
printing list of class before modification
First
Second
printing list created here
Not first
Second
printing list of class after modification
Not first
Second
So, as you can see extracting interface and exposing only get methods works only if you don't have any mutable member variable.
If you have a collection as a member variable whose reference you don't want to get escape from class, you can use Collections.unmodifiableList() as pointed out in ewernli's answer.
With this no external code can modify the underlying collection and your data is fully read only.
But again when it comes to custom objects for doing the same, I am aware of the Interface method only as well which can prevent modification by accident but not sure about the foolproof way to avoid reference escape.
Depending on where you want the rule enforced. If you are working collaboratively on a project, use final with a comment telling the next person they are not meant to modify this value. Otherwise wouldn't you simply write the method to not touch the object?
public static void main(String[] args) {
cantTouchThis("Cant touch this");
}
/**
*
* #param value - break it down
*/
public static void cantTouchThis(final String value) {
System.out.println("Value: " + value);
value = "Nah nah nah nah"; //Compile time error
}
So specifically to this method, the value will never be written to, and it is enforced at compile time making the solution extremely robust. Outside the scope of this method, the object remains unaltered without having to create any sort of wrapper.
private boolean isExecuteWriteQueue = false;
public boolean isWriting(){
final boolean b = isExecuteWriteQueue;
return b;
}
Expanding on ewernli's answer...
If you own the classes, you can use read-only interfaces so that methods using a read-only reference of the object can only get read-only copies of the children; while the main class returns the writable versions.
example
public interface ReadOnlyA {
public ReadOnlyA getA();
}
public class A implements ReadOnlyA {
#Override
public A getA() {
return this;
}
public static void main(String[] cheese) {
ReadOnlyA test= new A();
ReadOnlyA b1 = test.getA();
A b2 = test.getA(); //compile error
}
}
If you don't own the classes, you could extend the class, overriding the setters to throw an error or no-op, and use separate setters. This would effectively make the base class reference the read-only one, however this can easily lead to confusion and hard to understand bugs, so make sure it is well documented.
The JavaDoc for the LambdaMetaFactory of Java 1.8 specifies that lambda capture "may involve allocation of a new function object, or may return an existing function object", but it doesn't specify when and under what circumstances it might choose one way or the other.
Looking at the actual implementation of the LambdaMetaFactory, on the other hand, it is clear that it happens if and only if the lambda expression captures no parameters.
What I'm wondering is, is this behavior actually specified somewhere (outside of the JavaDoc) and can be relied upon? It would be nice to know whether I can rely on a lambda expression's identity being constant or not.
There is essentially no contract that covers the identity of objects that result from evaluating a lambda expression. This is covered in the JLS section 15.27.4, Run-time Evaluation of Lambda Expressions. This section explicitly leaves unspecified the exact behavior of creation vs reuse of lambda objects. The rationale from that section explains this well:
These rules are meant to offer flexibility to implementations of the Java programming language, in that:
A new object need not be allocated on every evaluation.
Objects produced by different lambda expressions need not belong to different classes (if the bodies are identical, for example).
Every object produced by evaluation need not belong to the same class (captured local variables might be inlined, for example).
If an "existing instance" is available, it need not have been created at a previous lambda evaluation (it might have been allocated during the enclosing class's initialization, for example).
You can, of course, experiment with the implementation, call equals() or use == on lambda objects, put them into IdentityHashMaps, etc., but since these exact behaviors are unspecified, your program may change its behavior (i.e., break) when run on different versions of the JDK or on different implementations of Java SE.
I read the exchange in the comments below the question but I don't really have anything more to offer. Perhaps if you explain what you're trying to do, we could come up with some suggestions for alternatives to using lambdas as keys in a map.
You should separate behavior from identity. Lambdas can be used to implement behavior while a single ordinary class can be used to implement identity by creating instances out of it. The following simplified example derived from your code should illustrate it:
import java.util.function.Function;
public class MeshBuf
{
{
// use case 1:
LayerID<Col> idCol = new LayerID<>(mbuf -> mbuf.new Col());
// use case 2:
Attribute attrib=…;
LayerID<Vec1Layer> idVec1 = new LayerID<>(mbuf->new Vec1Layer(attrib));
// the expression new LayerID<>(…) is guaranteed to create new instances…
LayerID<Vec1Layer> idVec2 = new LayerID<>(mbuf->new Vec1Layer(attrib));
// therefore idVec1 != idVec2 even if referring to the same expression
}
// single class is enough for maintaining the identity
public static final class LayerID<L> {
private final Function<MeshBuf, L> cons;
public LayerID(Function<MeshBuf, L> f) {
cons = f;
}
public L cons(MeshBuf buf) {
return cons.apply(buf);
}
}
// the other classes are taken from your code, unchanged
public class Col extends Layer<Color> {
public VertexBuf.ColorArray build(Collection<Color> in) {
FloatBuffer data = Utils.wfbuf(in.size() * 4);
for(Color c : in) {
data.put(c.getRed() / 255.0f); data.put(c.getGreen() / 255.0f);
data.put(c.getBlue() / 255.0f); data.put(c.getAlpha() / 255.0f);
}
return(new VertexBuf.ColorArray(data));
}
}
public abstract class AttribLayer<T> extends Layer<T> {
public final Attribute attrib;
public AttribLayer(Attribute attrib) {
this.attrib = attrib;
}
}
public class Vec1Layer extends AttribLayer<Float> {
public Vec1Layer(Attribute attrib) {super(attrib);}
public VertexBuf.Vec1Array build(Collection<Float> in) {
FloatBuffer data = Utils.wfbuf(in.size());
for(Float d : in)
data.put(d);
return(new VertexBuf.Vec1Array(data, attrib));
}
}
}
I have a following problem:
I had a few methods that are basically used to get something from Salesforce.
Here is an example:
public Map<String, Customer> findSomethingByIds(String[] somethingIds) throws... {
return binding.findSomethingByIds(somethingIds);
}
For a number of reasons I needed to retry the execution of this method in a very rare cases (f.e session expires etc.), so I used this.
So now I have something like this:
public Map<String, Something> findSomethingByIds(final String[] somethingIds) throws ... {
Map<String, Something> myList = null;
Callable<Map<String, Something>> task = new Callable<Map<String, Something>>() {
#Override
public Map<String, Something> call() throws Exception {
return binding.findSomethingByIds(somethingIds);
}
};
RetriableTask<Map<String, Something>> r = new RetriableTask<>(2, 1000, task);
try {
myList = r.call();
} catch (Exception e) {
// Ex. handling
}
return myList;
}
Now, there are a lot of such methods in my code, so if I want to use the RetriableTask interface I have to add a lot of code to those methods, similar to the one above, which I want to avoid at all costs. All those methods pretty much return something different, so I can't use a Factory here (or I don't know how). Does anyone know any solution for this? Any help would be appreciated.
If you have a method doing something similar and the only difference is the return type, try using generics:
public Map<String, T> findSomethingByIds(final String[] somethingIds) throws ... {
}
This will allow you to perform equivalent processing on different object types without copying and pasting code everywhere.
Responding to the comments, if they take different parameter types, you can still use generics in the parameters. If you mean they have a different number of parameters (i.e., have a completely different signature), then you can create wrapper methods which perform the processing which is unique to that object type, and after that you can pass control to the generic method for the processing which is common to all object types.
I am creating several functions in which I want to return the interface instead of the implementation, I.E. List instead of ArrayList . My method signature and a brief implementation follows:
public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>)
{
List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>();
for(MyAwesomeObject awesomeObject : awesomeObjects)
{
MyAwesomeComposedObject composedObject = new MyAwesomeComposedObject(awesomeObject);
composedObjects.add(composedObject);
}
List<MyAwesomeComposedObject> composedObjectList = Collections.checkedList<composedObjects, MyAwesomeComposedObject.class);
return composedObjectList;
}
My question is, is this an antipattern of some sort? I want to guarantee that the invoker of this method is getting the interface instead of an implementation. I also do not believe this to be a case of overengineering. If this is not the correct way to return an interface, in this scenario I am open to the correct implementation.
Attached is a small program that results in an exception:
public static void main(String[] args)
{
Vector v = (Vector) c();
}
static List<Object> c()
{
List<Object> l = new ArrayList<Object>();
l.add(new Object());
List<Object> o = Collections.checkedList(l, Object.class);
return o;
}
The javadoc is here: checked list
The List returned is a Collections.CheckedList not a Vector. You cannot the reference to a type the object is not.
However what you can do is
public static void main(String[] args) {
Vector<Object> v = new Vector<Object>(c());
}
composedObjects is already a List, you can return that.
public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>) {
List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>();
for(MyAwesomeObject awesomeObject : awesomeObjects)
composedObjects.add(new MyAwesomeComposedObject(awesomeObject));
return composedObjects;
}
For your revised question: There is no way to prevent the caller from attempting to cast to whatever they want. If it is an inappropriate cast they will get the exception. This is the very reason why casting from an interface to a concrete class is strongly discouraged.
If you are really worried about this, consider returning an ArrayList instead of a List. That should discourage casting since they are getting a concrete type. Please note that I do not endorse this, it is just an option.
I want to guarantee that the invoker of this method is getting the interface instead of an implementation
This is not valid. You are returning a List where the declared type of the elements is an interface, however each element must be SOME instantiation. All a checked collection does is prevent the addition of elements of the incorrect type. There is nothing that prevents the user from casting back to the implementation type.
If you are attempting to ensure that the user gets List instead of ArrayList (my assumption here because I don't see an interface for you Awesome class), this again is flawed because the user could still cast the List to an ArrayList although this would be a bad idea since it risks a ClassCastException.
No, I recommend to keep the code as simple as possible. Read the Javadoc for a discussion when to use Collections.checkedList
http://download.oracle.com/javase/7/docs/api/java/util/Collections.html#checkedCollection%28java.util.Collection,%20java.lang.Class%29