I encountered a problem while dealing with a call of a static method in another class.
So I have a function which is like follow, where I need to extract two values, a counter and an object :
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, DBObject result) {
int mergeCount = 1;
if (!cursorMap.isEmpty()) {
long ealiest = Long.MAX_VALUE;
for (DBObject o : cursorMap.keySet()) {
// do stuff to init tmp
...
if (tmp < ealiest) {
result = o;
ealiest = tmp;
}
// other stuff .....
}
return mergeCount;
}
here is how I call it in my other class :
DBObject result= null;
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result);
I checked in debug mod and result is set in getEarliestValue but when it's go out of the function call result is still null.
I thought that references where like pointers with the difference that we couldn't do arithmetic operation on the reference itself, but with this behavior it seems that even if we change the pointed value it still only in the local scope.
The only idea that I found was to put it in a List but this is neither elegant nor optimal.
Any suggestion ? Thanks in advance.
Passing result here is the same thing as passing null. You have to return this DBObject someway. For example, you can return something like Map.Entry<Integer, DBObject>. This could not be supposed to be a good solution, maybe you should create some class like BlahBlahResult, containing both int result and DBObject.
If you really-really want to pass it as a parameter, you may pass something like AtomicReference<DBObject> and set it inside the method:
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, AtomicReference<DBObject> result) {
int mergeCount = 1;
if (!cursorMap.isEmpty()) {
long ealiest = Long.MAX_VALUE;
for (DBObject o : cursorMap.keySet()) {
// do stuff to init tmp
...
if (tmp < ealiest) {
result.set(o);
ealiest = tmp;
}
// other stuff .....
}
return mergeCount;
}
...
...
AtomicReference<DBObject> resultReference = new AtomicReference<>(null);
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, resultReference);
DBObject result = resultReference.get();
In java "References to Objects are passed by value".
DBObject result= null;
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result); // here result --> null i.e, points to nothing
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, DBObject result) {
int mergeCount = 1;
if (!cursorMap.isEmpty()) {
long ealiest = Long.MAX_VALUE;
for (DBObject o : cursorMap.keySet()) {
// do stuff to init tmp
...
if (tmp < ealiest) {
result = o; // here (new)result --> o . (original)result-->null
ealiest = tmp;
}
// other stuff .....
}
return mergeCount;
}
the result parameter is a pointer. Java does not support pointer-to-pointer as in c/c++.
you can use a class contains a DBObject field, then pass this class to the method.
class Dummy {
DBObject result;
}
modify your getEarliestValue method, replace the argument DBObject result with Dummy dummy,
public static int getEarliestValue(Map<DBObject, DBCursor> cursorMap, Dummy dummy)
and then replace code result = o with dummy.result = o
Dummy dummy = new Dummy();
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, dummy);
DBObject result = dummy.result;
this is a simulation of **ptr in c/c++
You can do the following:
DBObject result= new DBOBject() // or any initializing code;
/** don't try to change or re-initialize reference inside the method
because the result will still point to old one
*/
int mergeCount = MongoTickReaderUtil.getEarliestValue(cursorList, result);
// use the result reference.
This is not specific for java also in the C++ or C pointer unless you use the & with pointer reference.
Note that it seems that the method cann't run alone with out DBObject instance so I think this method should be an instance method of Class DBObject and not a Util method,
For example:
int mergeCount = result.getEarliestValue(cursorList);
Related
In JavaScript, it's possible to do something along these lines:
var qwerty = (function() {
//some code
return returnValue;
}
This would assign returnValue to qwerty. Is there any way to do something similar in Java? Something like:
int num = {
public int method() {
//some code
return val;
}
}
I understand that I could write out a separate method, but I'd like to do it in a way similar to above as it looks neater and cleaner in the code I'm writing.
Because your function doesn't specify any parameters, you're most-likely looking for the IntSupplier functional interface:
IntSupplier supplier = () -> {
int val = ...;
//some code
return val;
};
int num = supplier.getAsInt();
If you really want to inline it, then you can use the following (which is unreadable, so I wouldn't recommend it):
int num = ((IntSupplier) () -> {
int val = ...;
//some code
return val;
}).getAsInt();
Because the above IntSupplier isn't stored in a variable, it's logically equivalent to the following:
int val = ...;
//some code
int num = val;
I have a script provided from the client like this
segment-id Integer
segment-description String
Now I want to build a class with the following methods
Sample sample = new Sample();
// casting to the type specified in the script
(map.get("segment-id")) segmentId = sample.get("segment-id");
// Now it can be used as an Integer
Integer result = segmentId + 2;
Is it possible to do something like
Class<map.get("segment-id")> segmentId = new Class<map.get("segment-id")>();
Or any better solution...? I need a way create objects of specific type, which I don't know in advance.
My current solution is
public Integer getInteger(String key) {
return map.get(key);
}
but in this way I have to know in advanced segment-id is of type Integer.
You can use Class.forName() to get the class and .newInstance() to get a new instance:
Object createdObject = Class.forName("java.lang.String").newInstance();
or ...
Object createdObject = Class.forName("java.lang.Integer").newInstance();
If you need to know if it's a String:
if(createdObject instanceof String) {
String castValue = (String) createdObject;
...
}
if(createdObject instanceof Integer) {
Integer castValue = (Integer) createdObject;
...
}
But you could just test the incoming string:
if("java.lang.String".equals(nameOfClassToCreate)) {
....
}
I am trying to get the constructor of a variable by using an ASTVisitor.
public boolean visit(VariableDeclarationFragment node)
{
IVariableBinding variableBinding = node.resolveBinding();
// I can't seem to get the constructor here
}
SAMPLE
Base b = new Derived(); // How do I get packageNAME.Derived?
int x = 5; // How do I get 5?
You need to look deeper into the syntax tree to find the answers. The ASTView is a great help in cases like this. This is the update site I use with Kepler: http://www.eclipse.org/jdt/ui/update-site
Your Samples could be answered like this (simplyfied):
/*
* Base b = new Derived(); // How do I get packageNAME.Derived?
*/
private String getClassNameFromConstructor(VariableDeclarationFragment fragment) {
Expression initializer = fragment.getInitializer();
if (initializer instanceof ClassInstanceCreation) {
ClassInstanceCreation instanceCreation = (ClassInstanceCreation)initializer;
if (instanceCreation.getType() instanceof SimpleType) {
SimpleType simpleType = (SimpleType)instanceCreation.getType();
return simpleType.getName().getFullyQualifiedName();
}
}
return null;
}
/*
* int x = 5; // How do I get 5?
*/
private String getInitialisationNumber(VariableDeclarationFragment fragment) {
Expression initializer = fragment.getInitializer();
if (initializer instanceof NumberLiteral) {
NumberLiteral numberLiteral = (NumberLiteral)initializer;
return numberLiteral.getToken();
}
return null;
}
Variables don't have constructors. Objects have constructors. Find the assignment, find the expression being assigned, and if that expression is a constructor you can get the class name from that.
I have a program in java that I wrote to return a table of values. Later on as the functions of this program grew I found that I would like to access a variable within the method that isn't returned but I am not sure the best way to go about it. I know that you cannot return more than one value but how would I go about accessing this variable without a major overhaul?
here is a simplified version of my code:
public class Reader {
public String[][] fluidigmReader(String cllmp) throws IOException {
//read in a file
while ((inpt = br.readLine()) != null) {
if (!inpt.equals("Calls")) {
continue;
}
break;
}
br.readLine();
inpt = br.readLine();
//set up parse parse parameters and parse
prse = inpt.split(dlmcma, -1);
while ((inpt = br.readLine()) != null) {
buffed.add(inpt);
}
int lncnt = 0;
String tbl[][] = new String[buffed.size()][rssnps.size()];
for (int s = 0; s < buffed.size(); s++) {
prse = buffed.get(s).split(dlmcma);
//turns out I want this smpls ArrayList elsewhere
smpls.add(prse[1]);
//making the table to search through
for (int m = 0; m < prse.length; m++) {
tbl[lncnt][m] = prse[m];
}
lncnt++;
}
//but I return just the tbl here
return tbl;
}
Can anyone recommend a way to use smpls in another class without returning it? Is this perhaps when you use a get/set sort of setup?
Sorry if this seems like an obvious question, I am still new to the world of modular programming
Right now you have this tbl variable. Wrap it in a class and add the list to the class.
class TableWrapper {
// default accessing for illustrative purposes -
// setters and getters are a good idea
String[][] table;
List<String> samples;
TableWrapper(String[][] table, List<String> samples) {
this.table = table;
this.samples = samples;
}
}
Then refactor your method to return the wrapper object.
public TableWrapper fluidigmReader(String cllmp) throws IOException {
// your code here
String tbl[][] = new String[buffed.size()][rssnps.size()];
TableWrapper tw = new TableWrapper(tbl,smpls);
// more of your code
return tw;
}
Then later in your code where you were going
String[][] tbl = fluidigmReader(cllmp);
You instead go
TableWrapper tw = fluidigmReader(cllmp);
String[][] tbl = tw.table;
List<String> smpls = tw.samples;
If you had used a dedicated class for the return value (such as the TableWrapper mentioned in another answer), then you could add additional fields there.
That is the good thing about classes - they can be extended. But you cannot extend String[][] in Java.
You can set a field, instead of a local variable, which you can retrieve later with a getter. You want to avoid it unless it is needed, but in this case it is.
You can use class(Inside Reader class) variable for this. But make sure that it's read/write is synchronized
I have this before the process:
protected void onPostExecute(SortedSet<RatedMessage> result) {
List<Object> list=Arrays.asList(result.toArray());
lancon.putExtra("results", list.toArray()); // as serializable
}
then in the other part I have
Object o=this.getIntent().getSerializableExtra("results");
//at this point the o holds the correct value (checked by debugger)
RatedMessage[] rm = (RatedMessage[]) o;// this line hangs out w ClassCastException
resultSet = new TreeSet<RatedMessage>(new Comp());
Collections.addAll(resultSet, rm);
Why I get the ClassCastException?
Finally I got it to work this way:
Serializable s = this.getIntent().getSerializableExtra("results");
Object[] o = (Object[]) s;
if (o != null) {
resultSet = new TreeSet<RatedMessage>(new Comp());
for (int i = 0; i < o.length; i++) {
if (o[i] instanceof RatedMessage) {
resultSet.add((RatedMessage) o[i]);
}
}
}
I'm sorry; I overlooked the use of the no-arg toArray() call.
Please note that there's overloaded toArray(T[]) method that takes an array as an argument.
By using this form, you can control the component type of the array, and it will work as expected.
protected void onPostExecute(SortedSet<RatedMessage> result) {
lancon.putExtra("results", result.toArray(new RatedMessage[result.size()]));
}