This is more of a hypothetical question but if I have some final called A and another final B that are both ints, I can't do this:
private final int A = B/2, B = (some kind of other derived number);
I am just wondering why. Any help would be awesome. NetBeans popped up an error on this and I just want to know why it is a problem.
PS-The error that popped up said "illegal forward reference".
You are accessing variable B before you declare it. That's the reason for "illegal forward reference".
Define variable B before A
private final int B = (some kind of other derived number), A = B/2;
Pretend you're the compiler:
private final int ok. Mr user wants a "const" int
A the variable is called A
= ...here comes the value
B/2 HUH? WHAT THE HELL IS B? NO ONE TOLD ME ANYTHING ABOUT B. STUFF YOU USER. I'M OUT OF HERE...
The existing answers don't answer the underlying question:
Why can I use methods that are defined later in my source file, but does the same with variables cause a forward reference error message?
The answer is found in the JLS, more specifically JLS $12.4.1
The static initializers and class variable initializers are executed in textual order, and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope (§8.3.2.3). This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.
This question was answered here. Basically it means that you are trying to use a variable that is not initiated.
Initialize B first, then use it to initialize A
private final int B = ?, A = B/2;
illegal forward reference in java
Your code isn't failing because A and B are final. It's failing because B isn't declared/initialized yet. If you declare it first, you'll be able to use them just fine.
For example,
private final int C = 5;
private final int B = C/3;
private final int A = B/2;
This is fine because B is declared first :)
"final" just means that you can't change the variable. So something like this won't work
private final static int C = 5;
private final static int B = C/3;
private final static int A = B/2;
public static void main (String[] args) {
A = 5;
}
because now we're trying to modify A which is "final"
Related
This question already has answers here:
Why isn't a qualified static final variable allowed in a static initialization block?
(2 answers)
Closed 8 years ago.
For example, consider code snap below:
public static final int a;
public static final int b;
static {
a = 8; // it's working
Test.b = 10; // compilation error Test.b cannot be assigned.
}
Why can't we use Test.b = 10; inside a static block of the Test class itself? Without the class name it's working fine.
Is there any reason behind this?
A static final variable must be initialized before use. It may be initialized either directly at declaration time, or in a static block.
But when you use class.var = x it is not seen as an initialization but as an assignation.
With a JDK 7, the error is cannot assign a value to final variable.
That explains why it works if you remove the final keyword
class Test {
static final int a = 2; // initialization at declaration time
static final int b;
static final int c;
static {
b = 4; // initialization in static block
Test.c = 6; // error : cannot assign a value to final variable c
}
...
}
EDIT
In the JLS the correct word for initialization is definite assignement
Extract from the JLS :
For every access of a local variable or blank final field x, x must be definitely
assigned before the access, or a compile-time error occurs.
Similarly, every blank final variable must be assigned at most once; it must be
definitely unassigned when an assignment to it occurs.
Such an assignment is defined to occur if and only if either the simple name of the
variable (or, for a field, its simple name qualified by this) occurs on the left hand
side of an assignment operator.
For every assignment to a blank final variable, the variable must be definitely
unassigned before the assignment, or a compile-time error occurs.
emphasize mine, but I think this is the real reason for the error.
The following code won't compile because the compiler isn't gauranteed that the data field f would be initialized. How do you fix this?
import java.util.Scanner;
public class Foo
{
private final int f;
/*constructor*/
public Foo()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
if(i == 5)
f = sc.nextInt();//error: variable f might be assigned in a loop
}
}
public Foo(int i)
{
j = i;//no problem
}
}
Isn't this kind of a glitch in the language because in my other constructor I can have f set to final and just because it's not done in a loop it works. I know the compiler (being dumb) sees a loop and thinks f will be reassigned, but the logic in the program ensures it only happens once. Is this an example of how Java "protects" the programer?
For everyone wondering why f was declared as final Netbeans suggested it, presumably when the code was much different.
private final int f;
↑
Remove the final keyword. The compilers doesn't know that the if will be satisfied only once and you'll get an error about trying to change f multiple times:
The final field f may already have been assigned
First of all, final field is field that you can not change value that is assigned to. In your case in each loop move you change that value, so it can not be compile. Remove final word before f.
public class Foo
{
private int f;
/*constructor*/
public Foo()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
if(i == 5)
f = sc.nextInt();
}
}
}
You .. don't.
I know the compiler (being dumb) sees a loop and thinks f will be reassigned, but the logic in the program ensures it only happens once. Is this an example of how Java "protects" the programmer?
This behavior, whether or not it "protects" the programmer, is a result of how the Java language is defined (per the JLS) and how the compiler correctly enforces the language specification.
4.12.4. final Variables:
A final variable may only be assigned to once .. It is a compile-time error if a final variable is assigned to unless it is definitely unassigned (§16) immediately prior to the assignment.
See Chapter 16. Definite Assignment which discusses the rules for this limited static analysis case in detail.
private final int f;
You use final for your declaration this will not allow to re-assign another value for f
A final variable can only be initialized once, either via an
initializer or an assignment statement.
Read more about final here
so just use
private int f;
When u declare any variable as final, the value of that value should not be changed.By the way is there any need to declare your variable as final?
Here is the catch, you can initialize any final instance on the same place or inside the constructor, but can not initialize inside method( METHOD ).
So you will say that I am initializing inside the constructor!! But the thing is that you are changing final instance variable's value multiple time inside for loop which compiler identifies and throws compiler error.
compiler inline final code like below.
private final int f = 10 //even if you initialize it inside the constructor only one time.
ex
public class Foo {
private final int f; // byte code becomes 'private final int f = 10' for each instance
Foo() {
f = 10;
}
}
Is there a difference between the following variable declarations?
Class A {
private int a;
A(){
a= 2;
}
}
VS
Class A {
private int a = 2;
A(){
}
}
Will garbage collection work any differently?
No there is no difference because the java compiler initialize "private int a = 2" inside the constructor internally. You can use java decompiler to confirm my above statement. So for both GC will work same.
There is no difference in the behaviour of your two initialisations. In the first example the a = 2 will happen just before the constructor code is called. If you made a final:
private final int a; //first example
private final int a = 2; //second example
Then you would see a difference between what you could do in the constructor:
A(){ //The blank final field a may not have been initialized for first example
}
A(){
a = 2; //The final field Apple.a cannot be assigned for second example
}
In both cases you are declaring int a as a member variable of the class. Whenever the class is instantiated, space will be set aside on the heap for that integer. However, the garbage collector only cares about whether or not there are any references to the containing object that has been instantiated. Regardless of what you do with the member variables, the object will stay in memory if there is a reference to it, after which point it's eligible for garbage collection.
However, perhaps you believe there should be a difference? Why is that?
In the following example, the variable b is declared final, but not static. That means it's a constant instance variable. However, because it's constant, none of the Passenger objects can change its value. So isn't it better to declare it static and make it a class variable, so that there is only one copy to be used by all instantiated objects?
class Passenger {
int a;
final int b = 0;
void drive() {
System.out.println("I'm driving!");
}
}
The purpose of final but non-static variables is to have an object-wide constant. It should be initialized in the constructor:
class Passenger {
final int b;
Passenger(int b) {
this.b = b;
}
}
If you are always assigning a constant literal value (0) to the final variable, it doesn't make much sense. Using static is preferred so that you are only having a single copy of b:
static final int b = 0;
BTW I don't think having default access modifier was your intention.
It depends on the purpose of b. Usually constants are there for a specific purpose. If you make it static you could accidentally change it in some instance of that class and that will affect all the others.
If you have multiple instances of Passenger class, I would go for making it static. While this has little benefit when talking about an int variable, this could save some memory if you have complex objects. This is because a static variable belongs to a class, not to an instance, thus memory space for it will be reserved only once, and it will be referred by the class object itself, not by the instances. Of course, you should be aware that having b as a static variable means that the changes made on this variable will be reflected on all the classes that access this variable, but since you made it final this won't be the case.
Note also that with the code you've written, classes in the same package as Passenger will be able to read the b value by accessing it via Passenger.b (if static).
In java, the static attribute basically means: associated with the type itself, rather than an instance of the type.
In other words you can reference a static variable without creating instances of that type... Whereas in the case of just using final you'd need to instantiate the class.
So, yes, to answer your question, I'd say that you're right. :)
A final primitive is the same as a static final primitive (except more efficient)
A final reference to an immutable object the same as a static final reference of the same.
A final reference to a mutable object is NOT the same as a static final reference of the same.
final int i = 0;
// same as
static final int = 0;
final String hi = "Hello";
// same as
static final String hi = "Hello";
final List<String> list = new ArrayList<String>();
// is NOT the same as
static final List<String> list = new ArrayList<String>();
The only time the last example is the same is when you have a singleton. It is fairly common for singletons to be written with a confusion of static and non static fields and methods as the difference is not obvious. :|
A final variable is defined when you need a constant, so you can assign a value just once.
Using static, instead, you are defining a variable shared by all the objects of that type (like a global variable) and it is not associated with a certain object itself.
can anyone tell me why I get this error?
illegal start of expression private int confirm;
and also
illegal start of expression private File soundFile3 = new File("merge.wav");
If I remove the word "private" the compiler doesn't show any errors.
The code is part of a public method.
Why?
Thank you.
the code is:
private int confirm;
confirm = JOptionPane.showConfirmDialog(this,
"Different sample size....",
"JOin", JOptionPane.OK_CANCEL_OPTION);
if (confirm != JOptionPane.OK_OPTION) {
return;
}
private File soundFile3 = new File("merge.wav");
private keyword cannot be used inside methods. it can be used to declare class fields or methods:
class Foo {
private int num; //private can be specified here
public void foo() {
int s = 1;
int k = num+s; //no private here
}
}
I guess you cannot put an access modifies except final in a method. It makes no sense to have a private modifier for a method level variable. As methods variables are created in their separate stack and destroyed when the scope is lost.
You should use access modifiers only on class members, not local variables.
Local variables are always visible only in the scope of the block where they were declared. So, if you declare a variable in your method, that variable will be visible only within that method. So, no need to use private there. I mean, no need even if you could.