Object instantiation: Inner class and outer class with the same name (Java) - java

Code description and ouput
In the following code. We have a class TestInners, one inner class A, one method local inner class A and one outer class A.
When we instantiate an object as in new A().m(); the ouput is
middle.
In order for the program to output inner we must instantiate the object after the method local inner class A in the gomethod.
If we comment the inner class the program will output outer.
Question
In the code as it is. Why did it output middle? Is there a preference for the inner classes first? then the outer classes? I got confused.
Source code
class A { void m() { System.out.println("outer"); } }
public class TestInners {
public static void main(String[] args) {
new TestInners().go();
}
void go() {
new A().m();
class A { void m() { System.out.println("inner"); } }
}
class A { void m() { System.out.println("middle"); } }
}

Yes, if you shadow symbols with more local definitions, the more local one is chosen. This most frequently happens with method parameters vs instance fields, leading to the famous this.name = name idiom.
In your case, you can get to the outer class by using a fully qualified class name.
But don't name classes like that. Too much confusion for no reason.

Related

Why does this.getClass give it's own class name rather than Anonymous class name?

I have created anonymous class by implementing interface I inside public static void main() method. So, by java 8 for the abstract method test(), the implementation is provided from imple() method of class C.
So, inside public static void main() method, printing _interface.getClass(), I got
package_path.Main$$Lambda$1/310656974 which is absolutely fine. Bacause it print's the anonymous class name.
Also, _interface is pointing to an anonymous object in heap and hence I'm doing _interface.test();
So, the first statement that test() method has now is to print the class name,
But eventually what it print was,
package_path.C (telling me C is the class name). How is that possible? Shouldn't package_path.Main$$Lambda$1/310656974 be printed again? Because 'this' means anonymous inside the test method right?
#java.lang.FunctionalInterface
interface I {
void test();
}
class C {
void imple() {
System.out.println(this.getClass());
System.out.println("Inside Implementation");
}
}
class Main {
public static void main(String[] args) {
I _interface = new C()::imple;
System.out.println(_interface.getClass());
_interface.test();
}
}
Hopefully, this might help you understand, that when you declare
I _interface = new C()::imple;
you've actually implemented the interface somewhat similar to (though not same as):
I _interface = new I() {
#Override
public void test() {
new C().imple(); // creating an instance of class `C` and calling its 'imple' method
}
};
Hence when the test method is called, it first creates an instance of C which prints
class x.y.z.C
as the class.
Because 'this' means anonymous inside the test method right?
Now as you can see above, there is no more anonymous class from which imple
is being called from, hence this is not representing the anonymous class anymore.
As Holger clarified in comments further, despite the representation as lambda or anonymous class at the calling site, the this.getClass() inside a method of class C will evaluate to C.class, regardless of how the caller looks like.
Recommend: Continue to read and follow on Is there any runtime benefit of using lambda expression in Java?

Why can't a local class that extends an inner class access the inner class enclosing instance?

