I am learning Java right now and I am stumped on constants. It says in my book that they are good for declaring a variable that doesn't change. Example would be:
final double PI = 3.14159
How is this different from
double pi = 3.14159
How would "pi" change in a program?
The final keyword makes a variable unchangeable. This means that you can initialize it and you will never be able to change it.
final double PI = 3.14159
PI = 2; //You are trying to change the value of a constant, this will result in a compile-time error
To change a variable's value, just re-assign a value to that variable:
double pi = 3.14159;
pi = 2; //pi is not a constant, so its value can be changed
You sure can define pi as a standard double. In fact, if you're defining PI then it needs to be a double (or BigDecimal depending on your use).
The final keyword means this value will not change. It makes your code far more readable. Look at it like this:
final double PI = 3.14;
double a = Math.pow(PI * radius, 2);
You see how it's instantly obvious PI is the value you're using, as opposed to just 3.14 which can mean anything in any context?
Read langugage spec jls #4.12.4
A variable can be declared final. A final variable may only be assigned to once. Declaring a variable final can serve as useful documentation that its value will not change and can help avoid programming errors.
The reason to declare a constant is to ensure that it cannot be changed. If in your code, you attempt to change its value, you'll get an error (I think, bit rusty on Java, to be honest)
While, off the top of my head, I can't think of a situation where a constant couldn't be declared as a variable, it makes the code clearer and prevents you or another coder from accidentally changing a value that shouldn't be changed.
final means that value of variable can't be changed.
So the following code will not be accepted:
final double PI = 3.14159;
PI = 3.14; //error because PI is declared as final
final double PI = 3.14159
PI = 2; // Compile error
double pi = 3.14159
pi = 2; // Works fine
Final fields cannot be modified after they are initialized. They are initialized when the constructor is called, and keep their value for the rest of the object's lifecycle.
The point of making it a constant, is so you or an other programmer don't change the value in error. It's not can Pi change it's declaring to the compiler/interpreter that any any attempt to change it, is unacceptable.
once you discovered anonymous inner class or method implementation\overriding you will realize what your final variables are good for.
The basic means of final is to ensure the reference of the object won't change after object construction.
You can do something like this:
public class PI {
private double piValue;
public PI(double pi) {
this.piValue = pi;
}
public double getPi() { return piValue; }
public void setPi(double newPi) { piValue = newPi; }
}
//somewhere else
final PI myPi = new PI(3.14159);
//but you can change it via setter;
myPi.setPi(3.13);
//but myPi reference wont change!!!
Related
I have trouble understanding why double xx and yy are put final in the constructor. Why don't I just put them double xx and double yy. Why
do they have to be final? I guess the whole purpose of this is
creating an immutable object.
public class Point {
private final double x, y;
private double distance;
public Point(final double xx, final double yy) {
this.x = xx;
this.y = yy;
this.distance = -1;
}
}
There is no need for these parameters to be final.
There are two reasons to make parameters final:
To make use of them in an inner class declared in that function;
To prevent their values from being changed accidentally.
Clearly (1) doesn't apply.
(2) isn't necessary because it's such simple code, and you can see that it's not changing the parameters.
There is a school of thought which says that all parameters and local variables should be declared final as a matter of course, as it makes it easier to reason about the code, in the same way that using immutable types makes it easier to reason about code using them.
There is another school of thought which says that adding final everywhere is just unnecessary noise, and, if you are writing methods where you can't tell if the value is changing, your methods are too long.
Largely, making parameters and local variables final comes down to personal/team preference.
Declaring x and y variables as final solves the purpose (i.e. The value must not be changed later). There is no point in declaring the constructor's parameters as final.
This code compiles (using Java 8), giving the warning The assignment to variable value has no effect:
package test;
public class Test {
private static int value;
static {
value = Test.value;
}
public static void main(String[] args) {
System.out.println(value);
}
}
The program outputs 0 as expected. But why does the compiler allow this, what is the use case?
Because variables in Java have a default value which is initialized before any other initialization, unless the initialization happens directly when declaring the variable. Indeed value is 0.
The warning seems reasonable, assigning a variable to itself has no apparent effect but I don't think it should be considered a compile type error since it's syntactically and semantically correct.
If as variable is assigned to itself, the compiler issues a warning, as in the following:
int x = 2;
x = x;
This warning is usually a sign of a programming problem, so for itself it is a good thing to have it, yet in the case that the variable is volatile, which will be the ONLIEST useful Use Case I can think off, the warning is incorrect.
int y = 0;
volatile int x = 2;
y = 3;
x = x;
The java memory model enforces that every thread reading x and y in that order is guaranteed to see the value 3 for y. This is because assigning to x in one thread and reading x in the other establishes a happens-before-ordering.
The assignment has no effect to the value of the variable but it does have a huge effect for concurrency.
Note that in the example above the warning can be suppressed by using
x = x + 0;
Yet there is no such hack for references. One Use Case that will hit you is when trying to sync the content of a int[]. One thread reads a member:
myarray[3]
and another thread writes the member:
myarray[3] = 2;
Because array members themselfes cannot be volatile, you have to make myarray volatile and add the following to the writing thread:
myarrray = myarray;
Here is the code that keeps saying illegal start of expression:
public static conversionRate= 4.546;
Here is the full code:
/**
* Write a description of class VolumeConversion here.
*
* #author (Aneeqa Rustam)
* #version (07/08/2014)
*/
public class VolumeConversion
{
// instance variables - replace the example below with your own
/**
* Constructor for objects of class VolumeConversion
*/
public VolumeConversion()
{
public static conversionRate= 4.546;
znaslcmlkmlskm(String[]args)
//Declare the variable and constants
double litres= 0;
double gallon= 14;
//Perform the conversion calculation
litres= gallon* conversionRate;
//This is the output result that is going to be shown to the user
System.out.println("The number of litres in "+gallons+ "gallons is" +litres);
}
}
You need a type for the variable. For example:
public static float conversionRate = 4.546f;
You also want to place that outside of the constructor, as a class level variable.
Type is missing in the variable declaration
The variable conversionRate doesn't have a type in its declaration.
Possible solutions:
public static float conversionRate = 4.546f;
public static double conversionRate = 4.546;
Besides that you try to declare this variable in the constructor (a "method"). That does not work. It has to be declared within class and not in methods.
Well, this one is quite obvious - you haven't defined the datatype for your conversionRate variable. What you'd probably want to use here is the double datatype, but I'd also suggest looking into BigDecimals for further reference.
Code sample:
public static double CONVERSION_RATE = 4.546;
I would personally recommend against using the float datatype (as #MrTux recommended) in real life projects, as it tends to make your code clumsier (unnecessary casting & parsing) and has the obvious limitation of a restricted value range. The performance penalty that results from the use of double in place of float, however, is miniscule in most cases.
This fails to compile (with an illegal forward reference error), as one would expect:
class test {
int x = x + 42;
}
But this works:
class test {
int x = this.x + 42;
}
What's going on? What gets assigned in the latter case?
It is too difficult to discover and forbid all accesses to x during x's initialization. For example
int x = that().x; | int x = getX();
|
Test that(){ return this; } | int getX(){ return x; }
The spec stops at "access by simple name" and does not try to be more comprehensive.
In another section, "Definite Assignment", the spec does the similar thing. For example
public class Test
{
static final int y;
static final int z = y; // fail, y is not definitely assigned
static{ y = 1; }
}
public class Test
{
static final int y;
static final int z = Test.y; // pass... because it's not a simple name
static{ y = 1; }
}
Interestingly, "Definite Assignment" specifically mentions that this.x is equivalent to x
(or, for a field, the simple name of the field qualified by this)
this clause could be added to the section quoted by NPE as well.
the usage is via a simple name (or a simple name qualified by this)
But in the end, it is impossible at compile time to analyze all possible usages/accesses to a field.
Summary: Both initializers access a field that's yet to be initialized (and therefore still has the default value of zero). Since this is likely to be a programming error, the language bans some simple forms of such access. However, it does not ban more complex form.
The behaviour is compliant with the JLS, specifically §8.3.2.3. Restrictions on the use of Fields during Initialization
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:
The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
The usage is not on the left hand side of an assignment.
The usage is via a simple name.
C is the innermost class or interface enclosing the usage.
The first example satisfies all four conditions and is therefore invalid. The second example doesn't satisfy the third condition (this.x is not a simple name), and is therefore OK.
The overall sequence of events is as follows:
When an instance of a class is created, all fields are initialized to their type's default values.
Initializers are then run in textual order (from top to bottom).
Thus if an initializer refers to a field that appears later in the class definition (or to the field itself), it would see the default value of that other field. This is likely to be be a programming error and is therefore explicitly forbidden by §8.3.2.3.
If you circumvent §8.3.2.3 by, for example, using this. to forward-refer to a field, you'll see the default value (zero for int). Thus the following is well-defined and is guaranteed to set x to 42:
class test {
int x = this.x + 42;
}
In the first case compiler tries to evaluate expression 'x + 42' but fails because x is not initialized.
In the second case expression 'this.x + 42' is evaluated at runtime (because of 'this' keyword), when x is already initialized and has value 0.
I am trying to access a private final static double from another class.
Here is the class:
public class coolMath{
private final static double alpha = 5.87;
public coolMath(){
}
public static double calDistance(double x1, double y1, double x2, double y2){
double dist = Math.sqrt(Math.pow((x2-x1), 2) + Math.pow((y2-y1),2));
return dist;
}
}
I need to access the variable alpha in another class. Is this possible? Does something need to happen in the constructor to make it available? Any ideas?
Either make alpha a public field or provide a public static double getAlpha() that returns it.
If you make the field public, you access it like so double a = coolMath.alpha.
Otherwise, double a = coolMath.getAlpha();
I strongly suggest you go through java modifiers again.
This could technically be possible through some esoteric reflection methods, but I highly discourage it. It's better to change the visibility of your alpha variable or write some method that returns it (or perhaps sets it, if you need that also (but not if your var is final)).