3

I tried this:

class protectedfinal
{
  static abstract class A 
  {
    protected final Object a;
  }

  static class B extends A
  {
    { a = new Integer(42); }
  }

  public static void main (String[] args)
  {
    B b = new B();
  }
}

But I got this error:

protectedfinal.java:12: error: cannot assign a value to final variable a
    { a = new Integer(42); }
      ^
1 error

How to work around this problem?

Some people suggested here to use a constructor but this works only in some cases. It works for most objects but it is not possible to reference the object itself from within the constructor.

  static abstract class X
  {
    protected final Object x;
    X (Object x) { this.x = x; }
  }

  static class Y extends X
  {
    Y () { super (new Integer(42)); }
  }

  static class Z extends X
  {
    Z () { super (this); }
  }

This is the error:

protectedfinal.java:28: error: cannot reference this before supertype constructor has been called
    Z () { super (this); }
                  ^

One could argue that it does not make much sense to store this kind of reference, because this exists already. That is right but this is a general problem which occurs with any use of this in the constructor. It is not possible to pass this to any other object to store it in the final variable.

  static class Z extends X
  {
    Z () { super (new Any (this)); }
  }

So how can I write an abstract class, which forces all child classes to have a final member which gets initialized in the child?

ceving
  • 21,900
  • 13
  • 104
  • 178
  • 5
    `super (this);` Why on Earth? The `this` will always be there when you need it, and even in the methods implemented in the **super** class, will mean the **actual** implementation: if the class is a descendant, then that... – ppeterka Oct 02 '13 at 11:37
  • 2
    `That is right but this is a general problem which occurs with any use of this in the constructor. It is not possible to pass this to any other object to store it in the final variable` **This is on purpose** You should **NEVER** pass a reference anywhere before the constructor completed. This even includes discouraging calling overridable methods from the constructor! This is not a generic problem: you should not need `this` in the constructor. If you do -- something bad is about to happen. – ppeterka Oct 02 '13 at 11:40
  • I dont realy get what you try to archive and im a bit in a hurry but use super.a = new Integer(42); or the below answer. Good luck! – JBA Oct 02 '13 at 11:43
  • @ppeterka66 Read it till the end. – ceving Oct 02 '13 at 12:02
  • 1
    @ceving it occurs to me that you are trying to solve the "egg or chicken" problem. You have to break the circular dependency somehow. I'd recommend reconsideration of the object hierarchy. If you have this kind of issue, I'd say that `Z` and the `Any` class should probably be the same... If you need one to construct the other and vice versa, they should be one.. – ppeterka Oct 02 '13 at 12:35
  • @ppeterka66 Circular references are absolutely common and no design flaw at all. Ever traversed a DOM tree or used a doubly-linked list? – ceving Oct 02 '13 at 13:27
  • 1
    @ceving circular references are OK. Circular dependency is not. (BTW, DOM is a [Tree](http://en.wikipedia.org/wiki/Tree_(graph_theory)) ,which is a form of an Acyclic graph, so that example is a bit faulty there.) Also, where is circular dependency in a doubly linked list? – ppeterka Oct 02 '13 at 13:57
  • @ppeterka66 I am talking about the `this` operator which is a reference in Java. So I am talking about references. I do not know why you talk about dependencies and what it has to do with the `this` reference. – ceving Oct 02 '13 at 14:07
  • 1
    When creating an instance of a class, first the `Object` constructor is executed (instance initializers aside). Then the constructor of the class extending `Object`. Then the next in the inheritance line, and so on. **All** the super constructors must be completed before `this` becomes even semantically available (Happened-Before relation!). To be able to provide `this` as an argument to the super constructor, it would have to be available before even the `Object` constructor is completed for that instance. The directed circle is in the Happened-Before relations, **not** the object references. – ppeterka Oct 02 '13 at 14:45

3 Answers3

6

You have to initialize A.a in its constructor. Subclasses will use super() to pass initializer to A.a.

class protectedfinal {
    static abstract class A {
        protected final Object a;

        protected A(Object a) {
            this.a = a;
        }
    }

    static class B extends A {
        B() {
            super(new Integer(42));
        }
    }

    public static void main (String[] args) {
        B b = new B();
    }
}

You cannot use this until superclass constructors were called, because at this stage the object is not initialized, even Object constructor hasn't run at this point, therefore calling any instance methods would lead to unpredictable results.

In your case, you have to resolve circular reference with Z class in another way:

Z () { super (new Any (this)); }

Either use a non-final field or change class hierarchy. Your workaround with instance method super(new Any(a())); would not work for the same reason: you cannot call instance methods until superclass constructors were run.

Alexey Ivanov
  • 11,541
  • 4
  • 39
  • 68
  • Fine you quoted my question. And what is the answer? – ceving Oct 02 '13 at 11:46
  • Why do you need to pass `this` to `super()`? When you `A()` constructor is called via `super()` in `B()` constructor, the reference stored in `this` will be the same. – Alexey Ivanov Oct 02 '13 at 11:54
  • Have you considered reading the question till the end? Sorry but this is worth a down vote. – ceving Oct 02 '13 at 11:55
  • @ceving Yes, I did. You cannot use `this` until `super` constructor is called. It's the same way with methods: you cannot use an instance method before `super` is called. – Alexey Ivanov Oct 02 '13 at 11:58
  • Sorry but after your last edit I have to say: you nether understood the question nor the work around. – ceving Oct 02 '13 at 14:04
2

In my personal opinion, your problems hints towards a flaw in design. But to answer your question. If absolutely necessary, you can change final fields in java using reflection.

And if everything fails, you can still utilize sun.misc.unsafe.

But I strongly discourage you from doing so, since it potentially kills your VM.

Per Lundberg
  • 3,837
  • 1
  • 36
  • 46
samjaf
  • 1,033
  • 1
  • 9
  • 19
  • Where is the design flow in a abstract class with a abstract final member? The question is simply: is it possible for members? It is possible for methods, but is the same also possible for members? – ceving Oct 02 '13 at 14:14
  • 1
    The design flaw is Java does not support 'abstract members' as you put it in any way. A abstract final member does not make sense at all when talking about java. – samjaf Oct 04 '13 at 20:11
0

My work around so far is to use methods instead of final members:

class protectedfinal
{

  static abstract class AA
  {
    protected abstract Object a();
  }

  static class BB extends AA
  {
    @Override
    protected Object a() { return this; }
  }

  public static void main (String[] args)
  {
    AA a = new BB();
    System.out.println (a.a());
  }
}

But I would like to use final members, because I think accessing a final member is faster than calling a method. Is there any chance to implement it with final members?

ceving
  • 21,900
  • 13
  • 104
  • 178
  • 1
    So the following condition is _always_ true: `a == a.a()`. I cannot see the reason why you want to store reference to `this` twice. – Alexey Ivanov Oct 02 '13 at 11:56
  • 4
    "I think accessing a final member is faster than calling a method" - when dealing with performance you don't _think_, you _measure_. Write something that works correctly, then profile it, work out where the hot spots are and then optimise as necessary until it's fast enough for your purposes. The difference between field and method access is almost certainly not going to be one of the serious hot spots unless you're calling the method millions of times (and even then the JIT will probably optimise it for you). – Ian Roberts Oct 02 '13 at 11:58
  • @IanRoberts Do you know any details about the optimizations of methods doing nothing else but returning a member? – ceving Oct 02 '13 at 12:01
  • @ceving I don't know any details for certain, but if the method were `final` then I would expect it to get inlined. Probably the safest approach would be a non-final `private` field in `A` with protected final get and set methods (with an `== null` check in the setter to prevent it being called more than once). You'd call the setter from within the subclass constructor. – Ian Roberts Oct 02 '13 at 12:04
  • @IanRoberts Is this a general requirement, that only final methods can be inlined? – ceving Oct 02 '13 at 12:06
  • 1
    @ceving I don't know, but the point of my comment was that you _shouldn't care_ until you've profiled the code and worked out that this really is something that's a critical bottleneck. Correctness first, optimisation later. – Ian Roberts Oct 02 '13 at 12:08
  • 1
    @ceving Knuth said `premature optimization is the root of all evil` for a reason... Only try to solve a performance issue if you proved you have one... – ppeterka Oct 02 '13 at 12:36
  • 1
    @ceving No, it's not a requirement. Non-final methods can also be inlined. – Alexey Ivanov Oct 02 '13 at 12:39