(I keep re-reading that question title and thinking about how ridiculous it must look, but I assure you that is the best description of the problem, and I have an actual application where this is the best structure. I swear I'm not crazy.)
Consider the following. Each block is a separate file:
package myPackage;
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
}
}
package myPackage;
import myPackage.A.B;
public class Main {
public static void main(String[] args) {
class C extends B {
public C(A enclosingInstance) {
enclosingInstance.super();
}
public void show() {
System.out.println(A.this.i);
}
}
A myA = new A(2);
C myC = new C(myA);
myC.show();
}
}
Note that the enclosingInstance business is to solve a problem involving intermediate constructor invocations. See "Why can't outer classes extend inner classes?".
I would expect the output to be "2". But instead, I have a compile error on System.out.println(A.this.i);:
No enclosing instance of the type A is accessible in scope
I think the programmatic concept I'm trying to solve is sound: Create a new type of B inside main to give to A that uses things from A that types of B can access.
So what am I doing wrong, or why isn't this possible in java?
EDIT/UPDATE: Note that the same error appears when the code in main is moved to a non-static method. That is to say, I tried moving everything inside of static void main to a new, non-static method of class Main called go(). Then I changed static void main to the single line new Main().go();. The error is in the same spot. So it doesn't seem to be an issue of class C being defined in a static context.
You want A.this to refer to the enclosing instance of the B instance. But why should it? That's not what the syntax means. A.this would mean the enclosing A instance of the C instance, and this does not make sense because C is not an inner class of A.
To make this clearer, here is an example where C is an inner class of A.
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
void foo() {
System.out.println(A.this.i);
}
}
public class C extends B {
C(A a) {
a.super();
}
void bar() {
System.out.println(A.this.i);
}
}
public static void main(String[] args) {
A a1 = new A(1);
A a2 = new A(2);
C c = a1.new C(a2);
c.foo();
c.bar();
}
}
Here C extends B, and both C and B are inner classes of A. Therefore any C has an enclosing A instance, and it also has an enclosing A instance when considered as a B, and these enclosing instances are different (as proved by the fact that foo and bar print different numbers).
So, A.this could not possibly mean what you want it to mean, because it already means something else. I guess the reason why the language designers didn't come up with other syntax to mean the enclosing instance of a super class, is because such syntax would be very complicated, with little pay-off (simple workarounds already exist).
This is absurd code that you should never write for production.
It is, in part, explained in the documentation for Explicit Constructor Invocations
Qualified superclass constructor invocations begin with a Primary
expression or an ExpressionName. They allow a subclass constructor to
explicitly specify the newly created object's immediately enclosing
instance with respect to the direct superclass (ยง8.1.3). This may be
necessary when the superclass is an inner class.
All this to say that C is a local class (which is an inner class, which is kind of nonsense because if you declare it in a static method there is no enclosing instance) that is a subclass of B but not a nested class of A. As such, there is no enclosing instance. An instance of C does not have an enclosing instance. (Though it would if you declared it in an instance method, but that would be an instance of Main.)
The newly created object's immediately enclosing instance (from JLS) is specified indirectly through a constructor parameter.
You'd have to store it yourself
private A enclosingInstance;
public C(A enclosingInstance) throws CloneNotSupportedException {
enclosingInstance.super();
this.enclosingInstance = enclosingInstance;
}
and since A#i is public, you can access it normally
public void show() {
System.out.println(enclosingInstance.i);
}
With the provided information, I would do this :
public class B {
protected A getOuterInstance() {
return A.this;
}
}
and just let C inherit and use this method. I know you dislike this method but this is the simplest answer I can see. With more information, I would probably propose a design which would try not involving any inner class as this is not a normal use case for inner classes.

Why can I use external non static classes and methods inside main, and can't with classes and methods defined inside the class?

