how does inner class make this reference escape - java

the noncompliant code example "inner class" section
it seems that there no instance method is called in the inner class, so I don't know how this reference escaped in this snippet.
I've readed some problems, like this, but it is different
public class DefaultExceptionReporter implements ExceptionReporter {
public DefaultExceptionReporter(ExceptionReporter er) {
er.setExceptionReporter(new ExceptionReporter() {
public void report(Throwable t) {
// report exception
}
public void setExceptionReporter(ExceptionReporter er) {
// register ExceptionReporter
}
});
}
// Default implementations of setExceptionReporter() and report()
}

In the constructor of DefaultExceptionReporter, you instantiate an anonymous class. The anonymous class gets a reference to its parent class before the parent class is fully instantiated.
If the parent object had state, it would mean that the anonymous class could theoretically operate on it before it was fully constructed.
Hopefully this demonstrates the potential issue:
class DefaultExceptionReporter implements ExceptionReporter {
private final int foo;
public DefaultExceptionReporter(ExceptionReporter er) {
er.setExceptionReporter(new ExceptionReporter() {
{
System.out.println(DefaultExceptionReporter.this.foo);
}
public void report(Throwable t) {}
public void setExceptionReporter(ExceptionReporter er) {}
});
foo = 1;
}
// ...
}
This will print zero, even though foo is final and assigned 1. A final variable has ended up having two values which should never normally be possible.
Because your object is stateless, I don't think it's a big deal. You should probably declare the class as final though, so it's not possible to extend it and add state.

This happens because when DefaultExceptionReporter publishes the anonymous class, it implicitly publishes the enclosing DefaultExceptionReporter instance as well. You can check this by writing a simple program to actually access that instance:
public static void main(String[] args) {
ExceptionReporter rep = new DefaultExceptionReporter(new ExceptionReporter() {
#Override
public void setExceptionReporter(ExceptionReporter er) {
for (Field field : er.getClass().getDeclaredFields()) {
System.out.println(field);
}
}
#Override
public void report() { }
});
}
Output:
final my.package.DefaultExceptionReporter my.package.DefaultExceptionReporter$1.this$0
This is because an anonymous class is always a non-static inner class (see reference) and these kinds of classes always have an implicit this reference to the enclosing class.

Technically in this example you let this reference escape.
Let's imagine that :
some other thread has access to the ExceptionReporter instance that is passed to the constructor of DefaultExceptionReporter
you actually access the outer instance through DefaultExceptionReporter.this in methods' of your anonymous class instance (for example you want to access field or invoke a method)
In this case other thread might invoke methods on the ExceptionReporter passed to the constructor of DefaultExceptionReporter. And if those methods invoke methods from the instance that is set through setExceptionReporter - other thread can potentially access
DefaultExceptionReporter before it's instance is fully created. The access from other Thread could be done through chain of references :
ExceptionReporter(passed to the constructor) -> ExceptionReporter(anonymous) -> DefaultExceptionReporter.this.

Related

Can Anonymous inner class instantiated within a static method has access to instance members of containing class?

