local variable access in 'method local inner classes' - java

What is the internal reason due to which within method local inner class we can only access final or effectively final local variables of the method in which that inner class is declared?
Please see below example.
class Test{
int i = 10;
static int j = 20;
public void m1(){
int k = 30;
//k=40;
final int m = 40;
class Inner{
public void m2(){
System.out.println("value of i = " + i + " value of j = " + j + " value of k = " + k + " value of m = " + m);
}
}
Inner i = new Inner();
i.m2();
}
public static void main(String[] args){
Test t = new Test();
t.m1();
}
}
If I try to change the value of variable k (line commented in source code), then there will be compiler error stating "local variables referenced from an inner class must be final or effectively final"
Also in java versions lower than 1.8, local variables must be explicitly defined as final if you want to access that variable within method local inner class.

Related

java: illegal forward reference for both static ans instance variable

I am having the following problem:
public class IntitializeTest {
static {
System.out.println("Static Initializer");
i = 1;
k = 2;
System.out.println(i+" "+k) // illegal forward reference;
}
static int i;
static int k;
{
System.out.println("Instance Initializer");
thisString = " empty ";
b = 0;
System.out.println(thisString+b) // illegal forward reference;
}
String thisString;
int b;
}
what would be the order of initialization here? for Eg: I am able to initialize before declaring the variable "b", but not able to print it because of the error.
Java docs mentions the left-hand side rule, How does this apply here.
Thanks in advance

Access shadowed variables from superclasses

From this anwser, he said that we can access shadowed variables from superclasses of superclasses by casting this, but it doesn't work for method calls because method calls are determined based on the runtime type of the object.
However, why can I still get shadowed variables without explicitly casting the passing parameter types?
interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 implements I { int x = 2; }
class T3 extends T2 implements I {
int x = 3;
void test() {
System.out.println("((T3)this).x=" + ((T3)this).x + "; getT3(this)=" + getT3(this));
System.out.println("((T2)this).x=" + ((T2)this).x + "; getT2(this)=" + getT2(this));
System.out.println("((T1)this).x=" + ((T1)this).x + "; getT2(this)=" + getT1(this));
System.out.println("((I)this).x=" + ((I)this).x + "; getI(this)=" + getI(this));
}
public static void main(String[] args) {
new T3().test();
}
int getT3(T3 t3) { return t3.x; }
int getT2(T2 t2) { return t2.x; }
int getT1(T1 t1) { return t1.x; }
int getI(I i) { return i.x; }
}
which produces the output:
((T3) this).x = 3; getT3(this) = 3
((T2) this).x = 2; getT2(this) = 2
((T1) this).x = 1; getT1(this) = 1
((I) this).x = 0; getI(this) = 0
If I understand his anwser correctly, shouldn't getT3, getT2, getT1 and getI methods all return 3?
Because the method signatures expect I, T1, T2, and T3, the parameters are treated as those types when returning i.x, t1.x, etc.
So calling getT2(this) is essentially equivalent to calling getT2((T2) this).
That's why they would not all return 3, but rather the value of x for that specific type.
I'm not sure I've explained this well, but because T3 extends T2, it is implicitly cast to an instance of T2 when passed to getT2.

Why won't variabes from other methods return to the main method? (more inside)