I naturally can have classes inside any class, so in my main method. I also can access to its methods and its attributes.
But this code isn't working. I know main to be static, so is it something like:
The main method runs and is it the one constructing any class, even the one who contains it.
Then, main should start, construct the class who contains it, and then any class or method inside.
package holamundo;
public class HolaMundo {
public class AnotherClass {
// Class body
}
public void method () {
// Code
}
public static void main(String[] args) {
AnotherClass a = new AnotherClass();
method();
}
So doing:
package holamundo;
public class HolaMundo {
public static class AnotherClass {
// Class body
}
public static void method () {
// Code
}
public static void main(String[] args) {
AnotherClass a = new AnotherClass();
method();
}
We could say main is running first, among the AnotherClass and method definitions?
I tried writing this up with my own words, but the SCJP 6 book does it way better, so here it goes:
A static nested class is simply a class that's a static member of the
enclosing class
Perhaps to better understand, here's some code:
public class HolaMundo {
public static class AnotherClass {
public void hello(){
System.out.println("Hello");
}
public static void hola(){
System.out.println("Hola");
}
}
public static void main(String[] args) {
HolaMundo.AnotherClass.hola();
HolaMundo.AnotherClass holaAnother = new HolaMundo.AnotherClass();
holaAnother.hello();
}
}
Note that the above code in the main() method will continue to work if you remove the occurrences of HolaMundo..
If you're confused, here's more from the book:
The class itself isn't really "static"; there's no such thing as a
static class. The static modifier in this case says that the nested
class is a static member of the outer class. That means it can be
accessed, as with other static members, without having an instance of
the outer class.
A static method (like main()), doesn't belong (and also cannot access) to any particular instance of any class.
This means that a static method can create new instances of any class it has access to, even if it happens to be an instance of the class that declared said method in the first place.
Now, since in this case, main(), AnotherClass and method() are all static members of HolaMundo, then yes, this means that they all "run together".
More specifically, they are loaded when the class is first loaded by the JVM (aka at Class Loading time).
In Java, non-static nested classes have an implicit reference to an instance of the container class and so cannot be utilized in static contexts (like the main method) since there is no instance to reference.

How to use the anonymous inner class?

I have made these 2 classes to make use of the concept of anonymous inner class.
Class 1 has a static inner class. And class 2 uses it. But i cant understand how to call the method of the inner class. Please help me out.
Class 1
public class outerclass {
outerclass() {
System.out.println("Constructor of new class");
}
public void showthis(String str) {
System.out.println(str);
}
static class insideclass {
insideclass() {
System.out.println("This is inside class constructor");
}
public void nowshowthis(String str) {
System.out.println(str);
}
}
}
Class 2
public class helloworld {
public static void main(String args[]) {
//this is an object of the outer class
outerclass example=new outerclass();
//How do i make an anonymous inner class and call the method "nowshowthis()"
}
}
An anonymous inner class is one that is created AND defined within the body of another class's method. In essence, you are creating a concrete class on the fly from an abstract definition. What you have so far with your InnerClass class is actually just a regular inner class, meaning non-anonymous.
If you want to experiment with anonymous inner classes, the simplest way I can think of is to change your InnerClass to an interface, like so:
public interface InnerClass{
public void doSomething();
}
So at the moment, InnerClass does squat; it has no meaning until it is defined. Next, you'll want to change how OuterClass works. Change your showThis() function like so:
public showThis(InnerClass innerObj){
innerObj.doSomething();
}
Now we have your outer class asking the inner class instance to do something, but we still have not defined what it is we want it to do. This is where the magic happens - in your main method, you will define what the inner class instance actually looks like:
public static void main (String[] args){
OuterClass outer = new OuterClass();
// This is the key part: Here you are creating a new instance of inner class
// AND defining its body. If you are using Eclipse, and only write the
// new InnerClass() part, you'll notice that the IDE complains that you need
// to implement the doSomething() method, which you will do as though you
// were creating a plain 'ol class definition
outer.showThis(new InnerClass(){
public void doSomething(){
System.out.println("This is the inner anonymous class speaking!");
}
});
}
In practice, I've not used anonymous inner classes too much, however they are useful to know about. I have used them most often when I am doing GUI programming, to define listeners for GUI control events, such as a button click.
Also, as other people have mentioned, keep in mind that the Java standard has the first letter of the class name a capital letter, which I have done here. You'll want to follow that standard as it makes it far easier for other people to read your code, and at a glance you can very easily tell when you're looking at a class, and when you're looking at an object.
Anyways, hope that helps.
Let me just get out of my immediate issue! If your inner class in non-static this is how to instanciate it: (assuming example to be an object of type outerclass)
example.new insideclass().nowshowthis("my String")
For static public inner class, you don't even need an instance of outer class. Just do this (much like accessing public static variable)
new outerclass.insideclass().nowshowthis("my String")
have you tried this?
What's the deal? In your case, you are not really dealing with Anonymous inner class. It's actually just a plain vanilla inner class. (I can't rationalize why would you do that.)
So what's an anonymous class, and where we use it? An anonymous class is like an instance of class for one time use. One of the examples comes to surface when you implement some interface... but you do not need to use it other wise. For example you want to attach a handler to a button. You can do it much like in this fashion (hypothetical example)
MyButtonInterface obj= new MyButtonInterface(){
#Override
onClick(Model obj){
//save model in DB
}
}
UI.add(obj, "specificId");
you see?
insideclass is an non-static class so it must be accessed via an instance of the outer class as follows:
new outerclass().new insideclass().nowshowthis();
That is not an anonymous inner class. Here is an example of an anonymous inner class:
class InnerClassDemo {
public static void main(String[] args) {
ActionListener a = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
};
// now a is the only instance of an anonymous inner class implementing the ActionListener interface
}
}
You can of course also do this with your own interface or class:
class InnerClassDemo {
public class InsideClass {
InsideClass() {
System.out.println("This is inside class constructor");
}
public void nowshowthis(String str) {
System.out.println(str);
}
}
public static void main(String[] args) {
InsideClass anonym = new InsideClass() {
#Override
public void nowshowthis(String str) {
System.out.println("anonymous inner class override: "+str);
}
}
InsideClass normalInstance = new InsideClass();
anonym.noshowthis("test");
normalInstance.noshowthis("test");
}
}
Your output will be
anonymous inner class override: test
test
So anonym is an instance of an anonymous inner class implementation of InsideClass while normalInstance is just a normal instance of your class InsideClass.
public class HelloWorld {
public static void main(String args[])
{
outerclass.insideclass example= new outerclass.insideclass();
example.nowshowthis("Hello");
}
}
Or, make the nowshowthis method static and it can be called like so:
outerclass.insideclass.nowshowthis("Howdy. This method is static.");

how to use inner class out side of current package

I have an inner class which is present inside a method and this class has a method.
I want to use the method which is present in my inner class method outside of my current package.
Can you suggest me how to use it?
package com.a3.local;
public class OuterClass
{
public void outerMethod()
{
class InnerClazz
{
public void wakeUp()
{
System.out.println("Good Morning");
}
}
}
}
As others explained you can access to your method local defined inner-class (using an interface => see other answers).
Anyway I don't think this is the purpose of defining a method-local class.
We can access the inner class method outside the package.
We need to create an instance of the Outerclass and then create an instance of the inner class using the outer class. After that we can call it.
code from tutorial : http://www.oursland.net/tutorials/java/innerclasses/
public class InnerClassTest {
public void foo() {
System.out.println("Outer class");
}
public class ReallyInner {
public void foo() {
System.out.println("Inner class");
}
public void test() {
this.foo();
InnerClassTest.this.foo();
}
}
public static void main(String[] args) {
InnerClassTest o = new InnerClassTest();
InnerClassTest.ReallyInner i = o.new ReallyInner();
i.test();
As far as I understood the code looks like:
class Outer
{
public void someMethod()
{
class Inner{
public void methodThatShouldBeVisibleOutside() {}
}
}
}
The only way is to have the Inner class implements a publicly visible interface 'InnerInterface' and return an instance of the Inner class and invoke the methodThatShouldBeVisibleOutside:
public InnerInterface someMethod()
{
class Inner implements InnerInterface()
{
#Override
public void methodThatShouldBeVisibleOutside() {}
}
return new Inner();
}
Then
new Outer().someMethod().methodThatShouldBeVisibleOutside();
If the inner class is defined in a method, calling its methods (without reflection) requires that:
The class implement an interface accessible to the caller.
An instance of the class is accessible to the caller.
There's an example at http://java.sun.com/new2java/divelog/part5/page5.jsp .
Your class has to be public and have a name and be defined in the class body, not inside a method for you to be able to use it in other packages directly, instead of just using it by its base type or one of its interface types.
If you have a class mypackage.Outer that defines an inner class Inner, you can refer to the class using the name mypackage.Outer.Inner and import that as normal to shorten the name.
If it's static, you can create it using the new mypackage.Outer.Inner(...).
If it's not static, you have to use a different syntax to create them : myOuterInstance.new mypackage.Outer.Inner(...).
First of all, your inner class must have a public visibility and be static.
Then, there's two possibilities :
You want to call a static method of your inner class
You want to call a method on an instance of your inner class
In the first case, if the visibility are setted right, you can simply do :
OuterClass.InnerClass.myStaticMethod()
In the seconde class, you must provide a way to retrieve an instance of the inner class and simply invoke the method on the instance as you'll do with any other method.
It is also possible to call a method on a non static inner class, but this is way more complicated. A code snippet will really helps here ;)
Hope this helps.

Categories