Two questions on inner classes in Java (class A { class B { } }) - java

Sorry for the bad title, but I couldn't think of a better one.
I'm having a class A and a class B which is kind of a sub class of A, like so:
(Is there actually a correct name for it? Isn't "sub class" reserved for inheritance?)
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
B b = a.new B();
A c = ??? b ??? // get "a" back
}
}
From B every property of A can be accessed, therefore both, a.i and b.i, return 0. Now, I'm wondering whether it's somehow possible to retrieve the original object of type A out of b, as b contains everything that a contains? Simple casting apparently doesn't do the trick.
Second one:
class A {
void print() {
System.out.println("This is class A.");
}
class B {
void print() {
// <--- How to access print() of class A (like this.A.print() or smth)?
System.out.println("This is class B.");
}
}
}
You could alternatively also provide me with some good resources on this topic, as I've been too stupid to find a good one so far.
Thanks in advance. :)

There doesn't seem to be a way to access the outer class from outside. But you can do it like this:
class A {
int i = 0;
class B {
final A outer = A.this;
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = b.outer // get "a" back
}
}
ClassName.this will be the instance of the outerclass associated with the instance of an inner class.

You can access it with the ParentClass.this syntax from within the inner class.
e.g.
public class Outter
{
class Inner {
public Outter getOutter()
{
return Outter.this;
}
}
public Inner getInner(){
return new Inner();
}
}
class Runner{
public static void main(String[] args){
Outter out = new Outter();
Outter.Inner inner = out.getInner();
System.out.println(inner.getOutter().toString());
}
}

[Edit: My answer is appropriate for C# programmers, but I can't guarantee that its applicable to Java.]
B is an inner class, not a subclass of A. Additionally, B does not hold an instance of A, so your code as is cannot return any instance of A.
You need to restructure your classes as follows:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
}
Now your B class has a field 'Parent' which returns its parent. You can use these classes as follows (this is C# syntax, because I don't know if Java has a different syntax for instantiating inner classes):
public static void Main(String[] args)
{
A parent = new A();
A.B child = new A.B(child);
A backToParent = child.Parent;
}
Of course, creating your B class in this way seems little funny: technically, you can pass in any parent. It would probably be better to rewrite your A class with a method which returns a B:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
public B getChild()
{
return new B(this);
}
}
public static void Main(String[] args)
{
A parent = new A();
A.B child = A.getChild();
A backToParent = child.Parent;
}

this seemed to work for me
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = (A)b.getClass().getDeclaredField("this$0").get(b);
}
}

Related

In Java, is there a way to get access to an object from inside an object created/used by that class?

Let's say I have a class that instantiates and uses another class. From the second class, is it possible to gain access to the first one?
For example:
public class A {
public B obj = new B();
public void something() {
b.somethingElse();
}
}
public class B {
public void somethingElse() {
A owner = getCallingObject();
//the object of class A that called b.somethingElse() is now stored in owner
}
public Object getCallingObject() {
// ?????
// returns the A that instantiated/owns this B
}
}
I know how to get the Class of that object using something like this:
private String getCallerClassName() {
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
for (int i = 1; i < stElements.length; i++) {
StackTraceElement ste = stElements[i];
if (!ste.getClassName().equals(B.class.getName()) && ste.getClassName().indexOf("java.lang.Thread") != 0)
return ste.getClassName();
}
return null;
}
which I got from a different question: How to get the caller class in Java.
Is there a way to get a pointer to the caller object?
If you control the source code, and if B can only be created by an A object, you could make B a non-static inner class, and then you would automatically get a reference back to the creator of the class, through the A.this pointer. Note this isn't the caller of B::somethingElse(), but the creator of B, which may or may not be the same thing, depending on your use case.
public class A {
public B obj = new B();
public void something() {
obj.somethingElse();
}
void thereAndBackAgain() {
}
public class B {
public void somethingElse() {
A owner = A.this;
owner.thereAndBackAgain();
}
}
}

Java error: class, interface, or enum expected