The purpose of this program is to print
the number of solutions and the solution(s) to a quadratic function,
entered by the user.
The problems here is that I get errors for having private variables,
why is this? Also for my constructor it states that my variables cannot be resolved even though
they are established in the main method. Finally, my variables will pass to the main method or to the "toString" method for use
in the main method.
This is for a school assignment and my professor requires that I use the "toString" method as well as have private variables. I apologize in advance for any formatting mistakes and for the large question, for I am new
to this site.
import java.util.Scanner
public class QuadraticSolver
{
private static Scanner in;
public static void main(String[]args)
{
QuadraticSolver qs = new QuadraticSolver();
in = new Scanner(System.in);
private double a;
private double b;
private double c;
System.out.println("Enter coefficients for quadratic function. ");
a = in.nextDouble();
b = in.nextDouble();
c = in.nextDouble();
qs.getRoot1(a,b,c);
qs.getRoot2(a,b,c);
qs.numOfSolutions(a,b,c);
System.out.println("Your quadratic function is " + a + "x^2 + " + b + "x + " + c);
System.out.println(qs.toString());
}
public QuadraticSolver()
{
a = 0;
b = 0;
c = 0;
}
public double getRoot1(double a,double b,double c)
{
private double root1;
root1 = (-b + Math.sqrt(Math.pow(b,2) - 4*a*c)) / (2*a);
return root1;
}
public double getRoot2(double a,double b,double c)
{
private double root2;
root2 = (-b + Math.sqrt(Math.pow(b,2) - 4*a*c)) / (2*a);
return root2;
}
public int numOfSolutions(double a,double b,double c)
{
private int sol = 0;
private double d;
d = Math.pow(b,2) - 4*a*c;
if(d > 0)
{
sol = 2;
}
else if(d == 0)
{
sol = 1;
}
else if(d < 0)
{
sol = 0;
}
return sol;
}
public String toString()
{
return "There are(is) " + sol + " solution(s). x = " + root1 + " x = " + root2;
}
}
You should move the variables to the class level:
public class QuadraticSolver {
private double a;
private double b;
private double c;
...
}
Next, you need to access the variables that belong to the object qs:
public static void main(String[]args)
{
QuadraticSolver qs = new QuadraticSolver();
in = new Scanner(System.in);
System.out.println("Enter coefficients for quadratic function. ");
qs.a = in.nextDouble();
qs.b = in.nextDouble();
qs.c = in.nextDouble();
...
}
And finally, you should remove the variables from the methods getRoot1(), etc. This is because each method can access the variables a,b,c belonging to the object itself. Thus:
public double getRoot1()
{
double root1 = (-b + Math.sqrt(Math.pow(b,2) - 4*a*c)) / (2*a);
return root1;
}
And at the call sites:
public static void main(String[]args)
{
...
double root1 = qs.getRoot1();
double root2 = qs.getRoot2();
int numsol = qs.numOfSolutions();
...
}
Private instance variables belong to a class. When you create an object that is an instance of a class, the object may have instance variables that belong to the object; if you create multiple instances of a class, each of those instances (objects) has its own set of instance variables. You declare those in the class:
public class QuadraticSolver
{
private static Scanner in;
private double a; // instance variables
private double b;
private double c;
Now, to access those variables, you need to have an object. If you're in a non-static method inside the class, or in a constructor for the class, the method will work with an object called this, so you could say this.a or just a to get at that variable. If you're outside the class, or in a static method in the class (including main), you need to tell it what object you're working with. In your program, your main method has an object qs that is a QuadraticSolver, and you can get at that object's instance variables by saying qs.a, qs.b, etc.
Variables declared inside a method are local variables. They're for use only within that method. They don't declare instance variables for an object. You can't use the keyword private on them, because that keyword is only for instance variables (and other things that aren't variables). You can't use the variables outside that method. If you declare them in an inner set of curly braces, you can't use them outside the curly braces. If you declare a local variable that's the same name as an instance variable, there's no connection between the two.

Java: Issue with classes

I have following code
class Demo {
static int a = 0;
static int b = 1;
static {
a = ++b;
}
void gam(int x) {
a = a * x;
b = b * x;
}
}
class Test {
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = new Demo();
d1.a++;
d2.a--;
System.out.println(d1.a + " " + d1.b + " " + d2.a + " " + d2.b);
}
}
But I can't figure out why d1.a is 2. Shouldn't it be 3? Since a=++b makes it 2 and d1.a++ makes it 3?
The variable a is static, so there is only one a for all instances of Demo. It starts off as 0, and the static initializer sets it to ++b, or 2. Then, d1.a++ increments it to 3, but d2.a-- decrements the same a back down to 2.
d1.a is a static member field, so it should be accessed not via the instance. It should accessed via: Demo.a.
And by the way, d1.a and d2.a refer to the same static member field, so the increment of a in d1.a++ is "roll-backed" with the decrement: d2.a--.

Method Local Inner Class Member scope access

How do I access the method variable having the same name as the inner class member instance or method local variable of the inner class?
class A{
int a = 10; //1
public void someMethodA(){
final int a = 20; //2
class B{
int a = 30; //3
public void someMethodB(){
int a = 40; //4
System.out.println("a = "+a); //access 4
System.out.println("a = "+this.a); //access 3
System.out.println("a = "+A.this.a); //access 1
System.out.println(?????); //how do I access value of a i.e 2
}
}
}
}
No. You can't do that. The reason being, the variable a in position 2 is a local variable, which can only be accessed with it's simple name, in the enclosing scope. From JLS §6.4:
A local variable (§14.4), formal parameter (§8.4.1), exception parameter (§14.20), and local class (§14.3) can only be referred to using a simple name (§6.2), not a qualified name (§6.6).
Now, this clears that you can only access that variable with just a. But, you have another variable in method local class B which shadows that local variable a in position 2, which is again shadowed by local variable in position 4.
Now in print statement, a would access the variable from nearmost enclosing scope, that is local variable at position 4. If you remove that variable, it will print the variable at position 3. And then if you remove it, it will print the variable at position 2.
So, the point is, there is no way to access the local variable a at position 2, because that is shadowed.
that code will never output those statements, here is an example from Sun that should explain things :
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
I am not sure, what you actually mean, but you access a class member with the same name as a local variable with the same name like this:
public class A
{
int a = 10;
public void someMethodA()
{
int a = 5;
this.a = 20; //change the member a from 10 to 20
a = 30; // changes the local variable, which is only known in this method to 30
}
}
Typically this pattern is used in constructors, to name the params the same as member variables, for example:
class Foo
{
private int bar = 10;
private string fooBar = 20;
public Foo(int bar, string fooBar)
{
this.bar = bar;
this.fooBar = fooBar;
}
}

Categories

Resources