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.
Related
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?
This question already has answers here:
Java inner class and static nested class
(28 answers)
Closed 5 years ago.
I used the following piece of code, which gave me an error at the point indicated:
class LinkedList{
class pair{
Integer petrol;
Integer distance;
public pair (Integer a, Integer b){
petrol = a;
distance = b;
}
}
public static void main(String args[]){
pair[] circle = {new pair(4,6), new pair(6,5), new pair(7,3), new pair(4,5)}; // error at first element of array circle!!!!!!!
}
}
I then rectified it to this and the error dissapeared!
class LinkedList{
static class pair{ // changed to static!!!
Integer petrol;
Integer distance;
public pair (Integer a, Integer b){
petrol = a;
distance = b;
}
}
public static void main(String args[]){
pair[] circle = {new pair(4,6), new pair(6,5), new pair(7,3), new pair(4,5)}; //error gone!
}
}
My question is why did the error even appear in the first place?
ERROR: No enclosing instance of type LinkedList is accessible. Must
qualify the allocation with an enclosing instance of type LinkedList.
In case 1, pair is a member of LinkedList. Meaning that you can access pair through only LinkedList and not directly just like any varaible or method of that class.
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
However in case 2, pair is just like any another top level class and just grouped to maintain the relation. It is not at all a member of outer class. You can access it directly.
Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
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 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;
}