I have an object instantiated like the following in only one place in my code(AggregateFunctions).
private String selectColumns() {
String query = "SELECT ";
if (this.distinctResults) {
query = query + "DISTINCT ";
}
SelectColumn selectColumn = new SelectColumn(this);
if (!this.applyAggregation) {
for (Object object : this.columns) {
query = selectColumn.selectColumn(query, object);
}
} else {
AggregateFunctions aggregateFunctions = new AggregateFunctions(this);
query = query + aggregateFunctions.select();
}
//Remove extra ', '
query = query.substring(0, query.length() - 2) + " FROM ";
return query;
}
The constructors:
public AggregateFunctions(#NotNull SqlQueryGenerator sqlQueryGenerator) {
this.spaceEncloser = sqlQueryGenerator.getSpaceEncloser();
this.selectColumn = new SelectColumn(sqlQueryGenerator);
JSONObject formData = sqlQueryGenerator.getFormData();
this.columns = formData.getJSONArray("columns");
this.aggregateJson = formData.getJSONObject("functions").getJSONArray("aggregate");
this.aggregatesList = new ArrayList<Aggregate>();
prepareAggregates();
this.query = new StringBuilder();
}
public SelectColumn(SqlQueryGenerator sqlQueryGenerator) {
this.sqlQueryGenerator = sqlQueryGenerator;
}
But IntelliJ Code Analysis says the following about recursive calls. Basically I didn't understand the meaning. Can anyone elaborate to help me understand?
Problem synopsis
Constructor has usage(s) but they all belong to recursive calls chain that has no members reachable from entry points.
Problem resolution
Safe delete
Comment out
Add as Entry Point
This is a warning from the Unused declaration inspection. IntelliJ IDEA thinks the constructor is not reachable from any entry points. The constructor is not unused however, but the usages are themselves unreachable.
If this is not the case for your code, it may be a bug in IntelliJ IDEA.
Probably in the constructor of AggregateFunctions in the code that you call you go back to the method selectColumns() in the other class. This way a recurrsion is never going to end.
My guess is that either here
JSONObject formData = sqlQueryGenerator.getFormData();
Or somewhere in here:
this.selectColumn = new SelectColumn(sqlQueryGenerator);
You go to the previous class and to the same method that creates a new aggreggate and a loop is happening.
You call the AggregateFunction with this - which is the same object. But then in the constructor you call methods of this. Check these methods and if any of them has another creation of AggregateFunction object - there is your problem.
I had this issue and it was because the object was not used anywhere else
Related
public NoWheelsException(Car[] carArray){
String holder = "";
for (int i=0; i<carArray.length; i++) {
if (i == carArray.length - 1) {
holder = holder + carArray[i].name;
}else{
holder = holder + carArray[i].name + ", ";
}
}
String message = holder + " has/have no wheels.";
super(message);
}
Written above is the ideal scenario that I'd have for my code, with the super constructor at the end. Although, since super has to be the first statement, I cannot figure out how to develop the string out of the array inline. I can't straight up use .toString() as there's certain criteria into what the string should look like. I've managed to figure out everything regarding Exceptions except this itty bitty detail. Any help would be greatly appreciated!
Update
I got suggested to try Strin.join in order to link them together although unfortunately the object reference names differ from the name variable in the array objects...
One way is to create a private static method, since static methods exist irrespective of constructors and instantiation:
public NoWheelsException(Car[] carArray){
super(buildMessageFrom(carArray));
}
private static String buildMessageFrom(Car[] cars) {
StringBuilder message = new StringBuilder();
String separator = "";
for (Car car : cars) {
message.append(separator);
message.append(car.name);
separator = ", ";
}
return message.toString();
}
(When building a String in a loop, StringBuilder is much more efficient than string concatenation. Each iteration of ‘holder = holder + …’ would create a new String object that eventually needs to be garbage collected.)
If you’re comfortable with Streams, you can do it all on one line:
public NoWheelsException(Car[] carArray){
super(Arrays.stream(carArray).map(c -> c.name).collect(Collectors.joining(", ")));
}
I am taking in an array of methods and I want to chain them together to modify an object that I am working in.
For example I start with
"getStuff().get(1).get(3).setMoreStuff().put(stuff,6)"
I split it into an array called methods, and clean up the parameters inside each method and I try to modify this.
Object res = this;
String[] methods = targetString.split("\\.(?=\\D)");
for (String m : methods){
List<Object> params = new ArrayList<Object>();
List<Object> params = new ArrayList<Object>();
for (String p : m.split("\\(|,|\\)")) {
try {
if (p.indexOf(".") != -1){
double tempD = Double.parseDouble(p);
params.add(tempD);
} else {
int tempP = Integer.parseInt(p);
params.add(tempP);
}
} catch (Exception ex) { //not a number
params.add(p);
}
}
switch (params.size()) {
case 1:
res = res.getClass().getMethod(
params.get(0)
).invoke(res);
break;
case 2:
res = res.getClass().getMethod(
params.get(0),
params.get(1).getClass()
).invoke(res, params.get(1));
break;
case 3:
res = res.getClass().getMethod(
params.get(0),
params.get(1).getClass(),
params.get(2).getClass()
).invoke(res, params.get(1), params.get(2));
break;
}
in the end I notice that res has been modified the way that I expect. All the getters and setters are called correctly. But of course the underlying object "this" refers to has not been changed!
I guess I'm just calling the getters and setters of the copy I made in the first line!
now I can't just use
this.getClass().getMethod(...).invoke(...)
because I need to call the same getMethod on the object returned by this call.
To clarify:
Object res = this;
creates a "pointer" to this. So that when I call
res.getStuff().setStuff(foo)
this will also be modified.
but it seem that when I call
res = res.getStuff();
res = res.setStuff();
like I do in my loop,
this does not modify the underlying object this refers to?
Edit: Included more code as per request.
Edit2: added anther example, to clarify my problem.
Edit3: tried to add more code, its a bit hard to add a working program without including every class
Your general approach should be fine (although your approach to parameter conversion is somewhat ugly) - it's the specifics that are presumably causing you problems. Here's a short but complete program demonstrating calling methods and then seeing the difference afterwards:
import java.lang.reflect.*;
class Person {
private String name = "default";
public String getName() {
return name;
}
// Obviously this would normally take a parameter
public void setName() {
name = "name has been set";
}
}
class Test {
private Person person = new Person();
public Person getPerson() {
return person;
}
// Note that we're only declaring throws Exception for convenience
// here - diagnostic code only, *not* production code!
public void callMethods(String... methodNames) throws Exception {
Object res = this;
for (String methodName : methodNames) {
Method method = res.getClass().getMethod(methodName);
res = method.invoke(res);
}
}
public static void main(String[] args) throws Exception {
Test test = new Test();
test.callMethods("getPerson", "setName");
System.out.println(test.getPerson().getName());
}
}
The output is "name has been set" just as I'd expect. So see if you can simplify your code bit by bit, removing extra dependencies etc until you've got something similarly short but complete, but which doesn't work. I suspect you'll actually find the problem as you go.
Object does not change reference, its VALUE changes. So if you will call this.get("some key"), you will get value that the same value that you put using reflection.
Right?
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 am trying to create multiple threads using variable like threadname1, threadname2,..threadnamen. Instead of giving it as a hard coded value I am trying to do it using a for loop for the n numbers and use that at the end of "threadname" string. It throws some error. How do I fix this issue?
public class RunnableExample{
public static void main(String[] args){
String Name = "";
String Ip = "";
for (int i=1; i<=2; i++){
if(i == 1){
Name = "irony";
Ip = "82.209.27.24";
}
else{
Name = "jocky";
Ip = "98.12.098.56";
}
String runname = "threadname" + i;
RunnableThread runname = new RunnableThread(Name,Ip);
new Thread(runname).start();
}
//RunnableThread threadname1 = new RunnableThread("irony","82.209.27.24");
//RunnableThread thread4 = new RunnableThread("jocky","98.12.098.56");
//new Thread(threadname1).start();
//new Thread(threadname2).start();
try{
}
catch (InterruptedException e) {
}
}
Output:
bash-3.00# javac RunnableExample.java
RunnableExample.java:43: runname is already defined in main(java.lang.String[])
RunnableThread runname = new RunnableThread(Name,Ip);
How do I resolve this issue? Maybe some typecasting is required it seems. I am not sure.
This is your problem:
String runname = "threadname" + i;
RunnableThread runname = new RunnableThread(Name,Ip);
You're trying to declare two variables with the same name. You can't do that. Change the name of one of the variables. The names of variables are fixed at compile-time in Java. You can't say "declare a variable with the name of the execution-time value of this variable" which is what I think you're trying to do.
If you want a way of accessing multiple values, use a collection or an array. For example, you might want a List<RunnableThread> here - add the value to the list in each iteration of your loop.
I'd also strongly recommend that you make sure you understand the basics of Java (things like variables and collections) before you start try experiment with threading. Threading is complicated and can be very hard to reason about - it's going to be even harder if you're struggling with the core language.
Probably a typo, you wanted to type :
String Name = "threadname" + i;
RunnableThread runname = new RunnableThread(Name,Ip);
You have to change the name of your variable containing the thread name :
String threadName = "threadname" + i;
RunnableThread runname = new RunnableThread(threadName, ip);
A good thing to do if you work with Java is to use the Java naming convention. For example all variable start with a lower case.
You might have wanted to do this :
import java.util.HashMap;
import java.util.Map;
public class RunnableExample {
public static void main(String[] args) {
Map<String, RunnableThread> threadMap = new HashMap<String, RunnableThread>();
String name = "";
String ip = "";
for (int i = 1; i <= 2; i++) {
if (i == 1) {
name = "irony";
ip = "82.209.27.24";
} else {
name = "jocky";
ip = "98.12.098.56";
}
String threadName = "threadname" + i;
RunnableThread thread = new RunnableThread(name, ip);
new Thread(thread).start();
threadMap.put(threadName, thread);
}
threadMap.get("threadname1").getIp();
}
}
Resources :
Oracle.com - Naming Conventions
I won't bother pointing out the problem of your posted code because others already have. I will however suggest you do not use a for loop if you are going to be doing if checks inside it to see which iteration you are on. This is not a good practice. Infact, a non iterative solution is actually less lines of code and cleaner...
Thread ironyThread = new RunnableThread("irony", "82.209.27.24");
Thread jockyThread = new RunnableThread("jocky", "98.12.098.56");
ironyThread.start();
jockyThread.start();
Something like that will do what you are trying. I know you said that you want it to handle N threads. My solution would still be cleaner that the pattern you are following; adding an if check around each iteration for different threadName values.
Please suggest in refactoring this code.
Avoid code duplication, mutiple If's
public FormDataDTO getDataForFieldFormCHrzntalField(Field field) {
FormDataDTO formDataDTO = new FormDataDTO();
CHrzntalField cHrzntalField = (CHrzntalField) field;
for (int j = 0; j < cHrzntalField.getFieldCount(); j++) {
Field sField = cHrzntalField.getField(j);
if (sField instanceof LabelField) {
LabelField labelField = sField;
String fieldName = labelField.getText();
System.out.println("The Label field name is " + fieldName);
formDataDTO.setFieldName(fieldName);
} else if (sField instanceof CTextFieldBorder) {
CTextFieldBorder cTextFieldBorder = (CTextFieldBorder) sField;
Field ssField = cTextFieldBorder.getField(0);
if (ssField instanceof TextField) {
TextField textField = ssField;
System.out.println("Inside TextField---- "
+ textField.getText());
formDataDTO.setFieldType("TextField");
formDataDTO.setSelectedValue(textField.getText());
} else if (ssField instanceof DateField) {
DateField dateField = ssField;
String dateString = dateField.toString();
System.out.println("dateString " + dateString);
formDataDTO.setFieldType("Date");
formDataDTO.setSelectedValue(dateString);
}
} else if (sField instanceof CChoiceField) {
CChoiceField cChoiceField = (CChoiceField) sField;
int i = cChoiceField.getSelectedIndex();
String selectedValue = cChoiceField.getChoice(i);
System.out.println("Choice " + selectedValue);
formDataDTO.setFieldType("Combo");
formDataDTO.setSelectedValue(selectedValue);
} else if (sField instanceof CheckboxField) {
CheckboxField checkboxField = (CheckboxField) sField;
boolean checkStatus = checkboxField.getChecked();
System.out.println("Check box field " + checkStatus);
formDataDTO.setFieldType("Checkbox");
String status = new Boolean(checkStatus).toString();
formDataDTO.setSelectedValue(status);
}
}
return formDataDTO;
}
First step is to create a unit test verifying the behavior of this method. Secondly, "Tell, don't ask" is a principle of good OO design, so it would be good if you could refactor the Field type and its subclasses, to implement a method that allows them to set the necessary information on the FormDataDTO.
You could start by pulling each case block (the code inside the if / else if blocks) into their own methods. There isn't a lot of repetition that I can see, it's just trying to do too much in one method.
You could apply a strategy pattern from the looks of it;
create an interface with methods you call on all Fields, say FieldHandler
initialise a map from ClassName to FieldHandler containing implementations per field type you need to cover (like LabelFieldHandler, DateFieldHandler, etc.)
in your function doXXX instead of using instanceOf to execute variantions per field type, look up the corresponding handler in your map and delegate the call to the handler.
pseudo code:
field = getField(j);
handler = handlerMap.get(field.className);
if (null == handler) {
// error unknown field type
} else {
handler.setFormData(field, formDataDTO);
}
Add a new abstract method in Field
public class Field {
public abstract void updateFormData(FormDataDTO formDataDTO);
}
and then, implements it in each subclass of Field.
Finally, your code becomes:
public FormDataDTO getDataForFieldFormCHrzntalField(Field field) {
FormDataDTO formDataDTO = new FormDataDTO();
CHrzntalField cHrzntalField = (CHrzntalField) field;
for (int j = 0; j < cHrzntalField.getFieldCount(); j++) {
Field sField = cHrzntalField.getField(j);
sField.updateFormData(formDataDTO);
}
return formDataDTO;
}
You need to dispatch on field type. There are various ways of doing this:
Use if statements that explicitly test the class.
Make all fields implement an interface, implement that interface appropriately for each field type, and then call the interface.
Use a map to look-up the appropriate action for the class.
Option 1 is what you are doing now; 2 is what Stroboskop mentions; 3 is called the strategy pattern by rsp. 1 is a bit of a mess, as you can see. 2 couples the work of the method above with the fields, while 3 doesn't. Which of these (2 or 3) to chose depends on your particular case. An advantage of (2) is that you don't forget to write the code for each new field (because you'll get a compiler error if you do forget). An advantage of (3) is that if you want to do this kind of thing many times, the fields can get cluttered. Also, (2) requires that you have access to the fields code.
It's worth noting that if you were using Scala rather than Java some of the problems with (2) are avoided with traits (and that it also has nicer syntax for (1) with pattern matching).
personally I would prefer (2) if possible - perhaps implementing it with delegation. The only real advantage of (3) over (1) is that the code is neater - and there's a little extra type safety.
You should use method overloading to avoid instanceof calls. Each if (sField instanceof ...) should be moved to a separate method taking the desired type as parameter.