I need to know the output of this code. But it's not working. Maybe the code is wrong.
I'm still learning how to use Java, and I tried fixing this for hours but still no luck.
Here is the code:
public class A
{
public A()
{
System.out.println ("A");
}
}
public class B extends A
{
public B()
{
System.out.println ("B");
}
}
public class C extends B
{
public C()
{
System.out.println ("C");
}
}
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
}
Can anyone tell me what is wrong or missing in the code?
Put your main method in a class.
Filename : DemoClass.java
class A
{
public A()
{
System.out.println ("A");
}
}
class B extends A
{
public B()
{
System.out.println ("B");
}
}
class C extends B
{
public C()
{
System.out.println ("C");
}
}
public class DemoClass {
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
}
}
Another point here is, you can have only public class in a file, so your A B and C all class can't be public in same java file.
Your java file name must be same as public class name. i.e. here DemoClass is public class so file name will be DemoClass.java
Java doc for getting started : getting started with java
For example:
public class Example {
public static void main(String...args) {
new C();
}
public static class A {
public A() {
System.out.println("A");
}
}
public static class B extends A {
public B() {
System.out.println("B");
}
}
public static class C extends B {
public C() {
System.out.println("C");
}
}
}
Also note that this might not print what you would expect. It would actually print:
A
B
C
Why? Constructors are always chained to the super class.
You can, but it is not recommended, nest your classes in a file. It is perfectly valid.
Notice in the output below that each successive child calls its parent's default constructor (super()) implicitly.
I recommend you create the files: A.java, B.java, C.java, and InheritenceTest.java.
public class InheritenceTest {
public class A {
public A() {
System.out.println("A");
}
}
public class B extends A {
public B() {
System.out.println("B");
}
}
public class C extends B {
public C() {
System.out.println("C");
}
}
public static void main(String args[]) {
InheritenceTest i = new InheritenceTest();
A a = i.new A();
B b = i.new B();
C c = i.new C();
}
}
Output:
A
A
B
A
B
C
Warning:
You shouldn't have more than 1 public classes in 1 java file, not recommended. However, it could still work if you didn't use the 'public' identifier (or by using static or inside another class). But for a starter, I would recommend you to have them all in separate files.
Error:
Your main method does not belong to any class. I propose you create another class that includes the public static void main method to test your application.
Info: keep a look at inheritance as your printings might not be what you expect. (Constructor of class B calls the constructor of A, and constructor of class C calls the constructor B which in turn calls the constructor of A).
That's why you get
A
A
B
A
B
C
*due to A() it prints A, then due to B() it prints A B and finally due to C() it prints A B C.
In your case, I would try the following:
//Filename: A.java
public class A {
public A() {
System.out.println ("A");
}
}
//Filename: B.java
public class B extends A {
public B() {
System.out.println ("B");
}
}
//Filename: C.java
public class C extends B {
public C() {
System.out.println ("C");
}
}
//Filename: Test.java
//use a Test class for testing
public class Test {
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
}
}

How do I control visibility to field in my Java classes?

