• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Accessing Object properties

 
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have written code taht reads a data file, parses it into a 2D String array (datasetStr) and then processes the array into an array of objects called Variable, one object for each data column in the 2D array. I want the objects to be available for other tasks later in the program. The Variable constructor defines the properties of the variable, such as its name, sum, mean, etc. In the following code, the System.out statement results in a null pointer exception. Can anyone point out why I can't access the Variable object properties?
 
Ranch Hand
Posts: 679
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If it's definitely line 12 that's throwing the exception, then nVar is less than or equal to 1 and hence nVar[1] is null.
The alternative explanation is that you haven't initialised your var variable, but that would give an NPE on line 10.
 
Chuck Geiger
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for a quick reply. It is definitely line 12 throwing the exception. I just ran a quick test to write the value of nVar immediately before line 12 and it accurately reported nVar = 3. I tried to put a similar System.out statement in the Variable constructor code, but it didn't send anything to the console.
 
Stuart A. Burkett
Ranch Hand
Posts: 679
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[strike]Does that code actually compile ? Line 10 looks wrong. I would have expected something like i.e. round brackets rather than square.[/strike]


Edit: Ignore that. I can see what you are doing. That line actually reinitialises the var variable every time rather than adding variables to the array.
It should be
That of course assumes that you have initialised the var variable somewhere. You may need the line
before your loop.
 
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Why is var marked static. That is often a mistake.
 
Chuck Geiger
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you both. I suspect these are newbie mistakes, but here goes. I declared Variable to be static (line 1) because when I tried referring to var[i] in another class I was working on, the compiler said that I could not make a static reference to a non-static variable; making it static seemed to make everyone happy. I think I see what you mean about reinitializing versus adding to the array, but I am not sure how to fix it. All the books and tutorials I have seen about initializing and using objects are for non-array situations.
 
Chuck Geiger
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK, I haven't had any more feedback for a long while, so let me update what I have tried. My code fragment now is below. I think it fits the advice I was given. Only now it won't compile elsewhere in the program, where in a separate class's constructor I have the line . The compilation error is: Cannot make a static reference to the non-static field Data.var (this was why my original post had "static" on the first line.


