How to create object of second level inner class? [duplicate] - java

This question already has answers here:
What causes error "No enclosing instance of type Foo is accessible" and how do I fix it?
(11 answers)
Closed 8 years ago.
I'm new to Java.
My file A.java looks like this:
public class A {
public class B {
int k;
public B(int a) { k=a; }
}
B sth;
public A(B b) { sth = b; }
}
In another java file I'm trying to create the A object calling
anotherMethod(new A(new A.B(5)));
but for some reason I get error: No enclosing instance of type A is accessible. Must qualify the allocation with an enclosing instance of type A (e.g. x.new B() where x is an instance of A).
Can someone explain how can I do what I want to do? I mean, do I really nead to create instance of A, then set it's sth and then give the instance of A to the method, or is there another way to do this?

Outside the outer class, you can create instance of inner class like this
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
In your case
A a = new A();
A.B b = a.new B(5);
For more detail read Java Nested Classes Official Tutorial

In your example you have an inner class that is always tied to an instance of the outer class.
If, what you want, is just a way of nesting classes for readability rather than instance association, then you want a static inner class.
public class A {
public static class B {
int k;
public B(int a) { k=a; }
}
B sth;
public A(B b) { sth = b; }
}
new A.B(4);

Interesting puzzle there. Unless you make B a static class, the only way you can instantiate A is by passing null to the constructor. Otherwise you would have to get an instance of B, which can only be instantiated from an instance of A, which requires an instance of B for construction...
The null solution would look like this:
anotherMethod(new A(new A(null).new B(5)));

Related

how java constructor does work? [duplicate]

This question already has answers here:
Does polymorphism apply on class attributes in Java?
(8 answers)
Closed 4 years ago.
I have the following program :
class A{
int b = 50;
}
class B extends A{
int b = 20;
}
public class Maini{
public static void main(String[] args){
A a = new B();
System.out.println(a.b);
}
}
and the result is 50 and I would like to know why?
before I run the code I am pretty sure that the result should be 20.
This has nothing to do with how constructors work.
Note that the member variable b in class B does not override the member variable b in class A. Only non-static, non-private methods can be overridden. Member variables cannot be overridden.
If you have an instance of class B, then it actually has two member variables called b: one in the superclass (A) part of the object, and one in the subclass part (B).
The reason that you see the value 50, which is the value of b in the A part of the object, is because the variable a in the main method is of type A. If you change this to B, you'll get 20:
B a = new B(); // instead of A a = ...;
In the statement
A a = new B();
You are calling Bs constructor in an object of type A
In your program, you have given no constructor to B, so it looks to A.
In A, the value of int b is 50 and an object is of type A, hence the value is chosen as 50
If you had a constructor in B e.g.
B() { b = 20;}
the value would be 20.
You think that you are creating a B but you have not written any constrcutors for the class B so it looks to the super() constructor which is it's parents (A). So you now have an object of A. If you are curious about why A's object isi being created while there is no constructor to it too. A calls to it's super constructor too which is Java's Object Class's constructor.
I hope that I could make this point clear.
use a intellitrace enabled IDE for better experience of coding.
1st of all you'l hav a default constructor if you are not imposing on it.
Secondly you are defining an object of type 'A' not 'B'. if you want the output as 20 then you hav to include this B() {int b = 20;}.
Here in this code Sniplet there is no constructor in Any class.
So JVM will create no argument default constructor in all classes.
While you are Running this then .
In the below code you
a is referring class A and having object of class B
A a = new B();
So here the Object a will have class A 's variable value.
and Class B object value as its calling Class B 's default constructor(new B();)
If Class A and B have same Method like below Example:
class A{
int b = 50;
void method(){
System.out.println("Method of A class");
}
}
class B extends A{
int b = 20;
void method(){
System.out.println("Method of B class");
}
}
public class Maini{
public static void main(String[] args){
A a = new B();
System.out.println(a.b);
a.method();
}
}
Then a.method() will print
50
Method of B class
as a is have Class B 's object.
When you write A a = new B() the object a is type A. This is why you're getting b = 50. If you want to get b = 20, you need to declare a as a B class
Hope it's clear enough.
Best

why can not access child fields using parent reference

