I have a function "getStudent()" that returns an ArrayList of strings and when i call this function in another class, i get a NullPointerException, i thought i had correctly initialized my List.
Here are the two functions and the line i get a NullPointerException is in bold.
public ArrayList<String> getStudents(){
try
{
System.out.println("gets here ");
Statement newStat = this.conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet res = newStat.executeQuery("SELECT FirstName FROM Students");
String data = "";
while (res.next()){
studentList.add(res.getString("FirstName"));
}
}
catch(SQLException e){
System.err.println("SQLException: " + e.getMessage());
}
return studentList;
}
Function that calls 'getStudents()'
public class CancelListener implements ActionListener{
private Main_Menu menu;
private ArrayList<String> arrayList = new ArrayList<String>();;
Iterator iterator = arrayList.iterator();
public CancelListener(Main_Menu menu) {
this.menu = menu;
}
#Override
public void actionPerformed(ActionEvent ae) {
if(ae.getActionCommand().equalsIgnoreCase("Cancel")){
**arrayList = StudentModel.getStudents();**// NULLPOINTER EXCEPTION
while(iterator.hasNext()){
System.out.println(iterator.next().toString());
}
this.menu.resetStudent();
}
}
}
Your StudentModel variable is probably null. The code you posted doesn't show how that variable is initialized so I can't tell you exactly what you're doing wrong, but when you reach the line marked it must be null.
You should check that you are initializing that variable correctly before you try to use it.
You probably didn't initialize StudentModel. But I can't tell for sure since this part of the code doesn't appear here.
getStudents() isn't static, and it looks like you're calling it as a static method (judging by the way you've capitalized StudentModel.) So, as others have already said, you probably need to instantiate a StudentModel object, then call instance.getStudents().
Further, I don't see where you're creating an array instance. getStudents() adds items to studentList, but we don't see how studentList is initialized. This might also be the problem. Frankly, given what you're doing, there's probably no reason to make studentList an instance variable. So just declare the variable locally and allocate the array in the getStudents() method.
You mentioned that you think you initialized the list correctly, but this isn't what you are getting the exception on. Also, you may have another problem.
You get an iterator for your list:
Iterator iterator = arrayList.iterator();
Then you assign a different object to that reference:
arrayList = StudentModel.getStudents();// NULLPOINTER EXCEPTION
Then you try to use the iterator:
while(iterator.hasNext()){
My understanding is that this shouldn't cause an exception, since you're not making changes to list the iterator refers. But, you are almost certainly iterating through a different list that you think you are. Is it possible you may be mis-interpreting an exception that is somehow caused here?
Related
I have a LogAnalyzer class that looks at a web server log, creates LogEntry objects and puts those objects into HashMaps for analyzing.
My LogAnalyzer class has these fields:
private int totalVisits;
private int uniqueVisits;
private ArrayList<LogEntry> records;
private HashMap<String, ArrayList<LogEntry>> uniqueIPs; //<address, log entries>
private HashMap<String, ArrayList<LogEntry>> dailyRecords; // <date, log entries>
My constructor looks like this:
public LogAnalyzer() {
records = new ArrayList<>();
dailyRecords = new HashMap<>();
uniqueIPs = new HashMap<>();
}
And then I have this method:
public void initializeRecords(String path){
readFile(path); //reads the web log file and fills out the records and dailyRecords fields
getUniqueIPs(); //fills out the uniqueIPs HashMap field.
uniqueVisits = uniqueIPs.size(); //fills out the uniqueVisits field
totalVisits = records.size(); //fills out the totalVisits field
}
So my question:
I have read (but don't really understand) it's "bad" to call methods inside the constructor. However it seems like the constructor is pointless here, since it is actually the initializeRecords that is doing all of the meaningful work of "creating" the object.
I don't have the background in Java or programming to understand the explanations I've found so far. There is a lot of talk of overriding things, and I think that's what I'm not clear on. I'm wondering why I should keep my constructor and this method seperated, in simple terms that a beginner can understand.
**EDIT: ** Here's the code for readFile():
public void readFile(String filename) {
FileResource fr = new FileResource(filename);
for (String line : fr.lines()){
LogEntry le = WebLogParser.parseEntry(line);
String date = le.getAccessTime().toString().substring(4, 10);
if (dailyRecords.keySet().contains(date)){
dailyRecords.get(date).add(le);
}
else{
ArrayList<LogEntry> entries = new ArrayList<>();
entries.add(le);
dailyRecords.put(date, entries);
}
records.add(le);
}
Keeping the two methods allows you more flexibility in the use of your code. You can instantiate your LogAnalyzer without knowing the path to your log. I would rename initializeRecords to processRecords which IMO is more descriptive of what you are doing there.
We should create the object first and then call methods on it. If your readFile method were to throw an Exception because it can't read the file for example. I would find it very odd to get that exception when I am constructing the object. The point of the constructor is to provide an object that can be used to do something.
It's not a good practice to call methods from within constructor, because Java always calls the most derived method, which means we could call a method on a half-initialized object.
To answer your question,
public LogAnalyzer() {
records = new ArrayList<>();
dailyRecords = new HashMap<>();
uniqueIPs = new HashMap<>();
}
What the above part exactly does is, it gives the variables, records, dailyRecods and uniqueIPs a physical address in the memory stack.
When we write something like private ArrayList<LogEntry> records; in the class, at this time only a reference is generated, but actual initialization happens only when records = new ArrayList<>(); this line gets executed.
Hope this clarifies your doubt!!!
As you can see in readFile() it uses the following instruction
dailyRecords.keySet().contains(date)
without initializing dailyRecords prior to it. So if you do not initialize dailyRecords either while declaring it or in constructor you will face NullPointerException.
In your case instead of using constructor for initialization you can use declaration part like this
private HashMap<String, ArrayList<LogEntry>> dailyRecords = new HashMap<>();
Given this method:
public void walk( String path , ArrayList<String> files, String ext)
which collects all files into the ArrayList<> files starting at path and with given extension ext, I'm looking for a way to stop the search when a certain condition is met. For example, it should stop when files.size() becomes greater than a given number. How could I do this without modifying the method walk() ?
By not modifying the method, I mean not touching the source code in the editor. It's in a state that I like, and I don't want to touch it, because it's just for testing purpose.
Create your class extending ArrayList and override add method:
public class MyList extends ArrayList<String> {
#Override
public boolean add(String item) {
boolean added = super.add(item);
if (added && size() >= 10) {
throw MaxItemsReachedException();
}
}
}
When size is greater or equals to 10, for instance, you can throw an exception.
And call your method with an instance of MyList instead of ArrayList:
MyList list = new MyList();
walk("path", list, "extension");
DISCLAIMER: This is bad programming practice. Dont't do this. I only offer it because it solves the OP's problem.
Subclass ArrayList. Add some logic to the add methods that throw an exception if files.size is greater than some threshold.
It will look like this
public void add(E element){
if(size()<THRESHOLD){
super.add(element);
}else{
throw new RuntimeException("STOP HERE");
}
}
Try to throw an exception that walk does not catch and you should catch this exception in the method that calls walk.
Among other bad things this is using exceptions to manage flow control.
For some reason, my sortByDuration method will not let me call my remove method to print out the items in my heap as they are being deleted. The purpose of this is just to sort the heap; it really doesn't matter that I am deleting it.
public static Song[] sortByDuration(Song[] songs)//sorts the heap
{
for(int i=size;i>0;i--)
System.out.print(songs.remove()+" ");
return songs;
}
and this is my remove method
public Song remove()//removes
{
Song retVal = peek();
heap[0] = heap[size-1];
heap[size-1] = null;
size--;
bubbleDown();
return retVal;
}
the error is in the print statement of my remove method
Thanks guys
You are trying to call the method remove() on an array of objects. Arrays in Java do not have such a method.
For your code to work properly, you will need to change the way you remove the objects from your songs array. Maybe you want to take a look at "Removing an element from an Array (Java)" question here in SO.
You may also have missed to index your elements (to access only the i-th element instead of the entire array), and the statement you wanted to write was
System.out.print(songs[i].remove()+" ");
I've been receiving ClassCastException in my code. Objective initially was to convert Set to List since the refreshDetailVOTable method will only get Set. The problem could have been in converting Set to List. refreshDetailVOTable might took the wrong List that's why I'm receiving ClassCastException. Any thoughts on this?
public List deleteChildPromotionComponentDetails(ClientContext context, List detailIRsToDelete,
String emergencyAccessPermission) throws RetekBusinessException {
List exclusionList = null;
RpmEvent deleteEvent = buildPromotionComponentDetailsDeleteEvent(emergencyAccessPermission);
deleteEvent.setTransitionNotificationExceptionFlag(true);
Set detailBOsToDelete = new HashSet();
for (Iterator iDetails = detailIRsToDelete.iterator(); iDetails.hasNext();) {
IdentifiableReference detailIR = (IdentifiableReference) iDetails.next();
PromotionComponentDetail promotionComponentDetail = (PromotionComponentDetail) getService()
.readForUpdate(detailIR);
Set exclusionSet = promotionComponentDetail.getExceptionsAndExclusions();
exclusionList = new ArrayList (exclusionSet);
for(Iterator exclusion = exclusionSet.iterator(); exclusion.hasNext();){
PromotionComponentDetail exclusionDel = (PromotionComponentDetail) exclusion.next();
exclusionDel.accept(deleteEvent);
detailBOsToDelete.add(promotionComponentDetail);
}
}
return exclusionList;
}
public void deleteChildDetails(final List parentComponentDetails)
{
List list = null;
try {
list = getCmlPromotionComponentDetailAppService().deleteChildPromotionComponentDetails(
ClientContext.getInstance(), parentComponentDetails,
emergencyPermission.getName());
} catch (RetekBusinessException e) {
e.printStackTrace();
}
refreshDetailVOTable(list);
}
Take a look at the generics tutorial here:
http://docs.oracle.com/javase/tutorial/java/generics/
You're doing pretty simple stuff, so you only need to look at the first part. You probably don't need to dive into wildcards.
A guess as to what's happening: your method is receiving a parameter List detailIRsToDelete from which you get an iterator and iterate over the elements like so:
for (Iterator iDetails = detailIRsToDelete.iterator(); iDetails.hasNext();) {
IdentifiableReference detailIR = (IdentifiableReference) iDetails.next();
...
}
If whoever calls you had accidentally put something other than an IdentifiableReference into detailIRsToDelete, you'd get a ClassCastException in the assignment statement within the loop. If instead the list parameter were declared
List<IdentifiableReference> detailIRsToDelete
the act of putting things into this list would be checked by the compiler, and the error would occur at the point where the erroneous object was added, at compile time, instead of later at runtime, as you're experiencing.
With the code
package items;
public class itemtest {
static itemobject[] item = new items[10];
{
items[0] = new Toy("Example ID","Example Desc");
items[1] = new Toy("Second Example ID", " Second Example Desc");
}
public static void main(String[] args)
{
String tid = items[0].exampleiD;
System.out.print(tid);
}
}
I get the error :
Exception in thread "main" java.lang.NullPointerException at items.itemtest.main(itemtest.java:17)
on the code line: String tid = item[0].exampleID;
Sorry I'm very new to java, could anyone shed some light on what I'm doing wrong ?
{
items[0] = new Toy("Example ID","Example Desc");
items[1] = new Toy("Second Example ID", " Second Example Desc");
}
You need to precede this block with the word static to have it take effect when the class is loaded -- which is what you actually want to happen, based on your code -- as opposed to when a new instance of itemobject is created, which never happens in your code.
From your code snippet I assume that you think you are trying to do the following:
Declare an array of items
Initialize the the first two items with Toy objects
Get the first item of the array and print it
The problem in the code is:
You declare items array as static field
You have an instance initialization block where you initialize the array
You have a main function where you get the item and print it
The problem is that the initialization block is done at initialization of instances. The main method however is a static method and has no instance. Therefore the block has not been called yet and you get a NPE.
You need to make the initialization block also static like this:
static {
items[0] = new Toy...
items[1] = new Toy...
}
A static initialization block is called once when the class is initialized. So that way it is called before main will be run.