I want to understand better the visibility of instance fields of containing class to an Anonymous inner class (AIC).
There have been lots of talks that AIC has an implicit reference to the containing class' instance (When exactly is it leak safe to use (anonymous) inner classes?). With that logic, even when an AIC is instantiated within a static method, it should have access to the instance fields of the containing class. But I can't find a way to test this as the compiler gives errors.
For e.g., in the below code, I get: "Non-static field 's' can't be referred from a static context" by the compiler when I refer 's' within print() method of the AIC:
public interface TestInterface {
void print();
}
public class AICTest {
public String s = "something";
public static void main( String[] args ) {
new TestInterface() {
#Override
public void print() {
System.out.println( s ); **<-- compilation error**
}
}.print();
}
}
Could you suggest if it's possible for the AIC instance to access 's' in the above example?
Edit/Answer
I want to clarify that I am aware that static methods have access to class members and instance methods have access to instance & class members. The confusion was more about the general statement that AIC always have an implicit reference to containing class' object. This clearly is not the case for AIC initialised within a static method. #shmosel shared a link which answers my question (Is it possible to make anonymous inner classes in Java static?): "So an anonymous class in a static context is roughly equivalent to a static nested class in that it does not keep a reference to the enclosing class, even though it's technically not a static class.".
You have to have an instance of AICTest to read 's' out of, since 's' is an instance variable. Here's an example that will work, representing your example modified to access an existing AICTest object that could potentially come from anywhere:
class AICTest {
public String s = "something";
public static void main( String[] args ) {
AICTest aic = new AICTest();
new TestInterface() {
#Override
public void print() {
System.out.println(aic.s);
}
}.print();
}
}
To be clear, running 'main' does not create an instance of AICTest. You have to do a 'new' somewhere to create an instance of AICTest.
Another option is to make 's' static. Then it isn't associated with any particular AICTest object, and so it exists even if you haven't instantiated an AICTest object:
class AICTest {
public static String s = "something";
public static void main( String[] args ) {
new TestInterface() {
#Override
public void print() {
System.out.println(s);
}
}.print();
}
}
As you can see, I haven't added any visibility modifiers. So your idea about visibility was sound. If it otherwise makes sense to access 's', the visibility is there in your code. The problem here has nothing to do with visibility.
This may not be what you want, but you can:
interface TestInterface {
void print();
}
class AICTest {
public String s="something";
public static void main(String[] args) {
AICTest aicTest=new AICTest();
new TestInterface() {
#Override public void print() {
System.out.println(aicTest.s);
}
}.print();
}
}
The confusion was more about the general philosophy that AIC always have an implicit reference to containing class' object. This clearly is not the case for AIC initialised within a static method. #shmosel shared a link which answers my question (Is it possible to make anonymous inner classes in Java static?): "So an anonymous class in a static context is roughly equivalent to a static nested class in that it does not keep a reference to the enclosing class, even though it's technically not a static class.".

overriding protected method of Superclass

