I have a problem with Java inner classes which I can't figure out. Suppose you have
class Outer
{
int outer = 0;
class Inner
{
int inner = Outer.this.outer; //(or just outer as it is not shadowed)
inner = 3; //or whatever, even outer = 3
}
}
Well, when I write the last assignment I get the compilation error
Syntax error on token ";", , expected
on the precedent line.
Why I cannot modify inner?
Thank you!
You cannot have a statement outside a method. One technique would be to use an instance initializer block:
class Outer
{
int outer = 0;
class Inner
{
int inner = Outer.this.outer; //(or just outer as it is not shadowed)
// instance initializer block:
{
inner = 3; //or whatever, even outer = 3
}
}
}
Alternatively, define a constructor:
class Outer
{
int outer = 0;
class Inner
{
int inner = Outer.this.outer; //(or just outer as it is not shadowed)
Inner() {
inner = 3; //or whatever, even outer = 3
}
}
}
You have to place the code in a method or in the constructor:
class Outer
{
int outer = 0;
class Inner
{
int inner = Outer.this.outer;
public Inner() {
inner = 3;
}
public increment() {
inner++;
}
}
}
Your assignment to inner must be inside a method or constructor, not "loose" in the class.
You need to include the line:
inner=3;
in a method in the inner class.
Yuo can not directly initialize inner = 3; outside method.Make sure that inner = 3; inside any method or constructor.
public Inner()
{
inner = 3;
}
Related
I'm facing java inner class and I'm having some trouble with outer variables visibility.
class A {
private int x = 5;
class B extends A{
public void fun(B b){
b.x = 10; //here
}
}
}
Why I can't do something like this (see the "here" tag) if there are no visibility restrictions between inner and outer class? I'm really not understanding these rules.
In your example the member variable x is not a property of class B so b.x = 10 makes no sesne, hence the error, it's nothing to do with visibility rules. Trying x = 10 works fine, which is a short-cut for A.this.x = 10 or super.x = 10.
Modifier private cannot be accessed in sub classes.
class A {
private int x = 5; // The issue is in `private` in this line
class B extends A{
public void fun(B b){
b.x = 10; //here
}
}
}
If you remove the modifier private and change it to default, public OR protected, you will be able to access the variable.
Please go through the link for better understanding.
UPDATE:
Remove extends keyword (Now Class B will not be a sub class but only an inner class), and the variable x will only be accessed using this OR super keyword. The usage is elaborated at link
you need know this three private,protected,default,publicaccess specifiers
private variables only can be modified in the itself class.not include subclass
default variables can be modified in same package.
protected variables can be modified in subclass and in same package and itself
public variables can be modified any where.
you can saw this on this link
beside.if you use this example ,this can modified your variables with usingsuperspecifiers to access your visiable
class A {
private int x = 5;
class B extends A{
public void fun(B b){
b.x = 10; //here error
super.x=1;//this is ok
}
}
}
this b.x = 10; //here error this problem is b is a parm of a methods not a member-variable or a super class variable.
This one is quite special. Inner class can access the private field of the outerclass. This can be shown with the fun(A) method
class A {
private int x = 5;
class B extends A{
public void fun(A a){
a.x = 5; //Valid since we are in the same class (inner-class can access private field)
}
}
Now, if you have a B parameter, this is a bit different because it will try to use the inheritence instead of the outer-inner link :
public void fun(B b){
b.x = 10; //Access using inheritence, not OK for private field
((A)b).x = 10; //Casting into A to be able to access the private field (just like fun(A).
}
Note that this is a problem because you update a reference receive in parameter, you can update the current inner instance easily
public void fun(){
x = 10; //OK : access to A.x from inner class
super.x = 10; //OK : same
this.x = 10; // KO : trying to access a private variable from B scope
}
I will be amazed if anyone can answer this question. I am a beginner struggling immensely with the syntax and logic of nested classes in Java. If you run the following program, 'a' will print instead of 'b'. Why?
class MainClass
{
public static void main(String[] args)
{
Outer OuterRefVar_a = new Outer('a');
Outer OuterRefVar_b = new Outer('b');
OuterRefVar_a.InnerTypeMember = OuterRefVar_a.new Inner();
OuterRefVar_b.InnerTypeMember = OuterRefVar_a.InnerTypeMember;
OuterRefVar_b.InnerTypeMember.set_innerChar_to_outerChar();
System.out.println(OuterRefVar_b.InnerTypeMember.innerChar);
}
}
class Outer
{
char outerChar;
Outer(char outerChar)
{
this.outerChar = outerChar;
}
class Inner
{
char innerChar;
void set_innerChar_to_outerChar()
{
innerChar = outerChar;
}
}
Inner InnerTypeMember;
}
That happens because while you have set the InnerTypeMember reference of object of A onto B..
OuterRefVar_b.InnerTypeMember = OuterRefVar_a.InnerTypeMember;
The inner object of A still has a reference to it's original Outer object A and will reference its member variables. Java implements inner classes by giving the object a secret reference to "Outer.this" which doesn't change simply by setting the InnerTypeMember on the other instance.
For example, if you had a InnerTypeMember variable within a completely different class, calling set_innerChar_to_outerChar() would still be expected to find Outer.outerChar on the object for which the inner class was original constructed.
I cannot access var variable from inner class method. but java is accessing to class variable instead of local variable. How can I access to local variable instead of class variable from inner class method ?
class Foo {
void test() {
int var = 3;
class Inner {
int var = 1;
void print_var_of_test() {
System.out.println(var); // this line prints 1 why ?
// I want this line to print var of test (3) function.
}
}
}
}
You cannot access a local variable defined in a method of the outer class from an inner class if the inner class defines already a variable with the same name.
You could use distinct names to distinguish them.
As workaround to keep the same variable names, you could change the signature of print_var_of_test() to accept an int.
In this way, outside the inner class you could pass the int var variable as the method is invoked.
class Foo {
void test() {
int var = 3;
class Inner {
int var = 1;
void print_var_of_test(int var) {
System.out.println("outer var=" + var);
System.out.println("inner var=" + this.var);
}
}
Inner inner = new Inner();
inner.print_var_of_test(var);
}
}
You do that by picking another name for either the local variable or the inner class variable.
Since the inner class and the method variable are defined in the same source method, you should always be able to change one of them. There is never a situation in which you don't have the permission/right/capability to change one but not the other.
What about naming inner class var as varInner if you want to compare between it and the original one?
I'd like to ask when it's required to explicitly write the name of the outer class when referring to the inner class or static nested class.
Ex:
class B {
static class Inner {
int a = 10;
}
}
class Test extends B {
public static void main(String[] args) {
Test t = new Test();
Inner obj = new Inner();
System.out.println(obj.a);
}
}
What I'd like to ask is under which circumstances it's needed to write:
B.Inner obj = new B.Inner();
instead of
Inner obj = new Inner();
For static nested classes (as G. Fiedler has mentioned in his answer) you can write new Inner() when you are within the scope of B.
You can also directly refer to Inner from within Test because it extends B.
In all other cases you need to say B.Inner and new B.Inner().
Inner classes - which are not static by definition - are initialized differently. Let's look at this example B:
class B {
public class Inner {
...
}
}
Inner classes are always tied to an instance of the outer class. That means that in this case there has to be an instance of B for us to be able to instantiate Inner. So let's do that:
B b = new B();
I'm by the way assuming we are currently somewhere outside of the scope of B
In order to create an instance of Inner we use our instance of B and write:
B.Inner inner = b.new Inner();
If we were inside of B (in a non-static method) we could, however, simply write
Inner inner = new Inner();
because we - or rather the compiler - know(s) that an instance of B has to exist for this inner to be tied to.
If you are inside the scope of class B then new Inner() can be used. Outside of class B new B.Inner() must be used.
I am relatively new to Java. I wanted to create an arraylist of an outer class and for each index of the outer class of the arraylist I want an arraylist of inner classes.
public Outerclass{
//Code Here
public InnerClass{
//Code Here
}
}
//My attempt at setting up the arrays
public ArrayList <Outerclass> olist;
public ArrayList <InnerClass> ilist;
olist= new ArrayList<Outerclass>();
for (int i = 0; i < 3; i++) {
Outerclass c = new Outerclass ();
ilist = new ArrayList<InnerClass>();
for(int j = 0 ; j < 4; j++){
InnerClass e = new InnerClass();
ilist.add(e);
}
olist.add(c);
}
Will this work?
First, I think that you should learn how to walk before you start running:
public Outerclass
should be
public class Outerclass
same with inner!
Second, all the last portion of your code should be in a main() method INSIDE Ourclass.
And third, no, you cannot use inner class like that, that's why these classes are inner. If you want to use inner classes from inside main() or from outside the outer class you have to use an instance of outer in order to access them, same like accessing any other instance member - you can't access it directly:
Outerclass oc = new Outerclass();
Outerclass.InnerClass in = oc.new InnerClass();
A litte refinement for answer #2, if you have nested classes for data storage, means that you have an constructor for the outer class that automatically generates a variable number of array members for the inner class like a tree structure. This solution is practically a workaround which uses one defined member - an ArrayList - which can be expanded later instead of a direct definition of an InnerClass[] array inside the OuterClass, which won't work if its not static.
public class OuterClass
{
private int NumberInnerClassInstances;
// ... other members of OuterClass
ArrayList<InnerClass> innerClassInstances = new ArrayList<>();
OuterClass( input vars ...) {
// calculate the NumberInnerClassInstances needed
for(int i = 0 ; j < NumberInnerClassInstances; i++) {
OuterClass.InnerClass in = this.new InnerClass(i);
innerClassInstances.add(in);
}
}
public class InnerClass
{
int icvar;
InnerClass(int i) {
//...construct the Inner Class Member #i
// can access the members of OuterClass
}
}
}
from outside, you can then access the InnerClass Instances with get:
oc = new OuterClass( vars ...)
var = oc.InnerClassInstances.get(i).icvar
Here are the key lines of your code:
Outerclass c = new Outerclass ();
InnerClass e = new InnerClass();
That won't work. You will get a compilation error.
Since InnerClass is an inner class, it needs to be instantiated in the context of an instance of its enclosing class (i.e. OuterClass). Like this:
Outerclass c = new Outerclass ();
InnerClass e = c.new InnerClass();
The c.new ... form is called a qualified class instance creation expression; see JLS 15.9.
Notes:
If the code that creates the inner class is in the context of an instance of the outer class (e.g. it is in an instance method of the outer class) then you don't need to qualify the new like that.
If the InnerClass is static this isn't necessary either. But then InnerClass is a nested class not an inner class ... according to the standard Java terminology.
An instance of an inner class can only exist within an instance of an outer class. (For a distinction between static and non-static inner classes, see this answer for more info).
What this means is that you create inner objects within outer objects. You can think of it as the outer objects creating and containing the inner objects (hence the name inner)
Here's an example:
import java.util.ArrayList;
public class OuterClass {
static ArrayList<InnerClass> innerClasses = new ArrayList<InnerClass>();
public static void main(String[] args) {
OuterClass oc1 = new OuterClass();
OuterClass.InnerClass ic1 = oc1.new InnerClass();
OuterClass.InnerClass ic2 = oc1.new InnerClass();
innerClasses.add(ic1);
innerClasses.add(ic2);
System.out.println(innerClasses.size());
}
class InnerClass {
}
}
Given that the InnerClass needs to maintain reference to the members of the OuterClass, I wonder why aren't you putting the ArrayList<InnerClass> inside OuterClass. If they're composed in that way it makes much more sense to have the list 'managed' by the OuterClass and just give it access methods to return the list of InnerClass instances etc.
So something like this:
public class OuterClass
{
private List<InnerClass> innerClassInstances = new ArrayList<>;
public void addInnerInstances(int count)
{
for(int j = 0 ; j < count; j++)
{
InnerClass e = new InnerClass();
innerClassInstances.add(e);
}
}
public List<InnerClass> getInnerClassInstances()
{
return innerClassInstances;
}
public class InnerClass
{
//...
}
}
//in your main class or wherever
List<Outerclass> olist;
olist= new ArrayList<Outerclass>();
for (int i = 0; i < 3; i++)
{
Outerclass c = new Outerclass ();
c.addInnerInstances(4);
olist.add(c);
}
You cannot create the InnerClass on its own with new as you're doing, you are saying that it needs to access the members of its OuterClass instance, and as you can see in your code, for each new InnerClass() you are never specifying in any way what is the OuterClass instance for it.