Using this keyword in abstract context - java

I came across this pattern in some source codes:
public abstract class Foo {
void doSomething(){
System.out.println("...");
}
private class FooBar extends Foo{
void doAnything(){
Foo.this.doSomething();
}
}
}
Whats the significance of
Foo.this.doSomething();
or is it just some cargo cult practice?

Foo.this and this refer to two different objects.
Since FooBar is an inner class defined inside Foo, every instance of FooBar has an instance of Foo associated with it.
this refers to the FooBar instance itself;
Foo.this refers to the outer Foo instance.
See How can "this" of the outer class be accessed from an inner class?
That said, the Foo.this. in the example you show is redundant and can be omitted (unless both Foo and FooBar have a method called doSomething()).

In the example you give this is equivalent to calling doSomething(); directly.
However, if you declared the same method void doSomething() in the FooBar class you would use this notation to signify you call the method of the outer class not the inner.
In the latter case this.doSomething() would not suffice, this still will point to the this member variable of FooBar, that is why you specify specifically the class from which you want to call the method.

Foo.this references outer class Foo's object instance, which is always bound in inner class's object.
You can think to Foo and FooBar as being instanced always together, when Foo is instantiated.
In your case is not necessary, but if you need to pass the Foo object instance to any method that requires it from the inner Foo.Bar, you can do it with:
// some method of some other class (OtherClass.java)
void someFunction( Foo foo )...
// ...
private class FooBar extends Foo{
void doAnything(){
otherClass.someFunction( Foo.this );
}
}

Foo.this refers to outer class object,where as this refers current class object.
According to java docs.It is also called Shadowing

Related

calling an abstract method from the subclass object

Here is my question. I have a super class with an abstract method in it.
public abstract class Base{
public abstract Boolean foo();
}
public class sub extends Base{
#Override
public Boolean foo(){
System.out.printLn("This is foo in the sub class!");
}
}
so When I go to the main and try this code
Base b = new sub();
b.foo();
I got no error and message shows on my screen. My assumption is the compiler looks at the b object and sees it as a Base object then it goes to the foo from the Base object and sees there is no implementation afterwards it checks out the foo from the child and then it sees the method foo is implemented there so it shows the message. Am I right?
Compiler does not see if the method is implemented by subclass or not. It only checks whether method called by the a particular class type reference is present in the class itself or not. At runtime it decides which method to call means Base class version or Subclass version.
So you are only right upto "My assumption is the compiler looks at the b object and sees it as a Base object then it goes to the foo from the Base" statement.
Compiler does not do so much of processing. Here in your case
You have created the reference variable as of your superclass which will hold the object of child class.
Now when you are calling the method it is directly calling the method present in your subclass based on your object type.
I am adding you code with my comments for your reference.
1) Abstract class having only method declaration
public abstract class Base {
public abstract Boolean foo(); //method declaration
}
2) Child class extending your parent class where you have to implement the method,If you are declaring this class as concrete class.
public class sub extends Base {
#Override
public Boolean foo() {
System.out.printLn("This is foo in the sub class!");
}
}
3) Here you have declared reference variable of your parent type that is storing the object of you child class
Base b = new sub();
4) when this line will get executed compiler will check, what is the type of object and call that method on the basis of object type.It will not invoke methods on the type of reference variable.
b.foo();

What is the recommended/correct way to access fields in an inner class?

