Donald T
Donald T

Reputation: 10647

Java classes not interacting properly

I have two Java class files: primegen and primecheck sitting in the same directory. primegen calls a public static function from primecheck. primecheck compiles fine.

However, I receive the following compilation error in primegen:

primegen.java:31: cannot find symbol
symbol  : variable primecheck
location: class primegen
          } while (!primecheck.prime(primeCandidate));
                ^

Shouldn't Java be checking other (compiled) classes within the same directory? Does Java have a problem with primecheck being in lower-case letters (e.g. Is it treating primecheck as a variable instead of a class?)?

Update with Complete Code

Code for primegen:

import java.math.BigInteger;
import java.util.Random;

public class primegen
{

    public static void main(String args[])
    {
        try
        {
            int numBits = Integer.parseInt(args[0].trim());
            System.out.println(generatePrime(numBits));
        }
        catch (Exception e)
        {
            System.out.println("You must enter a positive integer number of bits.");
        }
    }

    private static BigInteger generatePrime(int numBits) throws Exception
    {
        if (numBits < 1)
            throw new Exception("You must enter a positive integer number of bits.");

        BigInteger primeCandidate;
        Random rand = new Random();

        do
        {
            primeCandidate = new BigInteger(numBits, rand);
        } while (!primecheck.prime(primeCandidate));

        return primeCandidate;
    }

}

Code for primecheck:

import java.math.BigInteger;
import java.util.Random;

public class primecheck
{

    public static void main(String args[])
    {
        try
        {
            BigInteger primeCandidate = new BigInteger(args[0].trim());
            if (prime(primeCandidate))
                System.out.println("True");
            else
                System.out.println("False");
        }
        catch (Exception e)
        {
            System.out.println("You must enter a positive integer.");
        }
    }

    public static boolean prime(BigInteger n) throws Exception
    {
        if (n.compareTo(BigInteger.ZERO) == -1)
            throw new Exception("You must enter a positive integer.");
        else if (n.equals(BigInteger.ZERO) || n.equals(BigInteger.ONE))
            return false;

        int maxIterations = 1000;
        BigInteger a;

        for (int i = 0; i < maxIterations; i++)
        {
            a = randomBase(n);
            a = a.modPow(n.subtract(BigInteger.ONE), n);

            if (!a.equals(BigInteger.ONE))
                return false;
        }

        return true;
    }

    private static BigInteger randomBase(BigInteger n)
    {
        Random rand = new Random(); 
        BigInteger a;

        do
        {
            a = new BigInteger(n.bitLength(), rand);
        } while ( !(BigInteger.ONE.compareTo(a) <= 0 && a.compareTo(n) < 0) );

        return a;
    }

}

Upvotes: 0

Views: 565

Answers (5)

Grodriguez
Grodriguez

Reputation: 21995

Java does not care about names being all lowercase or uppercase. These are just naming conventions (Java is case sensitive, but will not enforce any particular naming convention).

Edit: (after a few iterations :)

The code you posted compiles fine. The problem is obviously somewhere else (javac command line arguments, classpath...)

Upvotes: 2

Vineet Reynolds
Vineet Reynolds

Reputation: 76709

There appears to be a symbol conflict in your primegen class.

Declaring another variable primecheck within the same scope results in confusing the compiler on how it should be treating the reference - is the code referencing the class or the object? It ends up treating it as an object reference, and since the object's class does not have the method prime() defined in it, it throws up the error. Of course, the example also vindicates why naming conventions are a good idea.

Consider the following snippets of code, and the resulting error when compiling primegen.

Class primegen

import java.math.BigInteger;
import java.util.Random;

public class primegen
{
    public static void main(String args[]){}
    private static BigInteger generatePrime(int numBits) throws Exception
    {
        if (numBits < 1)
            throw new Exception("You must enter a positive integer number of bits.");

        BigInteger primeCandidate;
        Random rand = new Random();
        String primecheck = "";
        do
        {
            primeCandidate = new BigInteger(numBits, rand);
        } while (!primecheck.prime(primeCandidate));

        return primeCandidate;
    }
}

Class primecheck

import java.math.BigInteger;

public class primecheck
{
    public static void main(String args[]){}
    private static BigInteger randomBase(BigInteger n){return null;}
    public static boolean prime(BigInteger n) throws Exception
    {
        if (n.compareTo(BigInteger.ZERO) == -1)
            throw new Exception("You must enter a positive integer.");
        else if (n.equals(BigInteger.ZERO) || n.equals(BigInteger.ONE))
            return false;

        int maxIterations = 1000;
        BigInteger a;

        for (int i = 0; i < maxIterations; i++)
        {
            a = randomBase(n);
            a = a.modPow(n.subtract(BigInteger.ONE), n);

            if (!a.equals(BigInteger.ONE))
                return false;
        }

        return true;
    }
}

The resulting error is:

primegen.java:18: cannot find symbol
symbol  : method prime(java.math.BigInteger)
location: class java.lang.String
        } while (!primecheck.prime(primeCandidate));
                            ^
1 error

Upvotes: 0

Vineet Reynolds
Vineet Reynolds

Reputation: 76709

Since this is a compilation error, rather than a runtime one, it is important to understand that the compiler cannot find the primecheck class when compiling primegen. The current directory (by inference, the current package) is included by default, by the javac compiler in the user classpath, whenever any symbols have to be resolved during compilation. However, if this is overridden by the CLASSPATH environment variable, then symbol resolution will fail.

There is also a likelihood (I haven't verified this) that the '.' symbol in the classpath environment variable is not expanded into the current working directory, and hence it would be better to explicitly specify the location of the .class files.

Therefore, it is important to specify the location of the primecheck class when compiling primegen, either by the -classpath option (to indicate where the .class files can be found) or the -sourcepath option (to indicate where the compiler can find the source code of the class).

Reference:

  1. The javac tech notes.
  2. Setting the classpath for javac

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074228

Check your classpath — does it have "." in it? If not, no, Java will not look in the current directory for classes.

No, Java doesn't care about the class names being in all lower case (provided they're consistently lower case, both where used and where defined), but the convention is for classes to have a capital first character (and usually to be camelCase), e.g. PrimeGen and PrimeCheck vs. primegen and primecheck. It doesn't relate to your problem, but it will tend to startle and confuse people looking at the code (like people on SO). :-)

Update Are these classes in a package? If so, you need to be sure that they're in the right place relative to the class path as relates to the package. But typically that would have shown up on your import statement, as opposed to your use of primecheck...

Upvotes: 2

Mark Peters
Mark Peters

Reputation: 81074

Java is case sensitive. Perhaps your class is defined as PrimeCheck or something similar?

Upvotes: 2

Related Questions