I'm still hoping for help. Thanks.
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chuck Geiger wrote: . . . Cannot make a static reference to the non-static field Data.var (this was why my original post had "static" on the first line. . . .

Definitely a mistake. What you are doing is writing code in your main method, which you oughtn’t, even though you see it in many books. You correct that error by moving the code out of the main method.You can probably think of a better name than go(), however. Now you put all the code you had there inside the go() method.

You have some very confusing code. You have a public field (fields should always be private unless they are used as constants), which looks like another mistake.Then inside your constructor, you are creating an array which shadows (I think it’s shadowing, or is it hiding? somebody please remind me) the field, which is not used in the code you showed, and which will go out of scope and vanish when you have finished your constructor but there appears to be a lot of code missing.
That is not what constructors are for. What you do in your constructor is to set up all the fields so as to get the class into a “consistent” state. Nothing more than that.
What is nVar? Is it a field? Why have you used such a poor name for the constructor parameter? What you ought to have looks more like thisMaybe you don’t need nVar as a field, but only use it to set up the Variable object.
You can provide getXXX methods to permit access to the fields, if required. You appear to have made the same mistake with the GS6 class (what a name for a class!) and its strName field. I think you have called it public static when it should be private and not static. If you need access to it, you can proved the GS6 class with a getStrName() method.
Similarly, of you have a go() method, that method will not be static, and can access all members of the class.
 
Chuck Geiger
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Wow, thanks for taking the time to write such a thorough answer. I have programmed a lot in Visual Basic and am finding Java a challenge. I will give your answer a close read and a lot of thought.
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You’re welcome
Java is really easy to understand, but underlying it is object‑oriented (OO) programming, which can be a big leap for somebody who hasn’t done OO programming before.
 
Chuck Geiger
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In this post I want to set the context, because I think that is lost in the fragment. The whole program is way too big to post.
Actually, GS6 is my main class (the program is GeoStats, which I use to teach statistics to my university Geography students). GS6 extends JFrame to create the program window with a tabbed series of JPanels.
GS6 calls the FileReader class to open and parse the data file. FileReader calls the Data class to do 2 things: create a small set of static variables (nVar is the # of variables, maxN is the # of rows in the longest data column, and datasetStr is the String version of the entire data table); and, in the piece I am solving here, I want the Data class to call the Variable class to make a complete representation of each variable (with fields such as varName, varSum, varMean, etc). Since I will have several variables in each dataset (and adapting my previous VisBasic versions 1-5 to Java) it seemed like creating an array of Variable objects fit the OOP model.
The next stage will be another class that writes all of the properties for each variable to a new tabbed panel in GS6 main. So far, even though the program compiles, by the time control is passed to the next class to write that panel, the Variable objects are all null.
You seem to be saying that it has to do with whether the field names in the Variable class are public or private (currently they are neither, so I will make them all private, and then write getters for each), and whether the code doing the work to calculate the sums and means, etc are in the constructor or in separate methods (I will work on moving them all into methods).
Please let me know if that is what you are saying. Thanks again.
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How much of that have you written? I only got halfway through the post and I was getting worried. You oughtn’t to put logic and display in the same class like that. You ought to separate them into different classes.

I would have developed it differently.
I would have started with a geography stats object. That would model a data line from your dataset. I am not sure whether it corresponds to your Data class or your Variable class. I would get one such object working, running it from a class which has a main method. Use that to get it working. You might find the altitude is always the third item in the line.Then I would use a reader (or possibly a Scanner, which works on text files only) to read from a file into such an object. Once that is working properly, you move onto the next stage.No need for static fields. No need for public fields. All the data are there in the GeogData object, ready for you to use The GeogData object can do any counting. No need for a String representation to pass around; those things are really difficult to use.
Beware if you are passing losts of different arguments to the constructor. There are ways round that sort of problem, possibly with multiple set methods, or with a factory, or by passing the entire String to a constructor and using a Scanner on it there. Yes, you can pass a String to a Scanner and it will take it apart for you.
The next stage might be to create an array of stats objects. Or it might put them in a Collection. A List like ArrayList<Data> might be a good candidate to try first. Get that working. Now you have lots of stats objects, all together where you can get at them. You can get the data from the List by iterating it, maybe with a for‑each loop, which you can use to get sums etc. You can get the number of lines from the List object by looking for its size.
You would want a class which works out the stats, from that List, and has methods like getAverageAltitude() etc etc. Get that working, similarly. Get methods like calculateAverageAltitude() which can be called from outside the class.

Now you put a GUI on top of all that lot.
 
Chuck Geiger
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK, here is where I am. I think what you were saying is that instead of starting with the entire datafile and breaking it down into smaller pieces to work with, I should start with the fundamental piece, the data value, make an object of that, and then work at building classes that compose it into the larger elements necessary for my GUI.
So, I created a new class, DataValue, and filled it with fields that will be useful (the code example below has just a few of them).

I already had a functioning Scanner, so now rather than read into the 2D Array String "matrix", I want to create DataValue objects. Here is my code for the file reader, with my matrix approach commented out and my DataValue added. The only problem is that Eclipse now tells me that it cannot instantiate DataValue (the exact line has the ERROR comment at the end).

Am I on the right track, and can you tell me why I'm getting the error?
Thanks.
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Why are you using column and row numbers? Why are you recording data as a String?
What sort of data do you have in a row? Show us an example. I can see what you are trying to do, viz. preserve the table in the object. But what good is that? What do the different parts represent? Is it lat, long, name, rainfall, altitude, and that sort of thing? Let’s imagine you have a row like this:I am afraid I ain’t got time to explain now, but try these classes
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Bad luck. I’m back.
What you see is nothing unusual; it is a common‑or‑garden class, which I have made immutable by making class and all fields final.
You should find the fields and toString and getXXX methods all easy to understand.
I think I have made a mistake in the equals() method with the exceptions. I think the class, as it stands, can never have null fields, so there is no chance of that Exception ever occurring. Apart from that it is a standard equals method. Note that instanceof is only reliable in a final class.
The hash code method is a standard implementation too, but the bit about ^ and >> is an advanced feature. Ask about that when you have the whole app working.
I don’t remember using a Scanner directly on a string before, but it works nicely and is quite easy when you actually try it. What it does is divide the String. It goes until it finds something which matches its delimiter, and whatever is before that is the name. The delimiter is a regular expression (again something to read up later) for a comma followed by any number (including 0) of white‑space characters. The next bit after name, until the next comma‑space, is the latitude. Etcetera, etcetera. It should be obvious, that constructor depends very heavily on the line being in the correct format.

Now it’s your turn. You can play with that class and use it, and alter it. I have made all sorts of suggestions already. Then you can write a class which matches your own data
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I got it wrong when I wrote: . . .

I missed out rainfall. It should read Sorry!
 
Chuck Geiger
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I see where you are coming from and we are talking at cross-purposes a bit. Your model is based on the assumption that the data being read in will always be in the same format: name, latitude, longitude, etc. I am writing a program that is much less predictable. The data file being read in could contain any number of rows AND any number of columns (separated by commas, *.csv fashion). Each column will always have the same kind of information (like yours) BUT the values in any of those positions can be any kind of data (numerical or text). That's why I am preserving a string version of each data value, so that I can process it elsewhere to determine what kind of data it is and what other statistical tests it's suited for. The ones that are numbers will be stored as numbers as well. When I need strings, such as for output purposes, I'll have the .valStrValue field ready for that.
I could use the Scanner on the lines of text in the DataValue object, but it seemed more appropriate to do in the CSVFileReader class. The line of text being read in is not the most important characteristic of the data. The columns (or variables) are much more important. If I can build the variables out of DataValue objects, then great.
I have two questions for you about your code that can still help me a lot. First, can you show me how your main class would change, if at all, if there were 2 or 3 lines of data to be read? I think that's where I have been getting messed up from the very beginning of this thread: how does Java hold on to multiple objects of the same type, multiple instances? Second, what is the purpose of lines 67 to 84 in your GeogData class, the "public boolean equals" etc. part? Does it have anything to do with maintaining multiple objects made from the same class?
Thanks again for your patience.
 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chuck Geiger wrote:I am writing a program that is much less predictable. The data file being read in could contain any number of rows AND any number of columns (separated by commas, *.csv fashion). Each column will always have the same kind of information (like yours) BUT the values in any of those positions can be any kind of data (numerical or text). That's why I am preserving a string version of each data value, so that I can process it elsewhere to determine what kind of data it is and what other statistical tests it's suited for. The ones that are numbers will be stored as numbers as well. When I need strings, such as for output purposes, I'll have the .valStrValue field ready for that.
Thanks again for your patience.


I've come to this thread a bit late, and have to admit not having read everything, so forgive me if I'm going over old ground; but from your last post it would suggest to me that you have stuff coming in that may not relate specifically to your GeogData class (or whatever it is you need).

If that's the case then simply turn it into a two-stage operation, no? Store the input as a String matrix (if it's line-oriented, I would suggest a List of Lists, or possibly a List<String[]> if your CSV class can provide it) and then extract the information from that.

As I say, I've been lazy on this one, so you may have already thought of it.

Winston

[Edit] I also split up the long comment lines in your code. Please re-read the UseCodeTags page thoroughly. Thanks.
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chuck Geiger wrote: . . . we are talking at cross-purposes a bit. Your model is based on the assumption that the data being read in will always be in the same format: name, latitude, longitude, etc. I am writing a program that is much less predictable. . . .

Yes, we are at cross purposes. I am not sure what to recommend. I know you can get programs which are designed to read .csv files, and we have an FAQ which suggests programs for all sorts of file formats.
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am wondering whether data where the rows and columns mean different things at different times are suitable for computerised processing at all. There are a few things I can think of which run by row/column. Obviously a database table is the first candidate, but you can get an array of arrays where each element represents a row.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic