Say that i have a boolean property that should represent the fact that a specific file inside a specific path exists or not.
Here is some code:
class SomeClass {
protected static final File FILE_TO_TEST = new File("test.canc.me");
//My javafx property
public ReadOnlyBooleanPropertyBase fileExistingProperty = new ReadOnlyBooleanPropertyBase() {
#Override public boolean get() {
return FILE_TO_TEST.exists();
}
#Override public Object getBean() { return null; }
#Override public String getName() { return ""; }
};
//old style property property
public boolean isFileExisting() {
return fileExistingProperty.get();
}
Ok. The fact is that this property is read only since it cannot be set, its value depends of the "external" condition represented by the file to be existent in the application home.
Yet, i need to refresh the property, that is look again to see if the file still exsist or not, and raise change and invalidation events accordingly.
I could easily add a refresh method to the property class, but in order to call it, i would have to create an inner class and not just an anonyous one.
And i would need an anonymous class for each different type of read-only-yet-refreshable property, that is boolean, String, Integer etc.
The question is: is there a more convenient way to accomplish this?
i would have to create an inner class and not just an anonyous one.
I would go down this approach rather than try to create a bunch of anonymous inner classes.
And i would need an anonymous class for each different type of read-only-yet-refreshable property, that is boolean, String, Integer etc.
Use generics - that's what they're designed for! Create a ReadOnlyRefreshableProperty<T>, then the return types and parameters of the relevant methods all use T as their type, removing the need for a separate class for each type.
Related
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'am trying to make a OGM to translate object to Vertex for the OrientDB. Currently i'am using GCLib but i read that ByteBuddy could implements two critical things that if work, it will improve the OGM speed.
Could ByteBuddy implement field access control? I read the doc but it's not clear or I do not understand it.
Dinamically add default empty constructor.
The current problem is this: We do not know the class definition that will be passed as a parameter. The idea is to redefine the class and implement the empty constructor if it not have one, add a field named __BB__Dirty to set the object as dirty if an assign operation was detected and force the implementation of an interface to talk with the object.
Example:
A generic class:
public class Example {
int i = 0;
String stringField;
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
}
Now we have an interface like this:
public interface DirtyCheck {
public boolean isDirty();
}
So, I want to force the Example class to implement the interface, the method isDirty(), a field to work on and a default contructor so the class should be translated to:
public class Example implements DirtyCheck {
int i = 0;
String stringField;
boolean __BB__dirty = false;
public Example() {
}
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
public boolean isDirty() {
return this.__BB__dirty;
}
}
and the some magically assigner so if any field (except __BB__dirty) is modified, the __BB__dirty field is set to True;
I have tried the first part of this but I fail :(
...
ByteBuddyAgent.install();
Example ex = new ByteBuddy()
.redefine(Example.class)
.defineField("__BB__Dirty", boolean.class, Visibility.PUBLIC)
.make()
.load(Example.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent())
.getLoaded().newInstance();
....
ex.addToI(); // <--- this should set __BB__dirty to true since it
// assign a value to i.
But i get this error:
Exception in thread "main" java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$1.apply(ClassReloadingStrategy.java:297)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:173)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4350)
at Test.TestBB.<init>(TestBB.java:33)
at Test.TestBB.main(TestBB.java:23)
I'am stuck in the very first stage to solve the problem with BB.
Thanks
The Java virtual machine does not support changing the layout of classes that are already loaded when redefining a class. This is not a limitation of Byte Buddy but the VM implementation.
In order to do what you want, you should look at the AgentBuilder API which allows you to modify classes before they are loaded. Creating an agent does however require you to add it explicitly as an agent on startup (opposed to adding the library to the class path.
You can implement the interface by calling:
.implement(DirtyCheck.class).intercept(FieldAccessor.of("__dirty__");
You can also add a default constructor by simply defining one:
.defineConstructor(Visibility.PUBLIC).intercept(SuperMethodCall.INSTANCE)
The latter definition requires the super class to define a default constructor.
In Java: What is the best way to pass a method from one object to another so that it can be called at a later time by the second object?
I come from an ActionScript background where it is as easy to pass around references to methods as it is to pass around references to variables but this seems to be much more difficult in Java. The first few links I found flat out say it is not possible (and it may have been at the time of their posting), but then I found http://www.javacamp.org/javavscsharp/delegate.html which details how this can be accomplished.
My issue with using Javacamp's example is the string based reference to the method. Methods get renamed all the time and a string reference will only complain once you actually run that function runtime as opposed to compile time for a proper explicit link.
Is there no way to do this with proper explicit links to the method you want the other class to execute?
Model of what I am hoping to accomplish:
Player clicks an upgrade button on Activity1 > Activity1 passes upgrade method to a new confirmation activity
Player clicks "Yes" > Confirmation activity calls upgrade method passed in from Activity1
OR: Player clicks "No" > Confirmation Activity closes
EDIT:
To be clear I am not looking for a static method solution as that would require my Confirmation activity to hold many lines of logic for which static method to call. The Confirmation activity will be used all over my application: a simple "Are you sure you want to X?" -Yes -No, if yes execute X
I am currently looking at implementing onActivityResult to avoid this issue but that will be more logic than I like for this kind of issue.
you can use interfaces like this:
public interface MyMethod {
public void method();
}
public class FirtObject{
private SecondObject ob;
public void tellSecondObjectExecuteLater(){
ob.executeLater( new MyMethod() {
public void method(){System.out.println("duh Method");} });
}
}
public class SecondObject {
private MyMethod myMth;
public void executeLater(MyMethod mth){
myMth = mth;
}
public void executeNow(){
myMth.method();
}
}
does this solve your problem?
The typical way to pass methods is to use an Interface and Anonymous Inner Classes. In order to maintain static typing an Interface is used to declare the method signature and typing information. The caller can use either a concrete implementation of that interface as a normal class or using Anonymous Inner Classes for quick class creation. I'll use standard Java SDK classes to illustrate:
interface Comparator<T> {
public int compare( T a, T b);
}
class SpecialCollection<T> {
public void sort( Comparator<T> comparator ) {...}
}
public class SomeClient {
public void doSomething( SpecialCollection<SpecialObj> collection ) {
collection.sort( new Comparator<SpecialObj>() {
public int compare( SpecialObject a, SpecialObject b ) {
// some implementation
}
} );
}
}
The above is an example of a strategy pattern. The thing about the strategy pattern (and passing callback methods like in Javascript). The author has to plan for those types of extensions. The author has to predict up front where he/she wants you to extend. And it just happens it's cleanest if you use Interfaces.
However, pure delegation doesn't have to have always involve Interfaces. You can pass concrete classes, since Java can always pass a subclass that overrides various methods of that class to change what method or code will be invoked. For example in Java InputStream/OutputStream are abstract classes and you typically pass subclass instances to the methods.
If you need the method to act differently depending on the context (AKA, it is different depending on how it is created), you'll want to pass along the instance of the class that the method is in.
If it is a static method, you can just referenced the method itself if you import that class at the top of your new class.
For example, lets say you have a method that will tell you stuff about a certain string. IF the class looks like this:
class stringChecker {
private String stringToCheck;
public class stringChecker(String s) {
stringToCheck = s;
}
public int getStringLength() {
return stringToCheck.length();
}
public boolean stringStartsWith(String startsWith) {
return (stringToCheck.indexOf(startsWith) == 0);
}
}
Then you'll want to pass along the instance, since it is non-static. Different instances have different strings that they were created with, so you will get a different return if you use a different instance.
However, if your class looks more like this:
class stringChecker {
public static int getStringLength(String s) {
return s.length();
}
public static boolean stringStartsWith(String s, String startsWith) {
return (s.indexOf(startsWith) == 0);
}
}
Then you can just reference those methods with stringChecker.getStringLength("test");, because the methods are static. It doesn't matter what instance they are in. The returned result depends ONLY on what is being passed in. You just have to make sure to add import stringChecker; at the top or whatever your class will be called. For you, it'll probably be something like com.example.blah.otherthing.stringChecker, since you're working with android.
Good luck! I hope this helps :)
EDIT: Looks like I may have read the problem too quickly...if this isn't what you were asking about, just let me know with a comment and I'll delete this answer so as to not confuse anybody else.
You said that you are using it in a project to open a Confirmation activity.
Activities should not contain references to each other to avoid memory leaks. To pass data between activities should be used Intent class. To receive a result, call StartActivityForResult() and get result in the onActivityResult() method.
But in general for your task is more suitable AlertDialog or PopupWindow.
All,
Hopefully a simple question. I am thinking of the best way to implement a class which holds a number of collections and HashMaps where the class needs to know about when they have been modified outside of the class - i.e. added/removed/changed items. Each collection/hashmap needs to be exposed as a public getter in my class at the moment.
So my basic class looks like as follows...
public class MyClass {
protected final HashMap<String, String> _values = new HashMap<String, String>();
protected final ArrayList<MyOtherClass> _other = new ArrayList<MyOtherClass>();
protected final ArrayList<MyOtherClass2> _other2 = new ArrayList<MyOtherClass2>();
// ... implementation
public HashMap<String, String> getValues() {
return _values;
}
public ArrayList<MyOtherClass> getMyOtherClassList() {
return _other;
}
public ArrayList<MyOtherClass2> getMyOtherClassList2() {
return _other2;
}
public String getContent() {
// build the content based on other/other2...
StringBuilder sb = new StringBuilder();
// iterate through both collections to build content...
// ...
return sb.toString();
}
}
public getMyOtherClass {
public String name; // has getter and setter
public String value; // has getter and setter
}
public getMyOtherClass2 {
public String name; // has getter and setter
public String value; // has getter and setter
public String somethingElse; // has getter and setter
}
I want to add a key/value to the _values based on the length of the content i.e.-
_values.add("Length", getContent().length);
So the Length value is dynamic based on what gets added to the _other and _other2.
The problem with this is exposing the _values and _other with public getters is that anything outside the class can modify them. The class will not know if items have been modified.
A couple of solutions I can think of is to make the collection/hashmap readonly - but this throws a runtime exception - if this was the case I'd like the compiler to indicate that they are read-only and throw an exception but I don't know if this is possible.
The other way would be to add a add/remove for each of the collections/maps and update the Length property accordingly - but again, if the values change in the MyOtherClass, MyClass will still not know about it.
Alternatively write my own Hashmap/List/Collection to determine when items are added/removed, and possibly have a property change listener on the getMyOtherClass, getMyOtherClass2.
Any nice solutions to this?
Thanks,
Andez
Overide the map/list implementations and insert a call-back into the add/update/remove methods that triggers an update function on the parent.
Also it's bad form to create references directly to the implementations - this is better (read up on polymorphism for reasoning):
private Map<String,String> myMap = new HashMap<String,String>();
private List<String> myList = new List<String>();
In this case you can make use of some fundamentals of the Observer design pattern to have an Object "watching" the Maps and registering each change is made to them.
Create an object contains a Map and another object that contains a List, so since you have 1 map and 2 lists you'll have 3 of those "Observable" objects. Let's name the classes "ObservableMap" and "ObservableList". You can even create an abstract class "ObservableObject" and extend it with the previously mentioned classes.
These objects won't override the Map/List implementation, they'll only act as a wrapper by wrapping the methods you'll want to track to register the state and derive the call to modify the collection. For example, I'll post some code of the ObservableMap class (I'm instantiating the map with <String,String> but you can use generics here too if it suits you).
public Class ObservableMap extends ObservableObject{
private Map<String,String> map = new LinkedHashMap<String,String>();
private Watcher observer = new Watcher();
//Example of one of the wrapper methods (the other ones are like this one)
public void putObject(String key, String value) {
watcher.notifyPut(); //You can name the method the way you like and even pass
//the new key/value pair to identify what has been added.
map.put(key,value);
}
}
Here, the Watcher class is the one that registers the canges. It can either be a completely new Object (like in this case) or you can make an Interface and implement it in an existing class of yours to be able to set it as a watcher on your Observable objects.
Not 100% sure what you are asking. If you are trying to track changes to attributes to two classes you may wish, as other people have mentioned implement the observer pattern and raise notifications in the set methods. An alternative, that I have used successfully for implementing an undo mechanism is to use aspectJ or some other AOP (Aspect Orientated Programming) tool to intercept the set methods and perform the required notifications/updates that way.
Alternatively define an interface that only provides access to the getXXX operations and return those from your model, that way nothing can change the data.
There is a part in my java code where I am extending a class from a library which I haven't written.
#override
public Object getPropertyValue(Object id) {
if(id.equals(model.PROPERTY_RENAME))
model.setName((String)value);
else if(id.equals(model.PROPERTY_COLOUR))
model.setColor((Color)value);
}
Now in this case how should I modify this code to make it scalable. There would be many more properties like location, dimension, etc. Now this model is instance of an abstract class AbsModel.
So every class implementing the AbsModel would have different properties. So the class architecture should be there, so that this part of code remains unchanged, no matter how many more model classes I add.
It looks like you want to carry out some operation on the model when this method (getPropertyValue) is called. I would create a Map of id onto the interface ModelOperation defined as follows:
public interface ModelOperation {
void operate(Object value);
}
Then the map would be defines as follows:
map.put(model.PROPERTY_RENAME, new RenameOperation(model));
Your extension class would then look like this:
#Override
public Object getPropertyValue(Object id) {
map.get(id).operate(model);
// etc...
}
For example, RenameOperation would be defined like this:
public class RenameOperation implements ModelOperation {
public RenameOperation(Model model) {
// etc...
}
public void operate(Object value) {
model.setName((String)value);
}
}
This allows you to support as many model operations as you like and means you don't have to change the extension class you have to write. The above is just an outline. You could use generics on the ModelOperation implementations to avoid the cast of the value in each one.
I guess reflection is probably the answer here if you can rely on some naming to help direct you.
It's not going to be nice, but the idea would be that you'd have a method that would reflect on the type and look up the appropriate method. The code belwo
public Object setPropertyValue(Object id) {
String className = id.getClass().getSimpleName();
// Hope that the method is called set<CLASS> and takes a single parameter that is the class
Method method = model.class.getMethod("set" + className, id.getClass());
// Invoke the method (TODO deal with all of the exceptions)
method.invoke(model, id);
}
There are multiple ways of doing this -- though it depends on what do you mean by "scalable" (being able to cope with lots of requests per second or being able to cope with lots of properties?):
one way -- if you're going to go down the path you have outlined in your code is to have those properties that are used very often at the top of your if/then/else block -- so their execution path is very short. this would "scale up" well for lots of requests as not too much time is being spent in actually executing the method (in most cases at least!)
another way -- and this scales up well for lots of properties and easiness of maintaining the code but you will take a hit on execution time: have a Map that maps property names to setxxx() method names, then you can use reflection to invoke these methods on the target object (id in your case) on each call. Classes extended your class will only have to provide a getMap() method which will return the mapping name-to-setter method, which can be a static member and initialized on class load.
Store your properties in a Map -- in which case setName() is the same as map.put( PROPERTY_RENAME, value)
Since in Java functions are not first class citizens, the "nice" route would be very awkward: define an enum with one value per each constant above (i.e. for each property), and a virtual method e.g. update(Object value, then override the method in each enum to update the corresponding property. If you can, redefine the constants PROPERTY_RENAME etc. themselves as enums. This still results in code bloat.
The other way is to use reflection. If you can use the same ids as the property names you want to update, you only need to invoke the setter for the property (as illustrated in other answers). Otherwise you may need to introduce a mapping from ids to property names.
A version not using reflection, call the base class's implementation:
public Object getValue(Object id) {
Object ret = super.getValue(id);
if (ret == null) {
// Subclass specific properties
}
return ret;
}
A common way around this is to use reflection like
public Object getValue(IdType id) {
Method getter = model.getClass().getMethod("get" + id);
return getter.invoke(model); // throws Exceptions.
}
OR
public void setValue(IdType id, Object value) {
Method setter = model.getClass().getMethod("set" + id, value.getClass());
setter.invoke(model, value); // throws Exceptions.
}
I solved this issue by creating an interface. So the code is.
public interface IModel
{
public void setProperty(String propertyName);
}
Rest of the classes were
public class HelloModel implements IModel
{
public void setProperty(String propertyName)
{ code for handling the properties goes here ... }
}
So in this case every class has to handle it's own property setters.
Is this the best way to handle abstraction ? I think this model is very scalable ...