Method Local Inner classes program - java

I am just learning Java concepts.
Can anyone let me know why i am not able to run this program?
package innerClasses;
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
class Inner {
public void m2() {
System.out.println(i);
}
}
}
public static void main(String[] args) {
Test t = new Test();
Test.Inner in = t.new Inner();
t.m1();
}
}
Can anyone let me know why i am not able to run this program?

The most basic reason is because of scope. In order to do
Test.Inner in = t.new Inner();
Inner must be defined in Test, but it is instead defined in m1 scope.

The class Inner is declared inside the method m1(), what makes it not available outside this method.
Your code has to look like the following to be able to run, although it will not print anything...
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
}
class Inner {
public void m2() {
System.out.println(i);
}
}
public static void main(String[] args) {
Test t = new Test();
Test.Inner in = t.new Inner();
t.m1();
}
}
Replacing t.m1(); by in.m2(); will output 10.
EDIT
In case you have to create the inner class inside the method, make it like
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
class Inner {
public void m2() {
System.out.println(i);
}
}
// this is what makes it run
Inner myInner = new Inner();
myInner.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1();
}
}
to compile and run.
IMHO this is not a good way to go...

A method inner class is only visible to that method only so you can't use this at any other location.
for using this class you have to declare it outside of the method.

You cannot compile it as the scope of Inner class is the m1 method.
If you want to be able to create instances of Inner class you can define it directly inside the Test:
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
}
// On the Test class level
class Inner {
public void m2() {
System.out.println(i);
}
}
public static void main(String[] args) {
Test t = new Test();
Test.Inner in = t.new Inner();
t.m1();
in.m2(); // prints 10
}
}
Another feature provided by Java is to use anonymous classes. It can be created by implementation of some Interface:
// Define an interface to be able to implement it inside the method
interface Inner {
void m2();
}
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
// Implement interface and call method on it
// Functional style:
((Inner) () -> System.out.println(i)).m2();
// Legacy style:
new Inner() {
#Override
public void m2() {
System.out.println(i);
}
}.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1(); // prints 10 twice
}
}
or extending some class:
// A class we going to extend
class Inner {
void m2() {
System.out.println(11);
}
}
public class Test {
int i=10;
static int j=20;
public void m1() {
int k=30;
final int m=40;
// Extend inner class and call method on it
new Inner() {
void m2() {
System.out.println(i);
}
}.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1(); // prints 10, not 11
}
}
So the best way for you depends on what code design do you want to get finally.

Your class Inner is what the JLS calls a Local Class (14.3. Local Class Declarations).
The scope of a Local Class is defined as (6.3. Scope of a Declaration):
The scope of a local class declaration immediately enclosed by a block (§14.2) is the rest of the immediately enclosing block, including its own class declaration.
The scope of a local class declaration immediately enclosed by a switch block statement group (§14.11) is the rest of the immediately enclosing switch block statement group, including its own class declaration.
In your case it is declared in a block, which is the body of your method. So the scope where your class is visible is the rest of this method body.
As the type Inner is not visible in main(), you cannot use it there. You could create instances of it and use them within m1(), though.

The very basic reason for compile time error is "Scope".
As per your code, class Inner is defined inside method m1 (this class is called Local class/method local class),so if you observe the scope of method variable, its within the declared method only and we cannot access any method variable outside that method and this is reason, the scope of class Inner is limited to the m1 method
so if you want to instantiate class Inner and invoke its methods then you must do it in m1 method (in code , you are trying to create class Inner object outside method m1, which is not possible) hence the code would be
public class Test {
int i = 10;
static int j = 20;
public void m1() {
int k = 30;
final int m = 40;
class Inner {
public void m2() {
System.out.println(i);
}
}
Inner in = new Inner();
in.m2();
}
public static void main(String[] args) {
Test t = new Test();
t.m1();
}
}
some more info , the local classes can be used when any repeated functionality is required inside a method (as nested methods are not allowed in java, so we can create inner class) and off course if we are not interested to create class level method for example
class Outer {
public void cal() {
class Inner {
public void sum(int x, int y) {
System.out.println("sum : "+(x+y));
}
}
Inner i= new Inner();
i.sum(10, 20); //sum is repeatdly needed in between code
i.sum(100, 200);
i.sum(1000, 2000);
i.sum(10000, 20000);
}
}
public class TestClass {
public static void main(String[] args) {
new Outer().cal();
}
}

