I'm writing a class which will make time consuming calculations on parametres stored in a list of MyObjects. Since I wanted to have easy access to a number of List's features, I decided to write it extending a list type (an alternative would be to have a List as one of the fields in my class and rewrite all methods I'm going to use, but it looks like an overcomplication). Since the calculations are pretty complex and time consuming, while the result depends solely on the stored parameters (no time influence, no hidden dependencies, etc), I decided to cache the result. So my code looks more or less like this:
public class Calculator extends ArrayList<MyObject> {
private double Result = Double.NaN;
public double getResult() {
if (Double.isNaN(Result)) {
Result = CalculateResult();
}
return Result;
}
}
This way, when the method getResult() is called for the first time it calculates the result, stores it, and then reuses during subsequent calls.
Now, the list's contents can be modified with various methods, and many modifications should clear the cache. To achieve this, normally I would write something like:
public void add(MyObject newvalue) {
super.add(newvalue);
Result = Double.NaN;
}
However, it does not work, because "super" refers to the generic ArrayList class, so the compiler produces a type error.
An obvious trick on my level would be to create an interim class, which would implement ArrayList of MyObject and make Calculator extend this interim class:
public class MyArrayList extends ArrayList<MyObject> {
}
public class Calculator extends MyArrayList {
}
But it looks like an overcomplication again. Isn't there a more elegant method to achieve this result? Or perhaps, is there a mechanism similar to trigger in SQL, which would force my class clear the cache whenever any modification is made to the List?
The method add should return boolean value, so all what you need to do is
public boolean add(MyObject newvalue) {
boolean retVal = super.add(newvalue);
Result = Double.NaN;
return retVal ;
}
This is a good example as to when composition over inheritance really makes sense for code design. Your class will become cluttered with unnecessary operations, when it only really needs to have an instance of a List of some kind floating around. It also means that you're not hard-dependent on the ArrayList implementation; for instance, what if your algorithms called for a LinkedList instead?
But, if you really want to fix what you have...
First and foremost, the reason you're getting the compiler error is because, as far as Java is concerned, you're trying to override the add method, but don't quite have the signature right.
The correct signature is specified as boolean add(E), but you're overriding it with a signature of void add(E). The types don't match, so you won't get a successful override, and Java will not compile the class, as you can see.
Next, creating more classes to accomplish the same thing as inheriting and properly overriding the ArrayList class will not gain you anything; if anything, it will be more of an overcomplication.
Related
How can I give a promise to the compiler that what I am doing is type safe?
I have a class "Container" that can have some info. I extend said class into what I will refer to as EContainer (E for Extended) and define that it can have some specific info, like say an int and a string. Now, I want to be able to make a list of EContainers and sort it by either int or string, and my solution was to have a ContainerList<T> class where T is what you sort by, and you pass in a lambda to act as an adapter for EContainer to extract T.
So far so good, however now say I want to delimit the list in some way into groups, so if the hypothetical EContainer has ints ranging from 0 to 100, I would want to say "group EContainers like this: 0-20, 21-50, 51-100".
My initial guess was that I would add a function I'll refer to as getDelimiter inside EContainer that would be able to return the "group" it is in, utilizing a protected predefined enum that would define delimiters, however, this is where I ran into problems - the way I would return a group is by having a shared value of T that multiple EContainers would return after running getDelimiter, and so I would group based on that, but unfortunately that would mean that getDelimiter would be a multi-type return function and I do not know how exactly I would tell the compiler that "yes, I know what I am doing, and that I will definitely get back T from getDelimiter"
I could probably get around this by adding another lambda in there that would define the function to call on the EContainer to get the delimiter function, and that should be type safe and everything, but I thought that would end up in an unnecessary boilerplate in EContainer, so maybe there is a better option I don't know of? I have to say, it is very difficult to find the keywords I could use for this problem, so I couldn't do much initial research.
Edit: Just had an idea of having getDelimiter return everything as Object and then casting to T right after, sounds like that should work and would minimize boilerplate.
How can I give a promise to the compiler that what I am doing is type safe?
Generally speaking, that is what the #SuppressWarnings("unchecked") does.
It is not clear if it will work for your use-case. (Show us your actual code ... if you want a more specific answer.)
However, there will still be a hidden runtime check to detect that you are not violating runtime type safety. There is no way you can turn off those checks.
Just had an idea of having getDelimiter return everything as Object and then casting to T right after, sounds like that should work and would minimize boilerplate.
Hmm ... you can't cast something statically typed as Object to T. The fundamental problem is that the actual type of T is erased, so the runtime doesn't know what type to cast to.
One possible workaround is to represent the actual type of T as a Class object, and use reflection to do the type check / cast. Indeed, this is the general workaround when you need to do type checks in spite of type erasure. Unfortunately this is cumbersome, because at some point you need to pass an extra explicit Class object as a parameter to make it work.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
public class StackOverflowNonsense {
public static abstract class Container{
public String sharedFunc(){return "this is a shared function";}
}
public static class EContainer{
public int _int; //id=0
public float _float; //id=!0
public EContainer(int _int,float _float){
this._int=_int;
this._float=_float;
}
protected enum Delimiters{
INT(new ArrayList<Object>(Arrays.asList(0,21,51))),
FLOAT(new ArrayList<Object>(Arrays.asList((float)0,(float)0.5,(float)1)));
final ArrayList<Object> delim;
Delimiters(ArrayList<Object> delim){
this.delim=delim;
}
}
public Object getDelimiter(int id){
if (id==0){
int pos=Collections.binarySearch(Delimiters.INT.delim, (Object)_int,Comparator.comparingInt(key->(int)key));
return (Object)Delimiters.INT.delim.get(pos<0?-2-pos:pos);
}else{
int pos=Collections.binarySearch(Delimiters.FLOAT.delim, (Object)_float,Comparator.comparingDouble(key->(Float)key));
return (Object)Delimiters.FLOAT.delim.get(pos<0?-2-pos:pos);
}
}
#Override
public String toString(){
return String.format("EContainer with (%d, %f)", _int,_float);
}
}
public static void main(String[] args){
ArrayList<EContainer> ContainerList=new ArrayList<>(
Arrays.asList(new EContainer(0,(float)2.0),new EContainer(69,(float)0.69))
);
Collections.sort(ContainerList,Comparator.comparingInt(key->(int)key.getDelimiter(0)));
System.out.println(ContainerList);
Collections.sort(ContainerList,Comparator.comparingDouble(key->(Float)key.getDelimiter(1)));
System.out.println(ContainerList);
}
}
This appears to provide the functionality I want, however I'm not sure if this code breaks some holy scripts, so maybe there is a better solution?
I am trying to implement a Map<String, Interface> where the interface in question takes in and returns a generic value, so that different functions in the map could have different return types but still using the same interface. I'm not quite sure how it would work but the goal would be to achieve something along these lines below.
// A generic interface of some kind
public interface Action {
Object doAction(Object object);
}
// The class which implements the map
public class MyClass {
public void example() {
HashMap<String, Action> map = new HashMap<>();
// this takes in a boolean and returns the opposing value
map.put("functionOne", (boolean bool) -> !bool);
// this takes in an integer, increments it and returns it.
map.put("functionTwo", (int integer) -> integer++);
...
}
}
Obviously this pseudo code isn't right and I might be way off track but I hope it gives you an understanding of what I'm trying to achieve. Any help would be appreciated.
First of all, your interface should be declared as FunctionalInterface.
Second, since your doAction method takes Object as an argument, I see no point in returning it, unless you want to preserve the original object. You can just modify the object inside the method and make your method void. After invoking the method, your object, which was passed, will be modified. (you want to use objects like Int, Boolean and etc., which wrap up the primitive types)
But overall, this approach seems a little bit old styled and unreliable one. Since this will lead you to creating if statements to ensure you are operating the right type (As some of the colleagues have written in comments).
What I would do is to make Action generic.
#FunctionalInterface
public interface Action<T> {
T doAction(T argument);
}
Then just declare your functions like below and use them without creating a collection for them, because it will result in writing more code to ensure type-safety.
Action<Boolean> booleanFunc = (Boolean bool) -> {...};
Ok, this might be a stupid question. However, it really confuses me;
What is the difference between a method like :
toString()
and a method like
toString(String s) ?
I know the last one doesn't exist but let's say i made one like this.
Why should I choose to make a method that can be invoked like this: object.method(); and not: method(object j ); i hope i could explain myself.
It all depends on what you want the method to do.
For instance, the .toString(), is used to provide a string representation of the object. In this case, all the data which the method requires to operate as expected is stored within the object itself, thus, no external input is required.
Taking a different example, printToStream(Stream stream) (where Stream would be some interface used by all the streams, be it file streams, console streams, network streams, etc). In this case, the method needs to know to which stream it must write to.
The class to which the printToStream method belongs could have a property which denotes to which stream it must print, and thus allowing us to change the signature of printToStream to printToStream(), but that would require 2 lines of code to set up, and in this case, this can potentially introduce problems, especially if you need to print to different streams and at some point, you forget to set the property. Thus, in this case, having the method take in the extra parameter results in cleaner code which is less error prone.
EDIT: The parseInt method is a static method which is provided by the Integer class which is used to transform items from one type to integer. Static methods are methods which need to be self contained, so if you want to transform one object from one form to another using a static method, passing it as a parameter is the way to go.
The suggestion you are making would take the look of something like so: int a = "123".ToInteger();. I guess that that would be one way to go around doing the same thing, but in the end the Java specification was not designed with that frame of mind.
EDIT 2: I'll try and expand my answer the one provided by # user3284549. Please note that my answer is in no means final and should be supplimented by other material you can find online. In Java, methods are either:
Static. Static methods are methods which have no state (more on that later) and are self contained. As seen earlier, the .parseInt method from the Integer class is one example of such method. Another examples are provided by the Math class.
Non Static. Non static methods are methods which are made available once that an object is initialized (or instantiated). These methods are methods which act upon the state of the object, or else, expose some functionality which the object provides which might, in turn, affect how it behaves.
Taking your dice example, again, you can achieve this in two ways:
Let us assume that we have a class called Dice:
public class Dice {
private int value;
public int getValue() {
return this.value;
}
public void setValue(int value) {
this.value = value;
}
}
Static method
public static void roll(Dice d) {
//Rolling the dice entails a potential change in it's current value. Thus, you would need to access the dice itself and update the value.
Random r = ...
d.setValue(randomNumber);
}
Non Static Method
We just enhance the Dice class to have a new method which mimics a dice roll as follows:
public void roll() {
Random r = ...;
this.value = randomNumber;
}
If you notice, even in the static method, we still made use of a method which takes in a parameter. The particular setXXX methods (and their counter parts getXXX methods provide us with encapsulation). This is because we need to change the state of the Dice object.
Lets proceed with you example -
object.method();
object.method(Object j);
The first one does some operations on it's variable and returns/set some value (although there may be a lot of other cases, but for simplicity just consider these). When the method is toString() it actually represents a string representation of some important properties of the Object. In this case the toString() method don't need to be feed some argument from the outside of the object.
And when you use object.method(Object j) it means you need to provide some arguments to complete it's task.
For the second part of your question. Think about encapsulation. If the method needs access to data that is private to the object then object.method() would be the correct way. And also it is probably not going to be helpful in processing objects of any other type.
For the second type, it could be a static method or utility method commonly used on many different objects. The method implementation logic doesn't have to be tightly related to the object's internal implementation.
I'm currently brushing up my Java and reading up on Generics. Since they were not treated extensively in my Java class, I'm still having some trouble wrapping my mind about it, so please keep that in mind when answering.
First of all, I'm pretty sure that what I'm trying to is not possible. However, I'd like to find out where my thinking is wrong and how I should go about achieving what I want.
What I'm trying to do is manipulating an object that implements a generic interface from another class that has no knowledge about the instantiated type. Thus, I have something like the following classes:
public interface CalledInterface<E> {
public E get() { ... }
public set(E e) { ... }
}
public class Called implements CalledInterface<String> {
...
}
Now what I want to do is:
public class Caller {
protected CalledInterface<?> c;
public Caller (CalledInterface<?> arg) {
c = arg;
}
public void run(){
// I can do this:
c.set(c.get());
// But I'd want to be able to do something like:
<?> element = c.get();
c.set(element);
}
}
What is the fundamental flaw in my thinking, if there is one? And what approach should I rather be taking?
First of all, keep in mind that generics is a compile time thing not a runtime.
Now in your Caller you defined Called c. Called is defined to implement CalledInterface<String>, so automatically, Called has the following methods generated at compile time:
String get();
void set(String e); //i assume you wanted to return void
So essentially this doesn't really make sense:
<?> element = c.get();
The Caller class isn't even aware Called is using generics internally, for it, Called just deals with strings.
UPDATE
Based on your comment, since you don't want Caller to use Called directly but use CalledInterface first thing you have to do is change the type of c to that. In this case you should not use generics, because the whole point of generics is that the same class is used in different scenarios with different types (again determined at compile time), enforcing types without having repeated code.
If I understand correctly you don't want to restrict Caller to use String, so what you have to do is change CalledInterface to not use generics, and change the methods to:
Object get();
void set(Object o);
This is how we used to do things before Generics in Java 1.4. You obviously run the risk of not having type safety, so think through whether what you want really makes design sense, because it probably does not because you have to do instanceof anyway to check the type to use the Object in a useful way (i.e. to access its methods).
If on the other hand you just change the c member (and the constructor argument of Caller) to:
CalledInterface<String> c;
Your Caller will be interacting with the CalledInterface rather than the implementation and at the same time still be type safe. So you can still pass an instance of Called and set it to c.
After your edit:
// I can do this:
c.set(c.get());
No you can't. It won't compile with c being CalledInterface<?>. (Have you even tried it?)
To do this, you can use a "capture helper":
private static <T> void helper(CalledInterface<T> c) {
c.set(c.get());
}
public void run(){
helper(c);
}
Which also solves your second problem:
private static <T> void helper(CalledInterface<T> c) {
T element = c.get();
c.set(element);
}
public void run(){
helper(c);
}
There are a few minor mistakes in your code:
protected Called c;
public Caller (CalledInterface arg) {
c = arg;
}
You are not allowed to assign arg here, because the type CalledInterface is not a subtype of Called (it is the other way around)
Also you should give type information when using CalledInterface (it is allowed to leave it out, but only for legacy purposes).
Now to the part you are wondering about. For the type Called, the compiler knows get() returns a String, if you are not interested in that, you can of course always use Object as the type of element. The compiler also knows that set() takes a String as argument, so it requires you to give one. In generics is essentially the same as using Object in a case without generics (even though it isn't allowed on the location you use it, because it doesn't make sense). This means that you would be telling the compiler to forget the type on the first line (calling get()) and to unforget it on the line below.
A little background first. I am looking into the possibility of implementing Ruby's ActiveRecord in Java as cleanly and succinctly as possible. To do this I would need to allow for the following type of method call:
Person person = Person.find("name", "Mike");
Which would resolve to something like:
ActiveRecord.find(Person.class, "name", "Mike");
The plan is to have Person extend ActiveRecord, which would have a static find method with two parameters (column, value). This method would need to know it was called via Person.find and not another domain class like Car.find and call the find(Class, String, Object) method to perform the actual operation.
The problem I am running into is the finding out via which child class of ActiveRecord the static find method (two param) was called. The following is a simple test case:
public class A {
public static void testMethod() {
// need to know whether A.testMethod(), B.testMethod(), or C.testMethod() was called
}
}
public class B extends A { }
public class C extends A { }
public class Runner {
public static void main(String[] args) {
A.testMethod();
B.testMethod();
C.testMethod();
}
}
Solutions found so far are load-time or compile time weaving using aspectJ. This would involve placing a call interceptor on the testMethod() in A and finding out what signature was used to call it. I am all for load time weaving but the set up of setting this up (via VM args) is a bit complex.
Is there a simpler solution?
Is this at all possible in java or would need to be done in something like groovy/ruby/python?
Would the approach of using something like ActiveRecord.find for static loads and Person.save for instances be better overall?
You cannot override static methods in Java, so any calls to the static method via a subclass will be bound to the base class at compile time. Thus a call to B.testMethod() will be bound to A.testMethod before the application is ever run.
Since you are looking for the information at runtime, it will not be available through normal Java operations.
As others have noted, I don't think the problem is solvable in Java as you pose it. A static method is not really inherited in the same way that a non-static method is. (Excuse me if I'm not using the terminology quite right.)
Nevertheless, it seems to me there are many ways you could accomplish the desired result if you're willing to modify your interface a little.
The most obvious would be to just make the call using the parent class. What's wrong with writing
Person person=(Person)ActiveRecord.find(Person.class, "name", "Mike");
?
Alternatively, you could create an instance of the record type first and then do a find to fill it in. Like
Person person=new Person();
person.find("name", "Mike");
At that point you have a Person object and if you need to know it's class from within a function in the supertype, you just do "this.getClass()".
Alternatively, you could create a dummy Person object to make the calls against, just to let you do the getClass() when necessary. Then your find would look something like:
Person dummyPerson=new Person();
Person realPerson=dummyPerson.find("name", "Mike");
By the way, seems to me that any attempt to have a generic ActiveRecord class is going to mean that the return type of find must be ActiveRecord and not the particular record type, so you'll probably have to cast it to the correct type upon return from the call. The only way to beat that is to have an explicit override of the find in each record object.
I've had plenty of times that I've written some generic record-processing code, but I always avoid creating Java objects for each record type, because that invariably turns into writing a whole bunch of code. I prefer to just keep the Record object completely generic and have field names, indexes, whatever all be internal data and names. If I want to retrieve the "foo" field from the "bar" record, my interface will look something like this:
Record bar=Record.get(key);
String foo=bar.get("foo");
Rather than:
BarRecord bar=BarRecord.get(key);
String foo=bar.getFoo();
Not as pretty and it limits compile-time error-checking, but it's way less code to implement.
You would not do this in Java. You would probably do something more like:
public interface Finder<T, RT, CT>
{
T find(RT colName, CT value);
}
public class PersonFinder
implements Finder<Person, String, String>
{
public Person find(String nameCol, String name)
{
// code to find a person
}
}
public class CarFinder
implements Finder<Car, String, int>
{
public Person find(String yearCol, int year)
{
// code to find a car
}
}
It is possible but it is expensive.
If you can find a way to only call it once then you're set.
You can create a new exception and look at the first frame and then you'll know who call it. Again the problem is it is not performant.
For instance with this answer it is possible to create a logger like this:
class MyClass {
private static final SomeLogger logger = SomeLogger.getLogger();
....
}
And have that logger create a different instance depending on who called it.
So, in the same fashion, you could have something like:
class A {
public static void myStatic() {
// find out who call it
String calledFrom = new RuntimeException()
.getStackTrace()[1].getClassName();
}
}
This is fine for a one time initialization. But not for 1,000 calls. Although I don't know if a good VM may inline this for you.
I would go for AspectJ path.
My theory on this, having built something similar, is to use a code generation strategy to create a delegate for each class which contains the method. You can't have quite as much hidden code in Java, it's probably not worth the effort as long as you generate something reasonable. If you really want to hide it, you could do something like...
public class Person extends PersonActiveRecord
{
}
//generated class, do not touch
public class PersonActiveRecord extends ActiveRecord
{
public Person find(Map params)
{
ActiveRecord.find(Person.class, params);
}
}
But it tends to mess up your inheritance hierarchy too much. I say just generate the classes and be done with it. Not worth it to hide the find method.
You can do it very manually by creating a hackish constructor.
A example = new B(B.class);
And have the superclass constructor store the class that's passed to it.
I don't think the thrown exception above would work, but if you'd want to ever do something like that without creating an exception...
Thread.currentThread().getStackTrace()
You may be able to do it much more smoothly with meta-programming and javassist.
I suppose you want to implement ActiveRecord in Java. When I decided to do the same, I hit the same problem. This is a hard one for Java, but I was able to overcome it.
I recently released entire framework called ActiveJDBC here:
http://code.google.com/p/activejdbc/
If interested, you can look at sources to see how this was implemented. Look at the Model.getClassName() method.
This is how I solved getting a class name from a static method. The second problem was to actually move all the static methods from a super class to subclasses (this is a cludgy form of inheritance after all!). I used Javassist for this. The two solutions allowed me to implement ActiveRecord in Java completely.
The byte code manipulation originally was done dynamically when classes loaded, but I ran into some class loading problems in Glassfish and Weblogic, and decided to implement static bytecode manipulation. This is done by a http: activejdbc.googlecode.com/svn/trunk/activejdbc-instrumentation/ Maven plugin.
I hope this provides an exhaustive answer to your question.
Enjoy,
Igor