I'm trying to implement an AbstractTableModel for a collection named "clients" but I keep receiving the error "required variable found value" for the "add" method.
Here is my code:
I'm sorry for the confusion created. The add method is meant to add a new client in the table (by that I mean a new row). I don't want to add a new client to the collection.
class ModelTabel extends AbstractTableModel{
public int getRowCount() {
return clients.size();
}
public int getColumnCount() {
return 4;
}
public Object getValueAt(int row, int column) {
Client c = clients.get(row-1);
switch(column){
case 0: return c.getName();
case 1: return c.getSurname();
case 2: return c.getID();
case 3: return c.getPhone();
default:return "ERROR";
}
}
public void add(Client c) {
clients.get(clients.size()++) = a;
fireTableDataChanged();
}
}
You can't ++ the return value from a method, because the argument of ++ has to be something that is valid on the left hand side of an assignment. If you want to add something to the end of a Collection then the correct way to do that is to use the add method.
clients.add(a);
Also, you should fire a more specific modification event than simply "table changed". Calling fireTableDataChanged essentially tells listeners "the data in this model has changed beyond recognition, throw away your current visual representation and build a completely new one instead". It would be much more efficient and provide a better user experience if instead you used
fireTableRowsInserted(clients.size() - 1, clients.size() - 1);
which specifically says "one new row has been added to the end of this model, but the rest of the data is unchanged".
do like this
change
clients.get(clients.size()++) = a;
to
clients.add(c);
Now your method looks like
public void add(Client c) {
clients.add(c);
fireTableDataChanged();
}
}
Not sure how you getting clients.size(); believing clients Collection present in ModelTabel class.
Just keep it simple. You have an arraylist of clients right?
class ModelTabel extends AbstractTableModel{
ArrayList<Client> clients = new ArrayList<Client>();
public int getRowCount() {
return clients.size();
}
public int getColumnCount() {
return 4;
}
public Object getValueAt(int row, int column) {
Client c = clients.get(row);
switch(column){
case 0: return c.getName();
case 1: return c.getSurname();
case 2: return c.getID();
case 3: return c.getPhone();
default:return "ERROR";
}
}
public void add(Client c) {
clients.add(c);
fireTableDataChanged();
}
}
I believe this is the same problem as this question... your variable assignment is reversed.
It should be (although this code is still incorrect - see below):
a = clients.get(clients.size()++);
EDIT: this was already answered by Prabhakaran, but apparently people felt the need to downvote my answer.. I think I did address the original question, but I appreciate that my code sample was still incorrect, so I will try to provide a more complete answer:
First of all, as to the "required variable not found" error, if you google it you will see that other SO question as the first hit. clients.get(clients.size()++) is not a variable, so you can't assign things to it. I am not sure where a is declared in your code, but assume that it is a variable and thus my suggestion of reversing the assignment.
Next, for the clients.get(clients.size()++) line, as others have mentioned or alluded to - VAR++ is equivalent to VAR = VAR + 1, so again is an assignment operation going on. In this case, clients.size() is not a variable, so you can not increment it. If you wanted the clients.size() + 1 index, you could have written: a = clients.get(clients.size() + 1)... but that will throw an ArrayIndexOutOfBoundsException, because you're trying to access an element of clients beyond its current size!
That is why Prabhakaran rewrote your method as they did, changing that line to a clients.add(c) call - as it seemed to fit the original intent of the method.
Please show the full error message, not a paraphrasing of the error. Please show the line of text that causes the error.
Having said that, where is your clients variable? Where is it declared? Initialized? I think that your model needs this to work and to make sense.
It would help if you show how your collection (I'm assuming it's a List? is being declared.
That being said, your add method doesn't make sense: I think you mean:
{
clients.add( c );
fireTableDataChanged()
}
Related
So I have written a Java program that has a function handInExam() that may not be called twice in a row, thus the program is history-sensitive. The problem that then occurs is that I need a variable canHandInExam to check whether this method has already been called and update this variable in each method, which leads to very poor maintainability. Below is a code snippet to show the problem.
public class NotAllowedException extends Exception {
public NotAllowedException(String message) {
super(message);
}
}
import java.util.Scanner;
public class Exam {
String[] exam;
String[] answers;
boolean canHandInExam;
public Exam(String[] questions) {
exam = questions;
answers = new String[exam.length];
canHandInExam = false;
}
// This method may only be called once in a row
public void handInExam throws NotAllowedException() {
if (canHandInExam) {
// Send exam to teacher
canHandInExam = false;
} else {
throw new NotAllowedException("You may not hand in this exam!");
}
}
public void otherMethod() {
// Do something
canHandInExam = true;
}
}
In this small example it is feasible to slightly adapt each method, however if you would have lots of methods you would need to adapt all of them. Since after all these methods you may again call handInExam() thus the variable canHandInExam would need to be set to true.
Is there a way to solve this problem in a way that is more maintainable? I am open to other possible programming languages that are not OO, but at this point I am unsure of what would be suitable.
I have considered using functional programming (e.g. Haskell) as those languages are not history-sensitive, however I did not know how to limit that you may only call a function once in a row. I tried searching for how to limit a function call to n times in a row both in Java and Haskell, but this ended up with only references to how to call a function n times.
If you speak about handing in an exam, than this doesn't mean that something is done with that exam, but that there is some entity to which the exam is given. So instead of storing within the exam whether it was handed in or can be handed in, something like this would be more appropriate:
//or whatever you call this
public interface Institution {
void handInExam(Exam exam) throws DuplicateExamException;
boolean isHandedIn(Exam exam);
}
Implementations of Institution store the exams that were handed in (possibly using a Set).
When we return value from a method,assign the return value to a variable is better than return value directly without assign to any variable?in the following examples:
public int getCustomerId(){
return CustomerService.getCustomerById();
}
and another example:
public int getCustomerId(){
int id = CustomerService.getCustomberById();
return id;
}
which one is more better and why?I saw one of my friend's code,he assign value to variable first and then return that variable to his service method.
Both the approach are right, it's all depend how much code we are writing in our functions or how much readable our code is.
If it is one-two liner code, i would go for the first approach.
As simple as this, readability is fine.
public int getCustomerId(){
return CustomerService.getCustomerById();
}
This makes code little less readable, because just a service call, i need to go through two steps. Extra debugging.
public int getCustomerId(){
int id = CustomerService.getCustomberById();
return id;
}
If i have some complex logic written, maybe at business layer, multiple if-else, try-catch etc, then 2nd approach looks fine.
Just an example, and it makes sense
f(){
Object obj = null;
try{
if(condition){
obj = // call service1
}else {
obj = // call service2
}
}catch(Exception e){
}
return obj;
}
I agree using extra variable (though local to function), then
assignment, might add little overhead to JVM, but code readability
should also be considered while coding. JVM is again smart enough to optimize your code as highlighted above.
Refer these links for something more. Not exactly related but can help.
Im learning java and i have come across a function calc (have changed few objects and removed few lines), however i couldnt understand below code...
I understand this follows builder pattern
Questions:
i have never seen this before and due to poor search i havent got much help from googling... can we do return new Object and a function below that...
How this can be explained in simple terms
case 1 with no coding and default below that; does it mean 1 is most of the time default
Here is my code:
public calc(int value)
{
switch (value) {
case 0:
return new validator<objValidator>() {
#Override
public Boolean evaluate() {
//some business logic to return true/false
return true;
}
};
case 1:
default:
return new validator<objValidator>() {
#Override
public Boolean evaluate() {
//some business logic to return true/false
return true;
}
};
}
}
What you see here is called an anonymous inner class. Searching for that term should bring up some useful results.
Basically validator<objValidator> is an interface and you create an implementation of it in-place.
These are called as Anonymous Classes.
See this link.
Question 1: yes you can
think about it like defining a new Anonymous class inside it
for more info about Anonymous classes
please see this link
enter link description here
Question 2:
case 1: means no action done if the value is 1
case default: means if the value not = 1 then the function below will be executed
for more info about switch case statement
please point to this link
Ok, So I have a method
public static int getTotalLegCountDog (ArrayList<Dog> dogList)
{
int temp = 0;
for (int i = 0; i < dogList.size(); i++)
{
temp = dogList.get(i).getNumLegs();
totalLegsDogs += temp;
}
return totalLegsDogs;
}
It adds up the total legs of dogs and returns them as totalLegsDogs and there is another that totals the legs for cats.
Now I'd like a method that would take both the returned totalLegsDogs and returned totalLegsCats and add them together. My try is below (It returns 0), any help would be great!
public int getTotalLegCount ()
{
totalLegs = totalLegsDogs + totalLegsCats;
return totalLegs;
}
Was not calling the Method correctly. The math in the Problem was solid. The problem was the Method output call.
As far as I can tell, there's nothing wrong with the methods themselves - likely you're calling getTotalLegCount before actually counting the legs.
Fix 1 (preferred): Have getTotalLegCount call the methods.
public int getTotalLegCount (ArrayList<Dog> dogList, ArrayList<Cat> catList) {
totalLegs = getTotalLegCountDog(dogList) + getTotalLegCountCat;
return totalLegs;
}
Fix 2: Make it very clear that the leg-counting methods are to be called first. This is the inferior solution, as it requires more effort on the future programmer's part (and that might be future-you!).
I don't think you've shown us enough of your code to do any troubleshooting. It looks like you must have a global static count for dog legs and cat legs? I can't figure out your use case, but any rate, you need to make sure both your counting methods are called before you do anything with the member variables or else they will not be initialized. Example:
DogCatCounter.getTotalLegDogCount(...);
DogCatCounter.getTotalLegCatCount(...);
new DogCatCounter().getTotalLegCount();
The result from that third line should be correct as long as no other instances of DogCatCounter have modified your static variables. In other words, if you have multiple instances of DogCatCounter, any calls to your counting methods are going to modify your global static members.
I face a problem in using AbstractTableModel, i use linked list as a container for data , and i fetch records from table from db then i put it in linked list in table model then i male jable.setModel(model). THE PROBLEM i face that the last record i fetch from table from db is repeated n times since n is the number of records in database.
and when i make model.getIndextOF(anAppointmentDate); each time return 0 , so i think it each time the object in inserted in the same place ? i may be wrong , but that what i think
public class appointmentModel extends AbstractTableModel {
List<appointmentDate> patientAppointment;
public appointmentModel() {
patientAppointment = new LinkedList<appointmentDate>(); // linked list
}
public int getRowCount() {
return patientAppointment.size();
}
public int getColumnCount() {
return 2;
}
public String getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return patientAppointment.get(rowIndex).getDateOFAppointment();
} else if (columnIndex == 1) {
return patientAppointment.get(rowIndex).getTimeOfAppointment();
} else {
return "Not found";
}
}
public String getColumnName(int column) {
if (column == 0) {
return "date";
} else if (column == 1) {
return "time";
} else {
return "not found";
}
}
public void insertRecord(appointmentDate anAppointmentDate)
{
list.add(anAppointmentDate);
fireTableRowsInserted(list.size()-1, list.size()-1);
System.out.println(list.indexOf(anAppointmentDate)); // each time it prints 0
}
//////////
here where i use the model
while (resultSet.next()) {
N_Date= resultSet.getDate("appointDate");
anAppointment.setDateOFAppointment(N_Date);
N_time = resultSet.getString("appointTime");
anAppointment.setTimeOfAppointment(N_time);
tableModel.insertRecord(anAppointment);
}
jTable.setModel(tableModel);
The output i have is the last record repeated in all table records ,plz help!
You are using the same reference to an AppointmentDate object, and change only its internal state.
Thus everytime you add the same object to the list. So with the last loop iteration you set all objects inside the list to have the data of the last row.
To fix this, instantiate a new AppointmentDate() on each loop iteration:
while (resultSet.next()) {
AppointmentDate anAppointment = new AppontmentDate();
// the rest is the same
}
Note also that the class name should start with an upper-case letter - i.e. AppointmentDate, not appointmentDate.
Found the problem!
You don't show quite enough code around "where you use the model" but it looks like you are re-using the same object for each insert. You've got this object, you set its attributes from what comes out of the DB, and then you stash it in the list.
Well guess what: It's the same object every time, so it's bound to have the same value every time! If you want different values in your list, you'll need to use distinct objects. Don't worry, this is a common enough beginner's mistake.
A sensible way to do this would be to construct a new appointmentDate for every DB record. You may want to initialize the data right in the constructor.
Finally, note that if appointmentDate is a class name, it should (by convention) begin with an uppercase letter!
Finally (some more): LinkedList is efficient at inserts, but performs horribly at retrieval, i.e. the get(n) thing. I'd expect there to be a lot more scrolling and displaying from your list than inserting, so I'd use the List implementation that's much better performing here: ArrayList. It works the same, is only marginally slower at inserts and much faster at retrieval. But that's just additional information for you. Performance isn't so important for a small project like this.