Related

How to access outer class method local variable in local inner class?

public class MyClass {
int x=9;
public static void main(String args[]) {
MyClass myClass = new MyClass();
myClass.test();
}
public void test(){
int x=10;
class InnerClass{
int x = 11;
void print(){
int x = 12;
System.out.println(x);
System.out.println(this.x);
System.out.println(MyClass.this.x);
System.out.println("MyClass => test() => x :" + "?");
}
}
InnerClass innerClass = new InnerClass();
innerClass.print();
}
}
How to call MyClass test() method local variable x inside the InnerClass print() method. What i can write in place of ? in last System.out.println() method in order to get the value of test() x.
Unfortunately in Java you can't.
The only way to access the x in MyClass::test would be to rename both variables in your inner class and in your inner class method into something else.
There is no need though to rename the outer class field x as InnerClass::print would consider the variable in the most-inner scope.
Although this snippet is for demonstration purposes, better practice would have you have different and more significant names for each variable.
That works fine for me:
public class Outerclass {
public static void main(String args[]) {
Outerclass outer = new Outerclass();
outer.outerMethod();
}
// method of the outer class
void outerMethod() {
int num = 23;
// method-local inner class
class MethodInnerClass {
public void print() {
System.out.println("This is method inner class "+num);
}
}
// Accessing the inner class
MethodInnerClass inner = new MethodInnerClass();
inner.print();
}
}
To print outer class variable use
MyClass.this.x

why can't i call variable from other class using object.variable_name?

I have just begun learning Java and I am trying to test stuff by myself. Below is the code where I am getting an error. I am trying to call the local variable in class B in class Demo using object of class B.
public class Demo {
public static void main(String args[])
{
B obj=new B();
System.out.println("printing that variable "+obj.a);
}
}
class B{
public void test()
{
int a=10;
}
}
Output:
Exception in thread "main" java.lang.Error: Unresolved compilation
problem: a cannot be resolved or is not a field at
Demo.main(Demo.java:7)
You can always call, but that needs to be in scope and when the current context have access to.
System.out.println("printing that variable "+obj.a);
You cannot do that since the variable a is local to the method test() and scope is restricted to that method only.
To access the way you want now, make it as a instance member.
class B{
int a; // instance member now
public void test()
{
a=10;
}
}
Now note that unless you call the method test() the default value is 0 only. Hence you might want to change your code as
public static void main(String args[])
{
B obj=new B();
obj.test();
System.out.println("printing that variable "+obj.a);
}
and if you don't want to call a method at all want to access a directly, you can do
public class Demo {
public static void main(String args[])
{
B obj=new B();
System.out.println("printing that variable "+obj.a);
}
}
class B{
public int a= 10;
}
Imp note :Always resolve all the compile errors before running your program :)
Because in
class B {
public void test() {
int a = 10;
}
}
a is local variable of test method. If what you are trying to do would be possible, what value should be used in scenario like
class B {
public void test1() {
int a = 10;
}
public void test2() {
int a = 20;
}
}
Should a come from test1 or from test2? For compiler this two methods are equally correct so it can't decide for you, which would cause the problem. Also lets not forget that method can have few variables with same name as long as they are in different scope, that is why we can have few for(int i...) methods (so from which scope you would want to use i).
Generally . operator is used to get access to member of class, not variable from method. So via object.member you may access to object.method() or object.field. If your class would look like
class B{
public int x;
public void test1() {
int a = 10;
}
}
you could use object.b since b is class B field.
Anyway if you want to get access to value of variable created and used only in method test, you could change this method to return this value. In other words you could rewrite it like
public int test1() {
int a = 10;
//... you can do something with a
return a;
}
Now in main method in Demo class you could use int result = obj.test();

Visibility of inner class variables

