Hi Java Developers,
wondering if someone can point out why references to 'Student' (successfully compiled java class) in my ValidRecords.java source file don't seem to resolve at compile time?

It's important to say that ANY and ALL references to Student object from inside ValidRecords.java don't resolve... not just the one I've listed below. I'm a newbie to java doing something really stupid, but what??? Appreciate some help from an experienced Java developer.

Things I've tried:

  1. ensured compiled Student.class file is in same dir AND classpath is set correctly to the same dir (should be redundant but done).
  2. same error from Netbeans and also from command line using javac ValidRecords.java
  3. ensured that both classes are public and so are the appropriate methods

code:

// this is an except from ValidRecords.java where the compiler says 
// (refer after the code for compiler error) ...
public boolean addStudent(Student s) {
    // wrapper for the arraylist add method
        boolean addOk = Boolean.FALSE;
        if( s.isValidStudent() ) {                      // s.isValidStudent() bombs because it can't resolve Student s: the compiler is not 'seeing' Student as a class from inside this class???
            this.list.add(s);
            addOk = Boolean.TRUE;
        }
        return addOk;
    }

COMPILER ERROR:

D:\ST152-Warwick\Student.java\AssignSource\src\Assignment\ValidRecords.java:57: cannot find symbol
symbol  : method isValidStudent()
location: class java.lang.Object
        if( s.isValidStudent()

I think it would be easier for us to help if you post the Student class as well. It would help if we can see how and where your methods are defined. Thanks

the compiler does not see the isValidStudent() as a method of Student class.

the compiler does not see the isValidStudent() as a method of Student class.

Yes I understand that. There may be a syntax error in your Student class that is causing the problem. That is why I asked to see the code for the Student class. Thanks.

Do you have all the files relating to this project saved in the same file or directory? That may be causing the problem.

Thanks for any help... here is Student.java so you can see how it's defined... as I mentioned in original post; these classes are in the same dir

I have listed BOTH classes below; Student.java first and then ValidRecords.java next... hope someone can see the problem.

package Assignment;
/**
 *
 * @author Nigel Novak
 */
public class Student {

// class variables and constants follow
    private int id;
    private String fName, lName;
    private double percent;
    private String grade;
    private boolean validStudent;
    private String textLine;
    private boolean validStudentCSV;
    private int numOfFields;
    private String[] fields;

// inclusive validation range for student id numbers
    public final int MIN_ID = 00000000;
    public final int MAX_ID = 99999999;
// inclusive validation length for name strings
    public final int MIN_NAME_LENGTH = 1;
    public final int MAX_NAME_LENGTH = 50;
    public static final int CORRECT_NUM_FIELDS = 5;
    
// Constructors Follow
    // Default
    public Student( ) {
        /* will only create 'placeholder' values of a new Student object
        *  and therefore it will be an invalid Student object by default... */
        this.id = 0;
        this.fName = ""; this.lName = "";
        this.percent = 0.0;
        this.grade = "";
        this.validStudent = Boolean.FALSE;  // most important that it's marked as INVALID Student
        this.textLine = "";
        this.validStudentCSV = Boolean.FALSE;
        this.numOfFields = 0;
        this.fields = null;
    } // end of Default constructor
    
    // Alternate Constructor Follows
    public Student( String inText ) {
        this.validStudentCSV = Boolean.FALSE;       // default to record format INVALID
        this.textLine = inText;
        if( processTextLine( inText ) ) {           // processTextLine determines student record validity and sets several class variables
            // 
            this.validStudent = Boolean.TRUE;
            assignArrayFieldsToClassVariables();    // the rest of the class fields are populated here
            addStudentToValidList( );               // check class ValidRecords for the ADT ArrayList<Student>
        }
        else {
            // add inText to the invalid records list
            this.validStudent = Boolean.FALSE;
            addTextLineToInvalidList( inText );       // check class InvalidRecords for the ADT ArrayList<String>
        } 
    } // end of Alternate Constructor

    // Copy Constructor Follows
    public Student( Student s) {
        // first use Default constructor to create a new but INVALID 'skeleton' Student instance
        Student sCopy = new Student();
        // now populate fields from input Student being copied
        // copy primitive fields directly
        sCopy.id = s.id;
        sCopy.fName = s.fName;
        sCopy.lName = s.lName;
        sCopy.percent = s.percent;
        sCopy.grade = s.grade;
        sCopy.validStudent = s.validStudent;
        sCopy.textLine = s.textLine;
        sCopy.validStudentCSV = s.validStudentCSV;
        sCopy.numOfFields = s.numOfFields;
        // do not copy ref to array as it's an object, so return a clone of the array instance
        sCopy.fields = s.getFieldsArrayClone();
    } // end of Copy constructor

// Accessors Follow
    public int getId() {
        return id;
    }

    public String getfName() {
        return fName;
    }

    public String getlName() {
        return lName;
    }

    public double getPercent() {
        return percent;
    }

    public String getGrade() {
        return grade;
    }
    public String getTextLine() {
        return textLine;
    }

    public String[] getFieldsArrayClone() {
        return fields.clone();
    }

    public int getNumOfFields() {
        return numOfFields;
    }

    public boolean isValidStudentCSV() {
        return validStudentCSV;
    }

    public boolean isValidStudent() {
        return validStudent;
    }
    public boolean isValidId(  ){
        // should be 8 digit integer according to class constants
        boolean isValid = Boolean.FALSE;
        if( MIN_ID <= this.id && this.id <= MAX_ID ){
            isValid = Boolean.TRUE;
        }
        return isValid;
    }

    public boolean isValidfName(  ){
        boolean isValid = Boolean.FALSE;
        if( MIN_NAME_LENGTH <= this.fName.length() && this.fName.length() <= MAX_NAME_LENGTH ){
            isValid = Boolean.TRUE;
        }
        return isValid;
    }
    public boolean isValidlName(  ){
        boolean isValid = Boolean.FALSE;
        if( MIN_NAME_LENGTH <= this.lName.length() && this.lName.length() <= MAX_NAME_LENGTH ){
            isValid = Boolean.TRUE;
        }
        return isValid;
    }
    public boolean isValidPercent( ){
        boolean isValid = Boolean.FALSE;
        if( 0.0 <= this.percent && this.percent <= 100.0 ){
            isValid = Boolean.TRUE;
        }
        return isValid;
    }
    public boolean isValidGrade( ){
        boolean isValid = Boolean.FALSE;
        char gradeChar = this.grade.toCharArray()[0];    // convert to char array and grab first element only, i.e. a Char
        if( gradeChar == 'F' || gradeChar == '5' || gradeChar == '6'||
            gradeChar == '7' || gradeChar == '8' || gradeChar == '9' )  // what about 100%, do they get a '10' :-)
        {
            if( this.grade.length() == 5) { isValid = Boolean.TRUE; }    // looks tidier than an '&&' condition in above if statement
        }
        return isValid;
    }
    
// Mutators Follow
    private void setFieldsArray(String[] fields) {
        this.fields = fields;
    }

    private void setNumOfFields(int numOfFields) {
        this.numOfFields = numOfFields;
    }

    private void setValidStudentCSV( ) {
    // relies on processTextLine() to have run first and setup the fields[] class variable
        if( this.numOfFields != CORRECT_NUM_FIELDS ) {
            this.validStudentCSV = Boolean.FALSE;
        }
        else {
            this.validStudentCSV = Boolean.TRUE;
        }
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setfName(String fName) {
        this.fName = fName;
    }

    public void setlName(String lName) {
        this.lName = lName;
    }

    public void setPercent(double percent) {
        this.percent = percent;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }
    
    
// Imperative Methods Follow
    private void addStudentToValidList( ) {
        // this will add this Student object to the ADT in ValidRecords class
        
    }

    private void addTextLineToInvalidList( String badText ) {
        // this will add textline to the ArrayList<String> in InvalidRecords class
        // badText is a ref to the actual textline passed into the constructor
        // the format of the textline seems INVALID so it's being added to the invalid record list

    }
    private void assignArrayFieldsToClassVariables() {
        // should only get into here if the CSV is valid format and processTextLine has already run
        // check array field count anyway...
        if( this.numOfFields != CORRECT_NUM_FIELDS ) {
            setId( Integer.parseInt(this.fields[0]) );
            setfName( this.fields[1].trim() );
            setlName( this.fields[2].trim() );
            setPercent( Double.parseDouble(this.fields[3]) );
            setGrade( this.fields[4].trim() );
        }
    }
    private boolean processTextLine( String inString ) {
        if( inString != null ) {
            setFieldsArray( inString.split("'"));
            setNumOfFields( this.fields.length );
        }
        setValidStudentCSV();
        return isValidStudentCSV();
    }
   
    private String toString( boolean csv ){
       // formats a student record as text in either
       // csv format for a file OR for output to screen
       String outString = null;
       if( csv ){
           outString = this.id + "," + this.fName + "," + this.lName + "," + this.percent + "," + this.grade;
       }
       else{
           outString = this.id + "\t" + this.fName + "\t" + this.lName + "\t" + this.percent + "\t" + this.grade;
       }
       return outString;
   }

    public String toString(){
       // overide the expected default class level toString method
       // assume default usage intended to display string on screen
       String outString = null;
       outString = toString( Boolean.FALSE );
       return outString;
   }

} // end of class Student

***************************** next class follows:

package Assignment;

import java.util.*;
/**
 *
 * @author Nigel Novak
 */
public class ValidRecords<Student> {

    // Class Fields and Constants Follow
    private ArrayList<Student> list;
    private int sortOrder;
    
    public final static int NO_SORT = 0;
    public final static int ID = 1;
    public final static int LAST_NAME = 2;
    public final static int PERCENT = 3;
    
// Constructor Follows
    public ValidRecords( ) {
        this.list = new ArrayList<Student>();
        this.sortOrder = NO_SORT;
    } // end of constructor

// Accessors Follow

    public int getSortOrder() {
        return sortOrder;
    }
    
    public int getNumRecords() {
    // wrapper for the api size method
        return this.list.size();
    }

    public Iterator getIterator() {
        return this.list.iterator();
    }

// Imperative Methods Follow
    public void displayList() {
    // intended to display the list contents to the screen
        for( int index = 0; index < getNumRecords(); index++) {
            Student s = this.list.get(index);
            s.toString();
        }
    }
    
    public boolean addStudent(Student s) {
    // wrapper for the arraylist add method
        boolean addOk = Boolean.FALSE;
        if( s.isValidStudent() ) {
            this.list.add(s);
            addOk = Boolean.TRUE;
        }
        return addOk;
    }

    public void swapListElements( int e1, int e2) {
    // swap 2 Students in the list: e1 (element 1) and e2 (element 2) are the arraylist index positions of the Student objects
    // can't allow swap of elements that are empty (null)
    // should implement try catch block to check for thrown exceptions like index out of bounds...
        Student s1 = this.list.get(e1);
        Student s2 = this.list.get(e2);

        if( s1 != null && s2 != null ) {
            // first make copy of Student at e1
            Student sCopy = new Student( s1 );
            // use arraylist set method to overwrite Student object at e1 with Student at e2
            this.list.set(e1, s2);
            // now just overwrite Student object at e2 with the temp sCopy and swap done!
            this.list.set(e2, sCopy);
        }
    }

} // end of class ValidRecords

the compiler does not see the isValidStudent() as a method of Student class.

Yes true (kinda...); the compiler is not 'resolving' that Student IS A class and therefore as a result has no idea where to find the definition for the method... so that doesn't help but thanks anyway. Any other ideas welcome though :-)

package Assignment;

Your compiled class file should be in a directory called Assignment, and the directory that contains the Assignment directory should be in the classpath.

what if you tray this declaration
public class ValidRecords{
.......
........
}

package Assignment;

Your compiled class file should be in a directory called Assignment, and the directory that contains the Assignment directory should be in the classpath.

I tried all this but it made absolutely no difference to the errors:
1. i put both classes into a directory called Assignment
2. i changed the package declarations (in both files) to be "package Assignment;"
3. i changed the classpath to the absolute pathname where the source files are
4. recompiled Student.java - successfully
5. recompiled ValidRecords.java and the same errors again:confused:

What could be wrong??

please what you mean by this declaration:
public class ValidRecords<Student>

This is a standard way of declaring a java class that implements 'generics' ( sun has a pdf you can download on generics... )
There is a load of stuff on the web about generics in java; we are expected to make use of generics in our programming course when generics make sense... In this case I am making the type ArrayList<Student> an arraylist that is only able to have Student class elements stored in it... type safety...

It's the .class files that need to be in the Assignments dir; the source .java files' locations are irrelevant to this.
The classpath must point to the folder that contains the Assignments folder, NOT to the folder where the files are.

yep, that's the case. I realize this but alas there's no change to my situation... the clocks ticking and I don't know which wire to cut, red or blue???

This really has to be simple surely, but what have I missed? Maybe I'll try another computer in case it's environmental (or just mental).

Are you sure?

1. i put both classes into a directory called Assignment
2. i changed the package declarations (in both files) to be "package Assignment;"
3. i changed the classpath to the absolute pathname where the source files are

1. If the second compile always fails you cannot have a second .class file to put into the directory.
2. Thay already had that. What did you change?
3. This is wrong - the classpath must point to the folder that contains the "Assignment" folder that contains the class files. It's irrelevant where you out the source files.

yes, I can always get Student.java to compile producing a .class file. I have never been able to get ValidRecords.java to compile.

The classpath is correct and is C:\ST152-Warwick\Assignment currently; this is where the files reside (the 2 source files and the Student.class file)...

I have just tried on another computer with EXACTLY the same result.

public class ValidRecords<Student> {

I am wondering about the generic declaration for ValidRecords class but not sure about any of this... reason:
compiler throws-

ValidRecords.java:74: unexpected type
found     : type parameter Student
required : class
                    Student sCopy = new Student( s1 );
                                                       ^

the whitespace in front of the ^ (caret) has been blown away by the formatter thingy on this site; oops!

so the caret in above post should go under the 'S' in Student after the new keyword. So the constructor bit NOT the first Student in front of the sCopy

Hope that's clear

Remove "<Student>" from ValidRecords class opening, problem solved...

package Assignment;

import java.util.*;
/**
 *
 * @author Nigel Novak
 */
public class ValidRecords {

    // Class Fields and Constants Follow
    private ArrayList<Student> list;
    private int sortOrder;
commented: lightning quick solution; wish i'd emailed Peter earlier! +1

Remove "<Student>" from ValidRecords class opening, problem solved...

Peter that's Sensational!

:-/ was under the impression that i needed that for the generic stuff to work, i.e. ArrayList<Student> ...

Obviously I don't understand generics too well (what newbie does :))?

Is ArrayList<ClassName> or any valid var name placeholder a special case of generics? I understand the type safety side but why don't I need to make the class declaration with this generic placeholder present for compiler??

Anyway, thanks so much for your help. Really appreciated!

Also, interested in the LJC Undergrad website although down-under in Perth, Western Australia.

Peter that's Sensational!

:-/ was under the impression that i needed that for the generic stuff to work, i.e. ArrayList<Student> ...

Obviously I don't understand generics too well (what newbie does :))?

Is ArrayList<ClassName> or any valid var name placeholder a special case of generics? I understand the type safety side but why don't I need to make the class declaration with this generic placeholder present for compiler??

Anyway, thanks so much for your help. Really appreciated!

Also, interested in the LJC Undergrad website although down-under in Perth, Western Australia.

Nothing special, already another user questioned your use of class declaration placeholder.
I guess your reference to Sun tutorial on generics in PDF format is to this article Generics in the Java Programming Language. It is my opinion that this is not well presented. Try to read SCJP Sun Certified Programmer for Java 6 Study Guide from chapter 7 and see if that makes more sense for you (definitely easier to read then my endless rumbling).

As for anything similar to Java user/meetup groups I'm member in London I did not found anything in your location through meetup site, however your best chance would be get in touch with Australia Java Champion Mike Cannon-Brookes and see if he is aware of any Java group in your area. Good luck

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.