In the below example why does the String b prints null and String c prints "gg".
Correct me if I am wrong, whenever a subclass (BClass) overrides a protected method (i.e initClass()) of the superclass (AClass).If you instantiate the subclass. The superclass must make use of overriden method specified by the subclass.
public class Example {
public class AClass {
private String a;
public AClass() {
initClass();
}
protected void initClass() {
a = "randomtext";
}
}
public class BClass extends AClass {
private String b = null;
private String c;
#Override
protected void initClass() {
b = "omg!";
c = "gg";
}
public void bValue() {
System.out.println(b); // prints null
System.out.println(c); // prints "gg"
}
}
public static void main(String[] args) {
Example.BClass b = new Example().new BClass();
b.bValue();
}
}
As of the JSF 12.5
In the example you can see the execution order. The first steps are the callings of the Constructor down to the Object constructor.
Afterwards this happens:
Next, all initializers for the instance variables of class [...] are executed.
Since your instance variable b is initialized to null it will be null again afterwards
This is happening because the superclass constructor is called before the fields of ClassB is initialized. Hence the initClass() method is called which sets b = "omg!" but then again when the super class constructor returns, b is initialized to the value declared in ClassB which is null.
To debug, put a break point and go step by step, you will find that b is first set to null and then changes to omg! and then comes back to null.
There have been already given several correct answers about what's happening. I just wanted to add that it is generally bad practice to call overridden methods from constructor (except of course if you know exactly what you are doing). As you can see, the subclass may not be completely initialised at the time its instance method is invoked (subclass constructor logic has not been executed yet, so effectively overridden method is invoked on an unconstructed object which is dangerous) which might lead to confusions like the one described in this question.
It is much better to write initialisation logic in the constructor and if it is too long then divide it between several private methods invoked from the constructor.
This is happening like this because, first constructor of AClass, which set value of b = omg! and c=gg. After that When BClass gets load in memory it set b=null and c remain as it is which is gg, this is happening because, because in BClass, for b you are doing declaration as well as initialization and for c you are doing only declaration, so as c is already in the memory it even won't get it's default value and as you are not doing any initialization for c, it remain with it's earlier state.
I believe that this example explains the issue:
public class Main {
private static class PrintOnCreate {
public PrintOnCreate(String message) {
System.out.println(message);
}
}
private static class BaseClass {
private PrintOnCreate member =
new PrintOnCreate("BaseClass: member initialization");
static {
System.out.println("BaseClass: static initialization");
}
public BaseClass() {
System.out.println("BaseClass: constructor");
memberCalledFromConstructor();
}
public void memberCalledFromConstructor() {
System.out.println("BaseClass: member called from constructor");
}
}
private static class DerivedClass extends BaseClass {
private PrintOnCreate member =
new PrintOnCreate("DerivedClass: member initialization");
static {
System.out.println("DerivedClass: static initialization");
}
public DerivedClass() {
System.out.println("DerivedClass: constructor");
}
#Override
public void memberCalledFromConstructor() {
System.out.println("DerivedClass: member called from constructor");
}
}
public static void main (String[] args) {
BaseClass obj = new DerivedClass();
}
}
The output from this program is:
BaseClass: static initialization
DerivedClass: static initialization
BaseClass: member initialization
BaseClass: constructor
DerivedClass: member called from constructor
DerivedClass: member initialization
DerivedClass: constructor
... which demonstrates that the derived class's members are initialized after the base class's constructor (and the invocation of the derived class's member function have completed). This also demonstrates a key danger of invoking an overridable function from a constructor, namely that the function can be invoked before the members of the class on which it depends have been initialized. For this reason, constructors should generally avoid invoking member functions (and, when they do, those functions should either be final or static, so that they either depend only on the current class which has been initialized or on none of the instance variables).

Passing the child instance on construction

I have a parent class which has methods that need to utilize the child's class instance, but I can't seem to pass it via constructor:
public abstract class CodelanxPlugin<E extends CodelanxPlugin<E>> /* other inheritance */ {
private final E plugin;
public CodelanxPlugin(E plugin) {
this.plugin = plugin;
}
#Override
public void onEnable() {
//need to be able to use the plugin instance
}
}
However, because the child class has to be able to collect a child instance in some form before onEnable is called, I essentially came to this:
public class MyPlugin extends CodelanxPlugin<MyPlugin> {
public MyPlugin() {
super(this);
}
Which is of course not possible since you can't super(this). How can I pass up the child instance upon construction?
One idea I had was:
public MyPlugin() {
super(new Box<MyPlugin>(this).getInst());
}
private class Box<E> {
private E inst;
public Box(E inst) {
this.inst = inst;
}
public E getInst() {
return this.inst;
}
}
However it still calls this before the super() is called, so it's still illegal.
One reason I cannot simple use this in the parent class in the first place is that I pass E as the type argument for some other classes:
protected ListenerManager<E> listener;
#Override
public void onEnable() {
//...
this.getLogger().log(Level.INFO, "Enabling listeners...");
this.listener = new ListenerManager<>(/* need the E instance */);
//...
}
If I pass this to the ListenerManager constructor, I receive this compiler error:
error: incompatible types: cannot infer type arguments for ListenerManager<>
If I use new ListenerManager<E>(this), then my error is:
error: incompatible types: CodelanxPlugin cannot be converted to E
I think you may be confused about how subclassing works. (Either that or I'm completely confused about what you're trying to accomplish.) If you have a class C and a subclass Sub:
class C {
}
class Sub extends C {
}
When the program says new Sub(), it creates one new instance. This object is an instance of Sub, and it is also an instance of C. It doesn't make sense to talk about the methods of C referring to "the child instance".
If you have a Sub object:
Sub myObject = new Sub();
and you call a method that runs code in C:
class C {
public void someMethod() {
// someMethod logic
}
}
myObject.someMethod();
and let's say that method is not overridden. So now you're in the section marked someMethod logic. Within that section, this refers to the object instance you're calling it for (myObject)--which is both an instance of C and an instance of Sub. You do not need a separate syntax to refer to "the child instance", because there's no such separate thing.
So in your original example, if your intent is for the plugin field to be "the child instance of the same object you're just creating", get rid of it. You don't need it.
On the other hand, if you're creating a new object and giving the new object a reference to a different, previously created object, that's a whole other story. But that's not how I understood your question.
You simply don't need to pass "this" to your parent's constructor. 'this' inside MyPlugin's constructor refer to the same object as 'this' inside CodelanxPlugin's constructor.
So what you are writing is simply:
public CodelanxPlugin() {
this.plugin = (E) this;
}
And then, you should wonder wy you'd need a "plugin" field anyway, since "this" will always be available... From your explanation, I feel that you are looking for the template method design pattern.

Java inheritance: Reducing visibility in a constructor vs inherited method

In the following code, the constructor of Child has reduced visibility from public to private, which is allowed. The inherited methods, such as test(), cannot have reduced visibility. Why does Java operate this way?
class Parent {
public Parent(){}
public void test()
{
System.out.print("parent test executed!");
}
}
class Child extends Parent{
private Child(){}
private void test(){
System.out.print("child test executed!");
}
}
Constructors are not inherited, so Child() doesn't override Parent().
As for the methods, if you have (if Child() were public)
Parent p = new Child();
p.test();
Had it been allowed, this would be invoking a private method. So narrowing the access while overriding is not permitted.
When extending a class you are stating that your class is an extension of the parent class ("IS-A" relationship). What this means is that your class will have all methods of your parent class. This is the same as implementing an interface in java except you gain the method definitions (and fields) from your parent and not just methods declared in the interface. In interfaces constructors are not present because they are not methods. Constructors are special as they belong entirely to the class they are declared on. They declare how to construct only themselves.
In order to construct an object you must know that objects class.
class A {
private message;
private A() {
message = "You created an A";
}
public A(String message) {
this.message = message;
}
public void printMessage() {
System.out.println(message);
}
public static A createAnA() {
return new A();
}
}
class B extends A {
public B() {
super("You created a B");
}
}
A anA = new B(); // This will work
A anotherA = new A(); // This is not allowed as the constructor is private
A yetAnotherA = A.createAnA(); // This works too
So when we constructed B we can say that it is an A. Even though the constructor A is private this is due the constructor not being a part of the interface. The only thing we are saying about B when we assign it to a field of type A is that it has the methods of declared in A. In this case printMessage and createAnA.
That is why you can make the constructor private without changing the definition of the class. Now, why are you not allowed to make the method private when overriding a parents signature. This comes to having varying definitions of the [class].method(). Let's say that you could make your method private. Let's say that you declared a printMssage in the B class. Your reasoning is that you want that method for your use only inside the method and you want your parents printMessage to be used when called externally. Now, you wrote a method like this in the B class.
public void adjustMessage(String additional) {
message = getMessage() + additional();
}
Which version of get message would be executed? Your private one or the public one of your parents? The Java dispatcher would of course choose the public one as it is the one declared in the interface. So we we look at this example we can see if you did make your method have different a lower privilege your method could never be dispatched too which would just make things confusing for the reader.
This is a very good question.

Why wouldn't you make a nested class static?

If I have class with a nested class, why wouldn't you want it to be static? Is there even a way for two instances of the same class to have different nested classes?
For example:
class MyClass {
public static class myInnerClass {
}
}
why wouldn't you want it to be static
Because I want it to access instance data of a parent object.
Is there even a way for two instances of the same class to have different nested classes?
What do you mean by have? Declared? A class has only one declaration where you list all nested classes. So, in this case the answer is no.
Take for example a Comparator or Runnable (multi-threading) implementations. This is a classic example when you need an extra class that has access to the current instance's fields and methods but is of no use outside of that class. However, static classes could be useful outside the enclosing type, too.
public class EnclosingType
{
private static final class StaticRunnableImplementation implements Runnable
{
private final EnclosingType instance;
public StaticRunnableImplementation(EnclosingType instance)
{
this.instance = instance;
}
#Override
public void run()
{
instance.getSomething();
//getSomething() leads to compile error
}
}
public class NonStaticRunnableImplementation implements Runnable
{
#Override
public void run()
{
doStuff();
}
}
public int getSomething()
{
return 42;
}
public synchronized void doStuff()
{
;
}
public void doSomething()
{
Thread t1 = new Thread(new StaticRunnableImplementation(this));
Thread t2 = new Thread(new NonStaticRunnableImplementation());
t1.start();
t2.start();
}
}
The access to the non-static methods and fields of current instance of the enclosing type, wouldn't be possible if the nested classes would be declared static.
I don't know if I understand your question correctly, but the difference between a static inner class to a non-static is that the second needs a reference from the parent class to be created.
It's preferable to create static class, because of "hidden ciclic references" that can be created. For example, it's normal in GUI developing you do something like
public class View {
private Table table;
...
private void addListeners() {
this.table.addListener(new TableSelectionListener());
}
privte class TableSelectionListener implements Table.SelectionListener {
#Overrides
public void selected(SelectionEvent evt) { /* do stuff.*/ }
}
}
Lots of programmers don't realize, but you now have a circular reference between View and Table, because SelectionListener, being non static, saves a reference to its parent. So
View -> Table -> TableSelectionListener --> View
If you declare TableSelectionListener static it will only need the "namespace" from view to be created, but besides that, it will not save a reference to any View unless you save it on a field. But then, you will return to the first problem :P
Hope that helps :)
A non-static nested class is associated and has access to the members of an enclosing class instance:
Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.
If you implement a Listener of some kind, for example, you usually want to call a method on the outer class when you receive the event. In that case, an inner class is simpler than a nested class with an explicit reference to the outer class instance.
That's often used in GUI components. For example (using an API which doesn't actually exist):
public class CircleView extends View {
private final Circle circle = new Circle();
private final Button button = new Button();
public CircleView() {
circle.setColor(Color.RED);
button.addClickListener(new MyClickListener());
}
private toggleColor() {
circle.setColor(circle.getColor() == Color.RED ? Color.BLUE : Color.RED);
}
private class MyClickListener implements ClickListener() {
#Override
public void onClick() {
// Only possible because of the implicit reference:
toggleColor();
}
}
}
A non-static nested class allows the following in an implicit/magical way:
class MyClass {
public static class MyInnerClass {
final MyClass myClass_this;
public MyInnerClass(MyClass parent) {
// Nested class instance has/keeps access to "parent" object.
// In a nested non-static class the "parent" is -guaranteed- to be
// non-null as the nested class can only be created with
// an instance of the containing class.
myClass_this = parent;
}
public Foo bar() {
// Use myClass_this
// Would be available as MyClass.this or implicit resolution in a
// a nested non-static class.
}
}
}
The rules for scope access are also a bit different but the above should show when it might be useful/desirable. In both cases there is only one type for the inner class (MyClass$MyInnerClass), although there can be many instances.
Wether or not this is a "good" thing to have such non-static nested type behavior is debatable, but it is provided in Java.
However, one case where this "non-static" behavior is extremely useful in Java is with anonymous classes (e.g. event handlers or callbacks) which behave as non-static nested classes; while a "different" construct the same mechanism allows accessing methods defined in the enclosing type. Moving the anonymous classes to non-static nested classes can thus merely be viewed as an extension of this common idiom that also allows exposing the nominative type.
(C# has no notion of a "non-static" nested class, but it is easy to emulate it as per above - although I would argue it's usually better to pass a more-refined interface. In addition, other constructs such as closures minimize the need/use even more.)

Categories

Resources