I have a code-
public class Hello
{
void create()
{
Inner obj=new Inner();
obj.r=100; //Able to access private variable x
obj.display(); //displays 100
}
class Inner
{
private int r=45;
void display()
{
System.out.println("r is : "+r);
}
}
public static void main(String[] args)
{
Hello ob=new Hello();
ob.create();
}
}
In the above code,by creating an instance of the inner class,we are able to access the private variable defined in that class.But this is not in the case of inheritance.Why it is so?For e.g.,in this code-
class One
{
private int x;
void getData()
{
x=10;
}
void display()
{
System.out.println("x is : "+x);
}
}
class Two extends One
{
int y;
void putData()
{
One o=new One();
o.x=13; //Error
}
}
public class File
{
public static void main(String[] args)
{
Two to=new Two();
to.putData();
}
}
What is the exact reason behind it?Thanks in advance...
See the Java Language Specification.
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Meaning that a top-level class can access the private members of it's nested classes.
Or said another way: Private means private to the top-level class and all it's nested classes, not private to the nested class itself.

How to access a method of Extended Class from nested class?

I have two nested classes inside a class with the outer class extending another class. The structure is something like this.
public class EXTENSION_CLASS
{
public int Get_Value()
{
return(100);
}
}
public class OUTER extends EXTENSION_CLASS
{
public static class NESTED1
{
public void Method1()
{
int value=0;
value=Get_Value();
System.out.println("Method1: "+value);
}
}
public static class NESTED2
{
NESTED1 Nested1_Instance=new NESTED1();
public void Method2()
{
Nested1_Instance.Method1();
}
}
public void run()
{
NESTED2 Nested2_Instance=new NESTED2();
Nested2_Instance.Method2();
}
public static void main (String[] args)
{
OUTER New_Class=new OUTER();
New_Class.run();
}
}
I'm expecting the output: "Method1: 100". But, am getting the output: "OUTER.java:16: error: non-static method Get_Value() cannot be referenced from a static context value=Get_Value();". How can i make this working?
Cheers !
Rajesh.
Remove the static modifier from the declaration of NESTED1 and NESTED2, like so:
public class NESTED1
If you want keep the nested classes static, you will have to create an instance of OUTER in the Method1() to access Get_Value().
public void Method1()
{
int value=0;
OUTER outer = new OUTER();
value=outer.Get_Value();
System.out.println("Method1: "+value);
}
You're trying to make a static reference to a non-static member.
This means that you're trying to access a instance member from a static member of the class.
To fix the issue, remove the static modifier from both the NESTED1 and NESTED2 clases.
Alternately, if you do not wish to remove the static modifier, you will have to create an object of the OUTER or EXTENSION_CLASS classes and then invoke Get_Value() using the object.
For example:
public void Method1()
{
int value=0;
EXTENSION_CLASS ext = new EXTENSION_CLASS ();
value=ext.Get_Value();
System.out.println("Method1: "+value);
}
OR
public void Method1()
{
int value=0;
OUTER outer = new OUTER();
value=outer.Get_Value();
System.out.println("Method1: "+value);
}
The error says every thing. You can not call non-static methods from static methods / class.
To make it work, Simply add static keyword to 'Get_Value' method in EXTENSION_CLASS.

Static block is not getting executed in case of anonymous objects

Why doesn't a static block in the class get executed when I don't create a reference variable for an object (anonymous) of that class?
For example, let us consider this simple class:
public class StaticDemo {
private static int x;
public static void display(){
System.out.println("Static Method: x = "+x);
}
static {
System.out.println("Static Block inside class");
}
public StaticDemo(){
System.out.println("Object created.");
}
}
Another class using it:
public class UseStaticDemo {
public static void main(String[] args) {
StaticDemo Obj = new StaticDemo();
Obj.display();
System.out.println("------------");
new StaticDemo().display();
}
}
Output:
Static Block inside class
Object created.
Static Method: x = 0
------------
Object created.
Static Method: x = 0
A static initializer block only runs once, when the class is loaded and initialized.
Also, static methods have absolutely no relation to any instances. Doing
new StaticDemo().display();
is pointless and unclear.

Categories