This is a question for Java. I have an interface called IMyObjectPredicate which implements a single test method to apply to an input:
public interface IMyObjectPredicate {
boolean test(MyObject x);
}
What I would like is to be able to pass an instance of IMyObjectPredicate around between objects and have the test function update its references to variables to those of the new object it is being passed to. For instance, consider a class which makes use of this predicate:
public class Tester {
MyObject o;
IMyObjectPredicate myTestFunction;
int myThreshold;
public Tester(/*stuff*/) {
/*Code here which initialises the Tester instance and 'myThreshold'*/
myTestFunction = new IMyObjectPredicate() {
#Override
public boolean test(MyObject o) {
return (o.value() > myThreshold);
}
};
}
public boolean isGood() {
return myTestFunction.test(o);
}
}
I would like to be able to perform a deep clone of the Tester object for reasons I won't go into here. But the idea is that the cloned instance of Tester should test the predicate against its own value of myThreshold, not reference the myThreshold of the first instance. But if I pass myTestFunction to a new instance of Tester, I guess it will still be referencing the myThreshold value of the first instance, instead of dynamically evaluating myThreshold based on the reference of the enclosing class.
How can I accomplish the passing of a IMyObjectPredicate object whose test function uses references to the fields of the new object it is passed to?
Edit:
A complicating factor is that, in general, it will not be possible to reconstruct myTestFunction solely from the fields within a Tester object. myTestFunction may be overwritten by other parts of the program in a way that does not correlate with the other fields of Tester. I can sacrifice this functionality if need be, but I would rather not for the sake of elegance.
Java does not have an API to replace enclosed context of anonymous class.
The simplest solution I can see from your simplified example is to add threshold to the signature of test function. As I understand the threshold is going to be there anyway.
public interface IMyObjectPredicate {
boolean test(MyObject x, int threshold);
}
Another approach would use some factory method that will create a predicate for provided threshold like
class PredicateFactory {
IMyObjectPredicate thresholdPredicate(int threshold) {
return new IMyObjectPredicate {
//...
}
}
}
then you can pas this factory to object that will use it's own threshold to construct new instance of predicate
factory.thresholdPredicate(myThreshold);
It is a lot easier if ImObjectPredicate is an class that simply stores a reference to a predicate instead of an interface. If you're able to make that change, each predicate can store its own threshold, which solves the issue.
public IMyObjectPredicate {
private int threshold;
private Predicate<MyObject> pred;
public int getThreshold() {
return threshold;
}
public Predicate<MyObject> getPredicate() {
return pred;
}
public IMObjectPredicate(int threshold, Predicate<MyObject> pred) {
this.threshold = threshold;
this.pred = pred;
}
public boolean test(MyObject o) {
return pred.test(o);
}
}
public class Tester {
MyObject o;
IMyObjectPredicate myTestFunction;
IMyObjectPredicate myTestFunctionCopyWithDiffThreshold;
int myThreshold;
public Tester(/*stuff*/) {
/*Code here which initialises the Tester instance and 'myThreshold'*/
myTestFunction =
new IMyObjectPredicate(myThreshold, o -> o.value() > getThreshold());
myTestFunctionCopyWithDiffThreshold =
new ImObjectPredicate(5, myTestFunction.getPredicate());
}
public boolean isGood() {
return myTestFunction.test(o);
}
}
This is the most sensible solution, as ImObjectPredicate should store its own threshold if that value uniquely refers to that ImObjectPredicate.
Related
I know the Java compiler generates different classes for lambda functions depending on the context and closure they have. When I receive the lambda as a parameter (using the Consumer<> class), may I know the lifetime of the parameter?
For example, I have the following Observable class, that keeps a weak reference to its observes.
class Observable {
private final List<WeakReference<Consumer<Object>>> observables = new ArrayList<>();
private Object obj;
public Observable(Object obj){
this.obj = obj;
}
public void observe(Consumer<Object> cons){
this.observables.add(new WeakReference<>(cons));
}
public void set(Object obj){
this.obj = obj;
// notify observes
for(WeakReference<Consumer<Object>> cons : this.observables){
if(cons.get() != null)
cons.get().accept(this.obj);
// clearing the non-existing observes from the list is ommited for simplicity
}
}
}
Now I use it as follows.
public class Main {
public static void main(String[] args) {
Object c = new Object();
Observable obs = new Observable(c);
new ContainingClass(obs);
obs.set(c);
System.gc();
obs.set(c);
}
}
The code just creates the object and its observer and creates ContainingClass (definition follows) that observes. Then the object is set once, garbage collector explicitly called (so the created ContainingClass is deleted) and set the object a second time.
Now, as long as the lambda is instance-specific (reference either this or its instances method) it's called only once (because it is destroyed by the GC).
public class ContainingClass {
public ContainingClass(Observable obs){
obs.observe(this::myMethod);
}
private void myMethod(Object obj) {
System.out.println("Hello here");
}
}
public class ContainingClass {
private Object obj;
public ContainingClass(Observable obs){
obs.observe(obj -> {
this.obj = obj;
System.out.println("Hello here");
});
}
}
But as the lambda becomes static, it is called twice, even after GC.
public class ContainingClass {
public ContainingClass(Observable obs){
obs.observe((obj) -> System.out.println("Hello here"));
}
}
The reference to this lambda is never destroyed and therefore add as an observer every time ContainingClass instance is created. As a result, it will be stuck in observers until the program ends.
Is there a way to detect this and at least show a warning, that the lambda will be never removed?
One thing I figured out is that lambda with instance lifetime has arg$1 property, so I can ask about the number of properties.
public void observe(Consumer<Object> cons){
if(cons.getClass().getDeclaredFields().length == 0)
System.out.println("It is static lifetime lambda");
this.observables.add(new WeakReference<>(cons));
}
Is it a universal approach? May there be a situation when this doesn't work?
I think a good solution would be the one hinted by #Olivier: you can return an object with a remove method that removes your Consumer from your list when called, like the following example:
#FunctionalInterface
public interface Registration {
void remove();
}
class Observable {
private final List<Consumer<Object>> observables = new ArrayList<>();
private Object obj;
public Observable(Object obj) {
this.obj = obj;
}
public Registration observe(Consumer<Object> cons) {
this.observables.add(cons);
return () -> this.observables.remove(cons);
}
public void set(Object obj) {
[...]
}
}
The alternative would be to check if the class the lambda belongs to is static or not, as suggested by #kutschkem, but I don't like resorting to introspection if there is a good alternative.
As already stated by #shalk, relying on WeakReference to handle GC can lead to unwanted behaviours, because there is no way to ensure that your Consumer isn't referenced (maybe by mistake) somewhere else.
Your question is similar to this question, so the answers there apply here too.
A static nested class has a flag that can be checked:
Modifier.isStatic(clazz.getModifiers()) // returns true if a class is static, false if not
Is it okay to pass an object type, or simply a type of any kind into the constructor of a new object then not use it inside of the constructor?
The purpose is to have the new object be created based on what parent class it resides in (it is aggregated) so it generates different variables for itself based on that fact.
Or is there a better way to do this?
public class ObjectA {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(this);
}
}
public class ObjectB {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(this);
}
}
public class MalleableObject{
private boolean doIBelongToA;
public MalleableObject(ObjectB obj){
doIBelongToA = false;
}
public MalleableObject(ObjectA obj){
doIBelongToA = true;
}
}
The approach you are taking will definitely work, But the question is whether it is a good idea or not, The answer is depends on the use case that you are trying to tackle.
You asked about taking a object as parameter in constructor and not using it
If you are not using the property of passed parameter then why to take that in parameter, for that we have empty constructor , even when you don't specify it is by default injected
public MalleableObject(ObjectB obj){
doIBelongToA = false; // if you are directly setting the value without
//using obj b then use default constructor.
}
public MalleableObject(ObjectA obj){
doIBelongToA = true;
}
/*If you are interested in setting the value based on the reference only there
is no problem with your approach as well, One alternative you can take to
combine both of them in single constructor and check the reference and set
the value accordingly*/
If you use the property of the object for creating new object then certainly it's a good idea,
Copy constructor if you are using same object as parameter, Prototype design pattern if you are creating your object with similiar object already created
The example that you gave is a very basic example which does not highlight any use case and hence the approach you have taken will not be suggested
The simpler approach would be just adding the boolean variable in the constructor of MalleableObject.
public class ObjectA {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(true);
}
}
public class ObjectB {
private MalleableObject obj;
public void createObject(){
obj = new MalleableObject(false);
}
}
public class MalleableObject{
private boolean doIBelongToA;
public MalleableObject(boolean doIBelongToA){
this.doIBelongToA = doIBelongToA;
}
}
This would easily assure that the object made from class A has value true for doIBelongToA.
Also, you will not have to add different constructors for further classes, if added, ensuring extensibility
While you aren't using it directly, you are definitely using information from the parameter. Personally, I'd save the reference, or at least its type, for later use in case you need it and implement doIBelongToA as a method, but there's nothing technically wrong with your approach:
public class MalleableObject{
private Class ownerType;
public MalleableObject(Class ownerType) {
this.ownerType = ownerType;
}
public boolean doBelongToA() {
return ownerType.equals(ObjectA.class);
}
}
The above approach works but it's not a best practice and hence has some limitations. I would suggest you use builder pattern where you can create use of a builder to create an object and then have a method that defines the behavior. You will be able to extend this to add variables/business logic in the future.
I think the Factory pattern is also good
thing to look at
I have two ArrayLists - ArrayList1 and ArrayList2. Each of them is filled with objects - Object1 and Object2, respectively.
Both of these objects have method 'getText'.
Object1:
public String getText() { return "1";}
Object2:
public String getText() { return "2";}
At certain point I would like to loop through each of these lists using the same method (just with different parameter).
loopThroughList(1)
loopThroughList(2)
What is the syntax if I want to call a method, but I don't know which object it is going to be? This is the code I have so far:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getText());
}
It says Cannot resolve method getText. I googled around and found another solution:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
But this gives me NoSuchMethodException error. Even though the 'getText' method is public.
EDIT: To get the correct list, I am calling the method 'getList' of a different object (lists) that returns either ArrayList1 or ArrayList2 (depending on the provided parameter).
class Lists
public getList(list) {
if (list == 1) {
return ArrayList1;
}
else if (list == 2) {
return ArrayList2;
}
}
Define an interface for the getText method
public interface YourInterface {
String getText();
}
Implement the interface on the respective classes
public class Object1 implements YourInterface {
#Override
public String getText() {
return "1";
}
}
public class Object2 implements YourInterface {
#Override
public String getText() {
return "2";
}
}
Modify your getList method to return List<YourInterface>
public static List<YourInterface> getList(int list){
List<YourInterface> result = new ArrayList<>();
if(list == 1){
// your initial type
List<Object1> firstList = new ArrayList<>();
result.addAll(firstList);
} else {
// your initial type
List<Object2> secondList = new ArrayList<>();
result.addAll(secondList);
}
return result;
}
Declaration for loopThroughList
public static void loopThroughList(List<YourInterface> list){
list.forEach(yourInterface -> System.out.println(yourInterface.getText()));
}
Sample usage.
public static void main(String[] args) {
loopThroughList(getList(1));
loopThroughList(getList(2));
}
Interfaces work great here, but there a couple of other options if you're dealing with legacy code and cannot use interfaces.
First would be to cast the list items into their respective types:
for (Object o : lists.getList(listNumber)) {
if(o instanceof Object1) {
Object1 o1 = (Object1)o;
System.out.println(o1.getText());
}
else if(o instanceof Object2) {
Object1 o2 = (Object2)o;
System.out.println(o2.getText());
}
else {
System.out.println("Unknown class");
}
}
You can also use reflection to see if the object has a getText method and then invoke it:
for (Object o : lists.getList(listNumber)) {
try {
System.out.println(o.getClass().getDeclaredMethod("getName").invoke(o));
}
catch(Exception e) {
System.out.println("Object doesn't have getText method");
}
}
This is awful. Can you elaborate on what specifically you are trying to do? Java is strong typed by design, and you are trying to get around it. Why? Instead of Object, use the specific class, or interface as previously suggested. If that's not possible, and you must use lists of Objects, use instanceof and casting eg:
for (Object o : lists.getList(listNumber)) {
if (o instanceof Object1) {
Object1 o1 = (Object1) o;
System.out.println(o1.getText());
} else if (o instanceof Object2) {
Object2 o2 = (Object2) o;
System.out.println(o2.getText());
}
}
This is where interfaces come in.
interface HasText {
public String getText();
}
class Object1 implements HasText {
#Override
public String getText() {
return "1";
}
}
class Object2 implements HasText {
#Override
public String getText() {
return "2";
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2());
for (HasText ht : list) {
System.out.println(ht);
}
}
If one of your objects is not in your control you can use a Wrapper class.
class Object3DoesNotImplementHasText {
public String getText() {
return "3";
}
}
class Object3Wrapper implements HasText{
final Object3DoesNotImplementHasText it;
public Object3Wrapper(Object3DoesNotImplementHasText it) {
this.it = it;
}
#Override
public String getText() {
return it.getText();
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2(), new Object3Wrapper(new Object3DoesNotImplementHasText()));
for (HasText ht : list) {
System.out.println(ht);
}
}
Just to add more to this answer and give you some more to think on this (Will try to do it in a simple, non-formal way). Using interfaces is the proper way of doing such operation. However, I want to stand on the "bad idea":
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
What you are doing here, is using a mechanism called Reflection:
Reflection is a feature in the Java programming language. It allows an
executing Java program to examine or "introspect" upon itself, and
manipulate internal properties of the program. For example, it's
possible for a Java class to obtain the names of all its members and
display them.
What you actually attempted, is using that mechanism, to retrieve the method through a Class reflection object instance of your Class (sounds weird, isn't it?).
From that perspective, you need to think that, if you want to invoke your method, you now have, in a sense, a meta-Class instance to manipulate your objects. Think of it like an Object that is one step above your Objects (Similarly to a dream inside a dream, in Inception). In that sense, you need to retrieve the method, and then invoke it in a different (meta-like) way:
java.lang.reflect.Method m = o.getClass().getMethod("getText");
m.invoke(o);
Using that logic, you could possibly iterate through the object list, check if method exists, then invoke your method.
This is though a bad, BAD idea.
Why? Well, the answer relies on reflection itself: reflection is directly associated with runtime - i.e. when the program executes, practically doing all things at runtime, bypassing the compilation world.
In other words, by doing this, you are bypassing the compilation error mechanism of Java, allowing such errors happen in runtime. This can lead to unstable behavior of the program while executing - apart from the performance overhead using Reflection, which will not analyze here.
Side note: While using reflection will require the usage of Checked Exception handling, it still is not a good idea of doing this - as you practically try to duck tape a bad solution.
On the other hand, you can follow the Inheritance mechanism of Java through Classes and Interfaces - define an interface with your method (let's call it Textable), make sure that your classes implement it, and then use it as your base object in your list declaration (#alexrolea has implemented this in his answer, as also #OldCurmudgeon has).
This way, your program will still make the method call decision making at Runtime (via a mechanism called late binding), but you will not bypass the compilation error mechanism of Java. Think about it: what would happen if you define a Textable implementation without providing the class - a compile error! And what if you set a non-Textable object into the list of Textables? Guess what! A compile error again. And the list goes on....
In general, avoid using Reflection when you are able to do so. Reflection is useful in some cases that you need to handle your program in such a meta-way and there is no other way of making such things. This is not the case though.
UPDATE: As suggested by some answers, you can use instanceof to check if you have a specific Class object instance that contains your method, then invoke respectively. While this seems a simple solution, it is bad in terms of scaling: what if you have 1000 different classes that implement the same method you want to call?
your objects have to implement a common interface.
interface GetTextable {
String getText();
}
class One implements GetTextable {
private final String text;
public One(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
class Two implements GetTextable {
private final String text;
public Two(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
#Test
public void shouldIterate() throws Exception {
List<GetTextable> toIterate = Arrays.asList(new One("oneText"), new Two("twoText"));
for(GetTextable obj: toIterate) {
System.out.println(obj.getText());
}
}
I'm not quite sure how to ask this question without posting the whole code here (it's quite a bit), but I'll try my best.
I have an enum class which implements an interface. The purpose of the whole program is to represent a bunch of integer numbers in Fields. So there is a concrete class TrueField which is derived from abstract class AbstractField that has the implementation of a method called boolean sameAs(Field that). That method also exists (it has to, because of the interface) in the enum class:
enum SimpleField implements Field{
Empty(),Zero(0),Binary(0,1),Unsigned(Integer.MAX_VALUE);
private Field simpleField;
SimpleField(int... intArray){
simpleField = new TrueField(intArray);
}
#Override
public boolean sameAs(Field that){
return that.sameAs(simpleField);
}
}
Implementation from TrueField:
public class TrueField extends AbstractField{
private final int[] intArray;
TrueField(int... thatArray){
intArray = thatArray;
}
#Override
public int at(int index){
if(index<0 || index>=intArray.length){
throw new IndexOutOfBoundsException();
}
return intArray[index];
}
#Override
public int length(){
return intArray.length;
}
...
AbstractField:
public abstract class AbstractField implements Field{
#Override
public abstract int length();
#Override
public boolean sameAs(Field that){
if(that==null)
throw new RuntimeException("that is null");
boolean result = true;
if(length()==that.length()){
for(int i=0;i<length();i++){
if(at(i)!=that.at(i))
result = false;
}
}
else
result = false;
return result;
}
#Override
public String toString(){
String result = "";
for(int i=0;i<length();i++){
result += at(i);
if(length()-i>1)
result += ",";
}
return "["+result+"]";
}
}
My question is, when I do something like this in my main method:
Field sf = SimpleField.Binary;
Field sf2 = SimpleField.Binary;
Field tf = new TrueField(1,2);
System.out.println(sf.sameAs(sf2));
...obviously the method sameAs in the enum class gets called. But why isn't it calling itself again so it is recursive? As there is dynamic binding because of the interface the JVM sees that sf is the dynamic type SimpleField.Binary and the static type Field. I don't quite understand what's going on and why it isn't calling itself again. I hope I've explained my question clear enough.
It's not recursive because your sameAs method in the SimpleField enum calls the sameAs method of the parameter object, which is not a SimpleField, it's a TrueField.
So the sameAs method is being run as declared in the Field class.
On further inspection, it could be recursive, but only if the declaration in the TrueField class was recursive also, which we can see that it is not, now that this code has been added above.
The method isn't recursive because it's not calling itself.
#Override
public boolean sameAs(Field that){
return that.sameAs(simpleField);
}
This method is using the argument to call sameAs. The argument may very well be the same enum, but it's still not calling itself.
This is an example of a simple recursive method:
public long factorial(int value) {
return value == 0 ? 1 : factorial(value-1);
}
In this, there's no extra reference to use to call the method again; I'm just invoking it once more with a slight change in parameters.
With the introduction of generics, I am reluctant to perform instanceof or casting as much as possible. But I don't see a way around it in this scenario:
for (CacheableObject<ICacheable> cacheableObject : cacheableObjects) {
ICacheable iCacheable = cacheableObject.getObject();
if (iCacheable instanceof MyObject) {
MyObject myObject = (MyObject) iCacheable;
myObjects.put(myObject.getKey(), myObject);
} else if (iCacheable instanceof OtherObject) {
OtherObject otherObject = (OtherObject) iCacheable;
otherObjects.put(otherObject.getKey(), otherObject);
}
}
In the above code, I know that my ICacheables should only ever be instances of MyObject, or OtherObject, and depending on this I want to put them into 2 separate maps and then perform some processing further down.
I'd be interested if there is another way to do this without my instanceof check.
Thanks
You could use double invocation. No promises it's a better solution, but it's an alternative.
Code Example
import java.util.HashMap;
public class Example {
public static void main(String[] argv) {
Example ex = new Example();
ICacheable[] cacheableObjects = new ICacheable[]{new MyObject(), new OtherObject()};
for (ICacheable iCacheable : cacheableObjects) {
// depending on whether the object is a MyObject or an OtherObject,
// the .put(Example) method will double dispatch to either
// the put(MyObject) or put(OtherObject) method, below
iCacheable.put(ex);
}
System.out.println("myObjects: "+ex.myObjects.size());
System.out.println("otherObjects: "+ex.otherObjects.size());
}
private HashMap<String, MyObject> myObjects = new HashMap<String, MyObject>();
private HashMap<String, OtherObject> otherObjects = new HashMap<String, OtherObject>();
public Example() {
}
public void put(MyObject myObject) {
myObjects.put(myObject.getKey(), myObject);
}
public void put(OtherObject otherObject) {
otherObjects.put(otherObject.getKey(), otherObject);
}
}
interface ICacheable {
public String getKey();
public void put(Example ex);
}
class MyObject implements ICacheable {
public String getKey() {
return "MyObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
class OtherObject implements ICacheable {
public String getKey() {
return "OtherObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
The idea here is that - instead of casting or using instanceof - you call the iCacheable object's .put(...) method which passes itself back to the Example object's overloaded methods. Which method is called depends on the type of that object.
See also the Visitor pattern. My code example smells because the ICacheable.put(...) method is incohesive - but using the interfaces defined in the Visitor pattern can clean up that smell.
Why can't I just call this.put(iCacheable) from the Example class?
In Java, overriding is always bound at runtime, but overloading is a little more complicated: dynamic dispatching means that the implementation of a method will be chosen at runtime, but the method's signature is nonetheless determined at compile time. (Check out the Java Language Specification, Chapter 8.4.9 for more info, and also check out the puzzler "Making a Hash of It" on page 137 of the book Java Puzzlers.)
Is there no way to combine the cached objects in each map into one map? Their keys could keep them separated so you could store them in one map. If you can't do that then you could have a
Map<Class,Map<Key,ICacheable>>
then do this:
Map<Class,Map<Key,ICacheable>> cache = ...;
public void cache( ICacheable cacheable ) {
if( cache.containsKey( cacheable.getClass() ) {
cache.put( cacheable.getClass(), new Map<Key,ICacheable>() );
}
cache.get(cacheable.getClass()).put( cacheable.getKey(), cacheable );
}
You can do the following:
Add a method to your ICachableInterface interface that will handle placing the object into one of two Maps, given as arguments to the method.
Implement this method in each of your two implementing classes, having each class decide which Map to put itself in.
Remove the instanceof checks in your for loop, and replace the put method with a call to the new method defined in step 1.
This is not a good design, however, because if you ever have another class that implements this interface, and a third map, then you'll need to pass another Map to your new method.