I'll take a stab at this, hoping that any errors or omissions will be remedied by other members.
Final simply means that once the variable is assigned, it may not be reassigned. That is, it is a constant. This is useful for two reasons. The first is performance: the compiler can handle the code more efficiently if it knows that a particular variable can be treated as a constant. For example, it can rewrite
final double PI = 3.1415;
area = PI * r * r as
area = 3.1415 * r *r;
in all cases. This saves some steps.
The second advantage that strikes me at this moment (there may be others) is a code-safety thing. If you know that a given variable should not change in the course of the program, and you mark it final, you'll be warned if you inadvertantly reassign that variable. Of course, none of us would ever make such a mistake, but it's always nice to know that the person maintaining the code after you will be caught if they goof. :)
Static is a kettle of fish of a different color, to mix a metaphor.
Static tells the compiler that this variable pertains to the class, not to any instance of the object.
For example, if you have Circle objects, and for some reason you want your circles to have an internal value for pi (pi might change, after all, and you want to be ready for that!), you would probably want to make that a static rather than an instance field.
That way, when it's set, it applies to all circles.
For example:
public class Circle
{
static double pi = 3.1415;
double radius;
public Circle(double radius)
{
this.radius = radius;
}
public double area()
{
return radius*radius*pi;
}
public static setPi(double newPi)
{
pi = newPi;
}
}
This is a silly example, but in this case pi is the same value for all Circles. But since it's not declared final, I can re-set it. Perhaps I come up with a more accurate value, or I want to experiment with different values, or who knows why, but I can do that. When I call setPi(), following calls to area() for any Circle object will return a value based on the new value of pi.
One real-life use would be coordinating GUI values (colors, line widths, default values for drawing objects) by setting them as static variables in a utility class. If your user decides that selected items should be red, you can set them once:
GraphicsSettings.selectedColor = Color.RED;
and then render them that way by setting the pen color to GraphicsSettings.selectedColor if the object is flagged as "selected".
Does that help?