Suppose we have this class and its inner class:
/* Outer.java */
public class Outer {
private static class Inner {
private final Object foo;
public Inner(Object foo) {
this.foo = foo;
}
public Object getFoo() {
return foo;
}
}
Inner inner = parse(/* someMistery */);
// Question: to access foo, which is recommended?
Object bar = inner.getFoo();
Object baz = inner.foo;
}
I am surprised that inner.foo works.
Since foo is private, it can be accessed only through getFoo(), right?
Since foo is private, it can be accessed only through getFoo(), right?
In this case, Outer has access to it too, because Inner is a member of Outer.
6.6.1 says:
[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 that encloses the declaration of the member or constructor.
Note that it's specified to be accessible within the body of the top level class that encloses the declaration.
This means, for example:
class Outer {
static class Foo {
private Foo() {}
private int i;
}
static class Bar {{
// Bar has access to Foo's
// private members too
new Foo().i = 2;
}}
}
Whether to use a getter or not is really a matter of taste. The important realization here is that outer classes have access to the private members of their nested classes.
As a recommendation, I would personally say:
If the nested class is private (only the outer class has access to it), I wouldn't bother even giving it a getter unless the getter does a computation. It's arbitrary, and somebody else can come along and choose not to use it. If the styles are mixed, the code has a vagueness. (Do inner.foo and inner.getFoo() really do the same thing? We have to go waste time examining the Inner class to find out.)
But you could go through a getter anyway if that's the style you are comfortable with.
If the nested class isn't private, use the getter so the style is uniform.
If you really want to hide the private members, even from the outer class, you can use a factory with a local or anonymous class:
interface Nested {
Object getFoo();
}
static Nested newNested(Object foo) {
// NestedImpl has method scope,
// so the outer class can't refer to it by name
// e.g. even to cast to it
class NestedImpl implements Nested {
Object foo;
NestedImpl(Object foo) {
this.foo = foo;
}
#Override
public Object getFoo() {
return foo;
}
}
return new NestedImpl(foo);
}
As a pedantic note, your static class Inner {} is technically a static nested class, not an inner class. class Inner {} (without static) would be an inner class.
This is specifically defined to be so:
The static keyword may modify the declaration of a member type C within the body of a non-inner class or interface T. Its effect is to declare that C is not an inner class.
It all depends on your piece of code from where do you want to access that object. Since it is a static nested class, so you will be able to access your object from either ways. Refer to this link http://www.javatpoint.com/static-nested-class for better understanding of inner classes.

Accessing methods of extended class from inner class

public class ABC extends XYZ
{
public static class InnerClass1
{
...
}
public static class InnerClass2
{
...
}
public static class InnerClass3
{
...
}
public static class InnerClass4
{
...
}
}
In the above code, I cannot access the methods of the class XYZ inside the inner classes1,2,3 and 4. How can i modify the above structure so that the inner classes can access the methods within the class XYZ ?
Thanks in advance !
public class ABC extends XYZ
{
public static class InnerClass1
{
...
}
InnerClass1 is not an inner class. It's a nested class, because of the word static.
If there were no static, it would be an inner class. And any instance of that inner class would have a hidden reference to an ABC (which is also an XYZ). If the inner class called any instance methods of ABC or XYZ, or referred to any instance variables in those classes, it would use that hidden reference to call the instance methods or access the instance variables.
Since it's a nested class, though, there is no hidden reference to an ABC (or XYZ). Thus, if you call an instance method or refer to an instance variable, it can't do it, because there is no ABC object to work with. (However, you can still call a static method of an ABC, or refer to a static variable.)
I'm not sure what the solution is--it depends on your needs. It's possible that the XYZ methods you can't call don't actually need an XYZ object to work on, and therefore those methods should be static. It's also possible that the nested class should have some explicit ABC or XYZ variable that it uses to access the instance methods; you can still call instance methods from a nested class if you have an object to work on:
public static class NestedClass {
XYZ x;
void someMethod() {
x.instanceMethod(); // legal even if instanceMethod is non-static
}
}
The other solution would be to remove the word static, so that InnerClass1 really has a hidden reference to an ABC. This means that when you create an InnerClass1 instance, you need some ABC object for it to refer to. If you create this in some other class, the syntax would be something like
ABC abcObject;
...
ABC.InnerClass1 newObject = abcObject.new InnerClass1();
static inner class can only access static members of the outer class
so the inner class will only be able to use the static members of xyz.
create the inner class non static if you want to access everything
You have two options, one remove the static call so a hidden this reference to the outer class is available to the inner class instances or two, when you create an instance of the inner class pass in a this explicitly, example:
public class ABC extends XYZ
{
XYZ.InnerClass innerInst = new InnerClass(this);
public static class InnerClass1
{
private final ABC extref;
public void Innerclass(ABC outerref)
{
extref = outerref;
}
...
}
}

Why do I need to use keyword "this" to call my enclosing methods or variables

I have a doubt if I have a non-static nested class why do I need to use the keyword "this" to call a method or variable of my enclosing class?
What I think is the following: if a non-static nested class can access to methods and variables of its enclosing class and a non-static nested object instance is already associated to its enclosing object instance why do I need to use "this"?
For example I have the following code:
public class ClassA {
public class ClassB {
public void bye() {
ClassA.this.hello();
// Why not just ClassA.hello()?
}
}
public void hello() {
}
}
and if from a method of my enclosing class I want to call a method of one of mine non-static classes how should I do?For example if from my method hello() I want to call bye() how should I type?
First of all, you can simply call hello().
ClassA.hello() would look for a static method named hello() in ClassA. ClassA.this.hello() looks for an instance method.
ClassA.hello() would work if hello() were declared as static. But because it is an instance method, it needs to be called on an instance.
The ClassA.this syntax is called a qualified this in JLS 15.8.4, and is the only way to refer to the this instance of an enclosing type.
Consider this case where both the inner and outer class have a method with the same signature, you need to be able to distinguish which one to call:
public class ClassA {
public class ClassB {
public void hello(){
System.out.println("Hello b!);
}
}
public void hello() {
System.out.println("Hello a!);
}
}
What would happen if you call hello() from classB? You get Hello b!
What would happen if you call this.hello() from classB? You get Hello b!
These two are equivalent.
What about calling ClassA.hello() from classB? You get an exception, there is no static method called hello() declared.
But if you call ClassA.this.hello() from classB? You get Hello a! This is the syntax for acquiring reference to the outer class from the inner class, should they both have a method with the same signature, otherwise it would be kinda redundant to use this syntax, as inner classes already have access to the outer classes methods.

Why doesn't Java allow hiding static methods by instance methods?

As shown in http://docs.oracle.com/javase/tutorial/java/IandI/override.html, Java does allow
Overriding an instance method by an instance method and
Hiding a static method by a static method
My question is why Java doesn't allow hiding a static superclass method by an instance method. This could be done like this:
class Base {
static void foo () {}
}
class Derived extends Base {
void foo () {}
void access () {
foo ();
Base.foo ();
}
}
I don't see any particular issue with the above approach - it is only as "messy/complex" as the (allowed) hiding of statics already is.
I suspect it is to avoid confusion with dealing with the base class. In fact I imagine the designers didn't see an obvious way this should behave.
class Base {
static void foo () {}
}
class Derived extends Base {
void foo () {} // say this compiled
}
Base b = new Derived()
b.foo(); // should the static or the virtual method be called?
Should b.foo() call Base.foo() or should it potentially call Derived.foo()?
Simple answer: that would be the mess.
Concrete answer: what to call in that case Derived.foo()? Base.foo() can't be called as it's hidden (as per you), Derived.foo() can't be called as it's not static.
Because, one are like Bananas and the other ones are Apples.
Explaination:
Static Methods are created when reading the Class-Structure
Methods are created when a object of a class is created.
Example:
Foo.bar();
is something different than
new Foo().bar();
Guess which one is called?
Foo f = new Foo();
f.bar();
Another to add here is:
1. Static methods belong at the class level. So u cannot override method in the derived class.
as simple its called hiding. :)
2. Instance methods belong to the objects, so objects are overrided. So we can override in the derived class.
Above other comments give a good example have a look into it..
Regards
Punith

Categories

Resources