class A {
int super_var = 1;
}
class B extends A {
int sub_var = 2;
}
public class Demo{
public static void main(String []args){
A a = new B();
System.out.print(a.sub_var); //compile error
}
}
why this will end with a compile error ? reference (a) referencing to an Object of B it has sub_var so why is it restricted ? why reference (a) can access only the fields in A ?
Let's say you have these classes:
public class Animal() {
// ...
}
public class Fish extends Animal() {
public void swim() {...}
}
If you declared an Animal:
Animal x = new Fish();
and you called the swim() method
x.swim();
Would you expect it to work? I don't think so, because not every animal can swim. That's why you have to explicitly specify that the animal x is a Fish:
((Fish) x).swim();
In your case, if you wanted to call that method, you should specify (technically, it's called cast) the type:
System.out.print(((B)a).sub_var);
Note:
This works similar for methods and variables. I used a method in the example since it's more illustrative.
Edit:
Let's see this example:
Animal x;
if (some_condition)
x = new Fish();
else
x = new Cat();
x.swim();
This restriction exists, because Java won't know if, at execution time, the object assigned to x will have the method swim(). So to avoid this, you have to cast to the respective type to call a method that doesn't exist in superclass.
At first it does sound like it should work. (And in some languages it probably does.) But think about this example:
public class Demo {
public static void main(String []args){
A a = new B();
print( a );
}
public static void print( A arg ) {
System.out.print(arg.sub_var); //compile error
}
}
This functionally does the same thing but the print is in another method. If your version worked, this one could be expected to work too.
But what if someone then does this?
Demo.print( new A() );
This should fail because A doesn't have a sub_var. It would have to throw some kind of runtime error instead.
So the design decision in Java was not to allow this and if you declare a local variable/field/method parameter as type A, then you can only access things that every object that is either A or a subclass is guaranteed to have.
If you want to access more, you need to cast it to the subclass, which will throw an exception if you try it on an object that doesn't fit.
A a = new A();
System.out.print(((B)a).sub_var); //ClassCastException is thrown here
You can not access B members with the reference of Parent object A.
Instead change your println statement like below to access,
System.out.print(((B)a).sub_var);
Is there a variable called sub_var in the parent class ? No. That is why you get the error -
sub_var cannot be resolved or is not a field
See this
System.out.print(a.super_var); //okay
System.out.print(a.sub_var); //compile error
you create an object of type B and assign it to a variable of type A. The type A does not declare sub_var. This field is declared only in type B. the compiler only sees what is declared in type A, although the variable is instantiated to an object of type B.
If you want to access sub_var you would have to cast a to B.
System.out.println( ((B)a).sub_var);
The sub_var is in class B, so you can only access through a reference of class B. To the compiler A a = new B(); means a is an instance of class A.

Are static class members static in Java?

In the below code, are b and show inherently static?
public class A {
public static class B {
private int b = 0;
public void show() {
System.out.println(b);
}
}
}
No they aren't static. You need to create an instance of B to access them.
The static keyword in your code example means that instances of B can be created without an instance of A.
If B was not static:
Instances would have an implicit reference to an instance of A.
The only way to create them would be to use new B() inside class A, or using syntax like new A().new B().
Methods in B can refer to A.this (the implicit reference to an instance of A).
Methods in B can refer to A.this.someField (using that implicit reference).
Methods in B can call instance (non-static) methods in A.
However, because B is static:
Instances do not have a reference to an instance of A - you don't need an A to create a B.
Instances can be created using new A.B() (or just new B() from within in class A)
Methods in B cannot refer to A.this.
Methods in B cannot access fields in A (unless passed in as a parameter).
Methods in B cannot call instance (non-static) methods in A.
They are not static. They are instance fields in B.
Meaning you need to have an instance of B to get/set them.
B is static in A but that does not make those fields of B static.
You can create many instances of B without any reference to A.
So B is static class in A but the same is not true for B's instance fields.
The static keyword has two meanings that are actually quite different and that can be confusing.
Static on a variable/method means that it exists at the class level, not the instance level. This means that you only have one copy of that variable/method no matter how many instances of the class you create.
Static on an inner class though just means that the class does not depend upon its outer class. In your example you can create a new B() without having an A. If you didn't have the static keyword on the class you could not create a new B() unless it was within an instance of A.
B is a static inner class of A.
Need to instantiate B.
A.B innerObject = new A.B();
innerObject.show();
The identifier static has a specific purpose here that many people don't immediately grasp. I'm going to take your code and change it a bit.
public class A {
private int a;
public A(int a) {
this.a = a;
}
public class B {
public void show() {
System.out.println(a);
}
}
}
Now, what's happening in class B? Because B is a non-static class, it has access to other non-static members in class A. Essentially, it states that every class A object has their own flavor of class B objects, even thought they are functionally the same. For us to get that same behavior if B was a static class:
public class A {
private int a;
public A(int a) {
this.a = a;
}
public int getA() { return a; }
public static class B {
public void show(A a) {
System.out.println(a.getA());
}
}
}
Here, this implies that the flavor of B objects doesn't change depending on which A object created it. The B class is static so that it cannot access non-static members of the A class object that created it and must access those members explicitly from whichever A object it wants to interact with.
In the previous implementation, a B object would seamlessly access fields and non-static methods of the A object that created it.
These are two different behaviors and often it's clear exactly which one fits your objective.

Call constructor within constructor with self(this)-parameter

I need to link an object of type B to any instance of type A (circular dependencies). I could also declare another method, which must be called after the constructor of A and link a new B to an A-instance. What I want to achieve is not having to call such a method manually. This is the sample code:
public Class A{
B b;
public A(){
b = new B(this); // this does not work,
// as this references an object that has not been created yet
}
}
public Class B{
A a;
public B(A a){
this.a = a; //or something else
}
}
I commented the problematic line. I also understand why it can't work. What I need to know is, if there is a well-known design pattern to avoid this problematic? Or should I just redesign my class model, putting anything in B to A? Any suggestions?
It does work. It's problematic in that it exposes an object before it's been fully initialized (so if the B constructor calls methods on the parameter, for example, that could be a bad thing), but it does work. The reference B.a will be a reference to the instance of A that's been/being constructed.
I would recommend trying to avoid the cyclic reference where possible, but where the alternative is even worse, the code you've given will work.
Using this approach is not recommended and possibly create runtime exception because the object is not fully initialized. We can take simple scenario as:
public class A {
B b;
String s;
public A(){
b = new B(this); // this does not work, as this references an object that has not been created yet
s = "print me";
}
}
public class B {
A a;
public B(A a){
this.a = a; //or something else
System.out.println(this.a.s); // will same as a.s;
}
}
It will output null because a partially initialized reference is copied to constructor. This code compiles because compiler doesn't find anything missing in code as all appropriate references and variable are there.

Naive Inheritance Problem - Java

G'day people,
I am feeling embarrass by asking such a naive question. But I can't understand one thing,
I have Inheritance structure like this,
B extends A, code I have wrote is as below,
Class A
public class A{
private int pos = 0;
public A(){
this.pos = 12;
}
public int getPos(){
return this.pos;
}
}
Class B
public class B extends A{
int spec = 15;
public B(){
super();
}
public int getSpec(){
return this.spec;
}
}
And I have one more class to test, Which will get us to my question.
Class Test
import java.util.*;
public class Test{
public static void main(String[] args){
B a = new B();
ArrayList<A> c = new ArrayList<A>();
c.add(a);
System.out.println(c.get(0).getPos());
System.out.println(c.get(0).getSpec());
}
}
Question : Now I am creating an instance of B, Which means I can access to my parent class's method getPos() and B's own method getSpec(). But if I create ArrayList with type A(...B is type A too, as it extends A...) and add my B's instance it losses it's ability to access it's own method. What am I doing wrong? Does ArrayList implementation is casting my B to A internally?
Note : My basic understanding of inheritance is parent cannot access
child's method except they are protected. But Child can access their
parent class's method.
There's no casting involved. What you're doing is no different from this:
A bAsA = new B():
While the object referred by bAsA is truly a B object, it is held by an A variable and thus only A methods are available (unless you explicitly cast it as a B variable).
Since your ArrayList is an ArrayList of A, each item in the ArrayList is treated as an A variable and only A methods are available.
Does ArrayList implementation is casting my B to A internally?
No. There is no "internal casting." You, the programmer, have told the compiler it's a list of A.
You have declared the List as List<A>, which you can read as "a list of A". Since all B are A, you can add any B to a List<A>. On retrieval, however, you're only guaranteed to get back an A, not a B — because it's a List<A>, remember — so the compiler treats everything that comes out of the list as an A, even if (at runtime) it's an instance of B.
In addition to the answers provided by #Matt Ball and #Hovercraft Full Of Eels, you can avoid having to explicitly cast by declaring methods implemented by the subclass as abstract methods in the superclass.
public abstract class A{
.
.
public abstract int getSpec();
}
EDIT-
As mentioned by #Kublai Khan, it is necessary to then make the superclass an abstract class.

Categories

Resources