How can I differentially control access to members of any class? Let's say I have three classes:-
Class A
{
int a;
int b;
}
Class B
{
Access to only 'a' and not 'b'
}
Class C
{
Access to only 'b' and not 'a'
}
One way would be to use aspect-oriented programming. You can check to see the accessing package or class and prohibit access.
AspectJ can be used to enforce that classes in the persistence tier are not accessed in the web tier, only from the service tier. Here's an example:
http://blog.jayway.com/2010/03/28/architectural-enforcement-with-aid-of-aspectj/
Interface time:
interface IHaveA { int a {get;set;} }
interface IHaveB { int b {get;set;} }
Class A : IHaveA, IHaveB
{
public int a {get;set;}
public int b {get; set;}
}
Class B
{
IHaveA _iHaveA;
C(IHaveA iHaveA)
{
_iHaveA = iHaveA;
}
}
Class C
{
IHaveB _iHaveB;
C(IHaveB iHaveB)
{
_iHaveB = iHaveB;
}
}
Then new up B and C like this:
static Main()
{
A a = new A();
B b = new B(a);
C c = new C(a);
}
Here is a really crude idea.
Have A have a function to take an observer derived from B, and another function to take an observer derived from A.
class A
{
int a;
int b;
void getAObserver(B bInstance);
void getBObserver(C cInstance);
}
Then have A can call functions such as aWasUpdated or bWasUpdated on the instances make the member a and b sort of psuedo public to the specific classes.
A really crude way of implementing this would be
Class A {
private int a ;
private int b ;
public int getA( Object obj) throws userDefinedIllegalAccessException {
//check if obj isInstance of B
// If yes return a
// else throw userDefinedIllegalAccessException
}
public int getB( Object obj) throws userDefinedIllegalAccessException {
//check if obj isInstance of c
// If yes return b
// else throw userDefinedIllegalAccessException
}
}
class B {
public void checkAccessValue() {
try{
A objA = new A() ;
System.out.println(objA.getA(this) ;
System.out.println(objA.getB(this) ;
}
catch(userDefinedIllegalAccessException udException){
}
}
}
class C {
public void checkAccessValue() {
try{
A objA = new A() ;
System.out.println(objA.getA(this) ;
System.out.println(objA.getB(this) ;
}
catch(userDefinedIllegalAccessException udException){
}
}
}

Java: how does a component know its owner

Suppose I have a class A and a class B.
public class A {
private B b;
public A() {
this.b = new B();
}
public B getB() {
return this.b;
}
}
public class B {
public String getSome() {
return "Get some!";
}
}
I know I can get B through A, because A has (or owns) B: new A().getB().
But if I have B, can I get A?
Sure, just add routine getA() in you class B, and change the line in your constructor to
public A() {
this.b = new B(this);
}
This of course assumes your class B has a constructor which accepts an A, e.g.,
public B(A a) {
this.a = a;
}
B needs an explicit reference to its owner:
public class B {
private final A owner;
public B(A owner) {
this.owner = owner;
}
public A getOwner() {
return owner;
}
}
And in A:
public A() {
b = new B(this);
}
Nope. There is no such thing as an 'owner' in Java. Any object can be referenced by any number of other objects.
If you need B to always be bound to an instance of A, make B an inner class of A:
class A {
B b = new B();
class B {
String getSome() {
// this will refer to the enclosing A
return A.this.toString();
}
}
}
An inner (non-static) class always has an implicit reference to the enclosing instance and cannot exist without it. In order to instantiate B from outside, you need a nasty syntax: B b = new A().new B();
No you cannot. B has no reference to A.
No.
Class a has reference to class B, but class B has no reference to class A. References are one way only.
No, that's not possible. You're looking for backreferences, but we have to create them in the code if needed.
If you want to collect all referencers to B, you could do this with a constructor or with a factory (pattern) that creates B's. I'll show the factory:
public class B {
private static Set<? extends Object> referencers = new HashSet<? extends Object>();
private B(){} // no public constructor
public static create(Object parent) {
// cooperative approach, the caller should pass "this"
referencers.add(parent);
}
public static remove(Object parent) {
referencers.remove(parent);
}
}
you can also use inner classes
package test;
public class A {
B b = null;
public B getB()
{
return b;
}
public class B {
public A getA()
{
return A.this;
}
}
public static void main(String[] args) {
B b = new A().new B();
}
}

Inheritance in Java

Consider the following code in Python:
class A(object):
CLASS_ATTRIBUTE = 42
def f(self):
return "CLASS_ATTRIBUTE: %d" % self.CLASS_ATTRIBUTE
class B(A):
CLASS_ATTRIBUTE = 44
Now A().f() and B().f() return "CLASS_ATTRIBUTE: 42" and "CLASS_ATTRIBUTE: 44" respectively.
How can I achieve a similar effect in Java? I want a CLASS_ATTRIBUTE field to be initialized statically and redefined in the inherited class but the f method should be only defined in the base class.
Is there a particular reason you want the attribute to be static? In Java the typical way you'd do this is to have A contain a protected variable that you then set in the constructors of the 2 classes:
public class A
{
protected int CLASS_ATTRIBUTE;
public A()
{
CLASS_ATTRIBUTE = 42;
}
public String f()
{
return "CLASS_ATTRIBUTE: " + CLASS_ATTRIBUTE;
}
}
public class B extends A
{
public B()
{
CLASS_ATTRIBUTE = 44;
}
}
Alternatively (and probably more consistent with Java design patterns) you'd declare a function that you can override to return the value instead of using a member variable.
Short answer: you cant solve it like this in Java. You'll have to solve it in another way.
In Java you can't override or "redeclare" fields in subclasses, and you can't override static methods.
It can be solved using an ugly reflection-hack (should be avoided though):
public class Main {
public static void main(String... args) {
A a = new A();
B b = new B();
System.out.println(a.f()); // Prints 42.
System.out.println(a.fReflection()); // Prints 42.
System.out.println(b.f()); // Prints 42.
System.out.println(b.fReflection()); // Prints 44.
}
}
class A {
static int CLASS_ATTRIBUTE = 42;
public int f() {
return CLASS_ATTRIBUTE;
}
public int fReflection() {
try {
return getClass().getDeclaredField("CLASS_ATTRIBUTE").getInt(null);
} catch (Exception wontHappen) {
return -1;
}
}
}
class B extends A {
// Compiles, but will not "override" A.CLASS_ATTRIBUTE.
static int CLASS_ATTRIBUTE = 44;
}
You can't do this directly with only a variable, because in Java variables cannot override (they only shadow the super classes variables).
You need to use a protected "getter" method, which can then be overridden by the subclass:
class A
{
private int attribute=42;
...
protected int getAttribute() {
return attribute;
}
}
class B
extends A
{
private int attribute=44;
...
protected int getAttribute() {
return attribute;
}
}
But note there's a special consideration to calling methods from an object's constructor, in that it allows object code to run before object construction is complete.
I'm not sure if you meant "statically" literally or not, but here's a brief example of how inheritance at it's most basic form looks in Java. Note that using a getter method to access the variable is a better idea for several reasons -- this is just an example.
public class Dog {
protected String whatISay = "Woof!";
public void speak(){
System.out.println(whatISay);
}
}
public class Poodle extends Dog {
public Poodle(){
whatISay = "Yap!";
}
}
public class Main {
public static void main(String[] args){
Poodle fluffy = new Poodle();
fluffy.speak();
Dog dog = new Dog();
dog.speak();
}
}
Yap!
Woof!
This way of doing it introduces as little intrusion as I could think of. setAttribute() could be named something like setDefaultValue() if that's clearer.
public class A
{
protected int attribute;
public A()
{
setAttribute();
}
public String f()
{
return "CLASS_ATTRIBUTE: " + attribute;
}
protected void setAttribute()
{
attribute = 42;
}
}
public class B extends A
{
#Override
protected void setAttribute()
{
attribute = 44;
}
}
public class Main
{
public static void main(String[] args)
{
A a = new A();
B b = new B();
System.out.println("A: " + a.f());
System.out.println("B: " + b.f());
}
}

Categories

Resources