Home Variables
Variable type
Choose the type which is most appropriate for the data you are trying to represent. Use 
an int when you only need whole numbers, doubles when you need 
decimal precision, booleans for when you need a binary true or false value, 
Strings for arbitrary text, and so forth.
Use int when you only need whole numbers. Use double when you 
need decimal precision. For example:
double numCreditsTaken = 15; // should be a number int scorePercentage = 86; // we probably want decimals
A corrected version would look like so:
int numCreditsTaken = 15; double scorePercentage = 86.2;
If you want an int to be a double so that you don't have to 
worry about issues with integer division, you should use either multiply your number by 1.0 
or use casting, rather then making a separate variable.
public static void foo(int a, int b) {
    double tempA = a;
    double tempB = b;
    
    return tempA / tempB;
}
The corrected version:
public static void foo(int a, int b) {
    return 1.0 * a / b;
    // OR 
    // return (double) a / b;
}
Don't try and shoehorn variables into something they aren't. For example, don't try and
use a String or an int to represent true/false values – that's what
booleans are for.
Variable phobia
Make liberal use of variables, especially to eliminate redundant and repeated expressions.
When you have identical expressions that are repeated throughout your method, you should strongly consider using variables to help eliminate that redundancy and to help make your code more concise.
For example, take the following:
public static void drawPixelX(
            Graphics g, 
            int startX, int startY, 
            int size, int pixelSize) {
    for (int i = 0; i < size; i++) {
        g.drawRect(
            startX + i * pixelSize, 
            startY + i * pixelSize,
            pixelSize,
            pixelSize);
        g.drawRect(
            startX + (size + 1) * pixelSize - i * pixelSize, 
            startY + i * pixelSize,
            pixelSize,
            pixelSize);
    }
}
While this method works correctly (it draws a pixelated "X"), it also has several repeated expressions that could be refactored out.
For example, the expression startY + i * pixelSize is repeated twice,
the expression i * pixelSize is repeated four times...
We can also refactor out the expression (size + 1) * pixelSize. Although
that expression isn't redundant, it does make that particular line longer.
Whenever you see these sorts of repeated expressions, you should refactor them out. For example:
public static void drawPixelX(
            Graphics g, 
            int startX, int startY, 
            int size, int pixelSize) {
    int maxWidth = (size + 1) * pixelSize;
    for (int i = 0; i < size; i++) {
        int step = i * pixelSize;
        int currentY = startY + step;
        g.drawRect(startX + step, currentY, pixelSize, pixelSize);
        g.drawRect(startX + maxWidth - step, currentY pixelSize, pixelSize);
    }
}
Now, our code is more concise. It's also more readable – by putting complex expressions into variables and giving them distinct names, it's easier for somebody to understand what each equation means.
Scope variables tightly
Scope your variables as tightly as possible – declare them within the smallest set of curly brackets as possible.
When coding, as a general rule of thumb, you want to try and arrange your code so that you minimize the number of factors you need to keep in your head at any given time.
The reason for this is that having to juggle and balance multiple factors adds cognitive load to your brain, making it subtly harder for you to be productive. In fact, it's just like juggling – almost everybody can easily juggle one ball at a time, most people can juggle two, but many people struggle to juggle three balls. The more things you have to keep track of, the harder it is to focus on any one thing.
When we declare variables in a wide scope (when we make variables available to a large segment of our code), we end up increasing the cognitive strain. For example, take the following code:
public static int findNumberOfDentists(Scanner names) {
    int total = 0;
    String name = "";
    while (names.hasNext()) {
        name = names.next();
        if (isDentist(name)) {
            total += 1;
        }
    }
    return total;
}
Currently, by placing both the total and name variable outside 
the loop instead of inside, we're implying that there's a good reason to do so –
perhaps we're about to use both variables to preserve information between each iteration?
While this is true of the total variable, it's untrue of the
name variable. The value of the name variable is unique per each 
loop, and so should be moved to inside it:
public static int findNumberOfDentists(Scanner names) {
    int total = 0;
    while (names.hasNext()) {
        String name = names.next();
        if (isDentist(name)) {
            total += 1;
        }
    }
    return total;
}
This makes it easy to reason about our code. I no longer have to worry if I need to 
preserve or do something with the previous value inside the name variable, and 
now know for certain that whatever I do with each name is unique per iteration.
Some beginners will wonder if doing this sort of repeated declaration is potentially inefficient. In reality, it turns out that it isn't – the Java compiler is intelligent enough to detect this sort of thing and automatically optimize it for us to ensure that we incur no penalty in performance.