[BUG] Missing error? blank final may not have been initialized
Jan Lahoda
jan.lahoda at oracle.com
Wed Apr 9 12:13:35 UTC 2014
On 04/08/2014 11:24 PM, Raffaele Sgarro wrote:
> Hi Jan,
>
> I'm sure it's not a regression, and I agree this behavior is reasonable
> and nobody writes code like that - just wonder if it follows the spec or
> if the spec needs to be updated.
>
> I saw this code on a message board where the anonymous class (compiling)
> was contrasted with the lambda (not compiling). Moreover, it only showed
> up because, after the update to JDK8, NetBeans suggested the original
> author to replace the anonymous with a lambda - and the suggestion
> turned out to be a failure, because after the "translation" the code did
> not compile anymore.
I've opened a bug for NetBeans:
https://netbeans.org/bugzilla/show_bug.cgi?id=243695
(Thanks for the report.)
>
> To me the contrast with the lambda is key here, because it's feels wrong
> the compiler behaves in two different ways. We all know lambdas and
> anonymous classes are totally different beasts, but the semantic is the
> same wrt this situation, while the compiler is inconsistent: it screws
> because the blank final can be accessed before being assigned, but only
> if it's a lambda, not if it's an anonymous, despite the fact that both
> are instance fields, so can only be leaked before a ctor ends. I think
> arguing about the lambda machinary and other compiler internals doesn't
> buy anything to us in this case - I expect an explicit rule here, not
> reasons why javac might not be wrong in doing this and also might not be
> wrong in doing that even if the two are opposite behaviors
JLS 16.2.2 says:
A blank final member field V is definitely assigned (and moreover is not
definitely unassigned) before the block (§14.2) that is the body of any
method in the scope of V and before the declaration of any class
declared within the scope of V.
So not generating the compile-time error for the access inside the
anonymous innerclass' methods seems appropriate to me.
Jan
>
>
> 2014-04-08 18:37 GMT+02:00 Jan Lahoda <jan.lahoda at oracle.com
> <mailto:jan.lahoda at oracle.com>>:
>
> On 04/08/2014 02:06 AM, Alex Buckley wrote:
>
> The question for compiler-dev is not whether the DU/DA analysis
> within
> anonymous classes is reasonable, but whether there's been a
> regression
> in javac. I know Paul and Jan are working on DU/DA analysis at the
> moment, maybe they could comment.
>
>
> I don't think there is a regression in javac - I was able to compile
> the provided code with "1.4.2_07" javac. Intuitively, considering
> the methods declared in the anonymous innerclass to be outside of
> the expression that contains the new instance expression itself
> seems reasonable to me. Note that if the access is moved to the
> initializer of the anonymous class, it is flagged as an error (which
> makes sense to me).
>
> Jan
>
>
>
> Alex
>
> On 4/7/2014 3:50 PM, Raffaele Sgarro wrote:
>
> Hi Alex,
>
> In fact, the lambda behavior is correct to me. Why do you
> think it would
> be unreasonable for the anonymous?
>
>
> 2014-04-08 0:09 GMT+02:00 Alex Buckley
> <alex.buckley at oracle.com <mailto:alex.buckley at oracle.com>
> <mailto:alex.buckley at oracle.__com
> <mailto:alex.buckley at oracle.com>>>:
>
> I don't believe javac has ever given an error in this
> case. It would
> be unreasonable to require 'data' to be definitely
> assigned before
> the body of the anonymous class. OTOH, names in the
> body of a lambda
> expression are specified as if they appear outside the
> lambda
> expression, where 'data' would be definitely
> unassigned, so an error
> is due there.
>
> Alex
>
>
> On 4/7/2014 10:02 AM, Raffaele Sgarro wrote:
>
> §16 states:
>
> For every access of a local variable or blank final
> field x, x
> must be
> definitely assigned before the access, or a
> compile-time error
> occurs.
>
> Consider the following code:
>
> class Ideone{
>
> public interface Provider{ String
> get(); }
>
> public static class Outer{
>
> private final String data;
> private final String token;
> private final Provider
> secretProvider= new
> Provider() {
>
> public String get() {
> return data;
> }
> };
>
> public Outer() {
> token= secretProvider.get();
> data= "FOOBAR";
>
> }
>
> public String getToken() {
> return token;
> }
>
> }
>
> public static void main(String[] args)
> throws
> java.lang.Exception {
> Outer outer= new Outer();
>
>
> System.out.println(outer.____getToken()); //
> Prints null
> }
> }
>
> Note that if I used a lambda expression, instead,
> javac would
> have
> complained.
>
>
>
More information about the compiler-dev
mailing list