This discussion is archived
5 Replies Latest reply: Jul 27, 2010 6:09 PM by EJP RSS

Generic - a Type or Variable?

794029 Newbie
Currently Being Moderated
Hello,

This thread is similar to the one posted here, but more specific to Generics.

Anyhow. As mentioned in the other thread, I am in a group working on building a resolution algorithm for Java.
For example "String" would resolve to a class in java.lang, ( Unless there was an inner class called "String" in the current context, or some other weird corner case)

Anyhow, it seems like 98% of the resolution only took a day to complete... but the last 2% are weird corner cases and are taking weeks.
I currently have an example which I cannot find the specification in the JLS. In Netbeans (and from the command line) i get 1 answer, and from Eclipse - i get another answer.

Small example of what i am saying:
public class Foo<A>{

       public static class A{}

       A myA; // What is "A" here? is it the Generic <A> or the static class A?
                    // Java & Netbeans say it is the Generic, Eclipse says the class.


}
Netbeans & java seem to treat Generics more like a "Variable" (which obscures Types).
Whereas Eclipse treats Generics more like a "Type" (which is shadowed by a more local Type)

The JLS says that generics are a "Type Variable" as far as i can tell.

In case you were curious, here is a working Example of obscuring:
 
 public class Example1 {
 
     int [] A = new int[10]; // the field "A"
 
     void myMethod(){
         static class A{static int length = 5;} // declaration of class inside the scope "myMethod()"
         System.out.println(A.length); // this "A" is the field due to obscuring.
     }
 
     public static void main(String [] args)
     {
         new Example1().myMethod(); // prints 10, even though the class is in "more local",
                                      //because Variables obscure Types with the same name. (when they both could be used)
     }
 }
 
  • 1. Re: Generic - a Type or Variable?
    843793 Newbie
    Currently Being Moderated
    Hello 00jt,

    a type variable is a type. I'm not sure how it could make a difference for your example as it does not contain any unclassified (contextually ambiguous) names. This is a matter of shadowing, specifically:
    A declaration d of a type named n shadows the declarations of any other types named n that are in scope at the point where d occurs throughout the scope of d.
    So the question becomes which shadows which; we have to find out the [scope of a type variable in a generic class declaration|http://java.sun.com/docs/books/jls/third_edition/html/classes.html#329478] and the [scope of a member type|http://java.sun.com/docs/books/jls/third_edition/html/classes.html#329405]:
    The scope of a class' type parameter is the entire declaration of the class including the type parameter section itself.
    The scope of a declaration of a member m declared in or inherited by a class type C is the entire body of C, including any nested type declarations.
    With kind regards
    Ben
  • 2. Re: Generic - a Type or Variable?
    794029 Newbie
    Currently Being Moderated
    BenSchulz wrote:
    Hello 00jt,

    a type variable is a type.
    Then Netbeans & Javac are wrong.
    I'm not sure how it could make a difference for your example as it does not contain any unclassified (contextually ambiguous) names.
    My first example code? There is a class called "A", which is different then the generic (type variable) <A>.
    I personally think that this SHOULD be flagged as ambiguous ("the type "A" is already defined").
  • 3. Re: Generic - a Type or Variable?
    843793 Newbie
    Currently Being Moderated
    00jt wrote:
    Then Netbeans & Javac are wrong.
    It's happened before. ;)
    I'm not sure how it could make a difference for your example as it does not contain any unclassified (contextually ambiguous) names.
    My first example code? There is a class called "A", which is different then the generic (type variable) <A>.
    Yes, but you refer to "A" in a field declaration, according to name classification rules "A" must be a TypeName. That means that obscuring does not enter the equation and thus your original question is somewhat irrelevant.

    With kind regards
    Ben
  • 4. Re: Generic - a Type or Variable?
    794029 Newbie
    Currently Being Moderated
    I know that
    ...
    A myA; // "A" must be a TypeName.. but i wasn't sure if "type Variables" can obscure "types" just like "variables" can.
    ...
    However, I think you are right: Java & Netbeans are both wrong.

    look at this (according to Netbeans/Java):
    public class Test {
    
        class Foo<A>{
                A myA;      // generic type "A"
                class A{    // class "A"
                    A myA;  // generic type "A" ???!!!! Clearly it is "Obscuring"  like a +type+
                }
        }
    
        class Bar<A>{
            class ExtraWrapperClass{  // this somehow changes the meaning.. 1 level further away from <A>
                A myA;     // class "A"
                class A{   // class "A"
                    A myA; // class "A" ???? No longer obscuring??
                }
            }
        }
      /// runs the code for proof
        public static void main(String [] args)
        {
            new Test().worksWith_Javac_And_Netbeans();
            new Test().OnlyWorksInEclipse();
            new Test().withExtraClass();
        }
        private void worksWith_Javac_And_Netbeans() {
            Foo<String> theFoo = new Foo<String>();
            theFoo.myA = "Hi";
            Foo<String>.A theA = theFoo.new A();
            theA.myA = "Hi";
            System.out.println("Netbeans/java says Foo's \"myA\" is :" + theFoo.myA.getClass().getCanonicalName());
            System.out.println("Netbeans/java says Foo.A's   \"myA\" is :" + theA.myA.getClass().getCanonicalName());
        }
    
        private void OnlyWorksInEclipse() {
    //         Foo<String> theFoo = new Foo<String>();
    //         theFoo.myA = theFoo.new A();
    //        Foo<String>.A theA = theFoo.new A();
    //        theA.myA =   theFoo.new A();
    //        System.out.println("Eclipse says Foo's \"myA\" is :" + theFoo.myA.getClass().getCanonicalName());
    //        System.out.println("Eclipse says Foo.A's   \"myA\" is :" + theA.myA.getClass().getCanonicalName());
        }
         private void withExtraClass() {
            Bar<String>.ExtraWrapperClass theExtra = new Bar<String>().new ExtraWrapperClass();
            theExtra.myA = theExtra.new A();
            Bar<String>.ExtraWrapperClass.A theA = theExtra.new A();
            theA.myA = theExtra.new A();
            System.out.println("The ExtraWrapperClass class's \"myA\" is :" + theExtra.myA.getClass().getCanonicalName());
            System.out.println("The ExtraWrapperClass.A class's \"myA\" is :" + theA.myA.getClass().getCanonicalName());
        }
    
    }
    This code works in Netbeans & Java (it works in Eclipse if you change which method is commented out).
    Anyhow, if <A> was treated a variable, then it makes sense:
        class Foo<A>{
                A myA;      // generic type "A" // makes sense, Variables obscure Types
                class A{    // class "A"
                    A myA;  // generic type "A" // makes sense, Variables obscure Types
                }
        }
    That code would be similar to how Variables obscure a Type in this example without generics:
    public class FooBar1 {
    
        static int [] x = new int[10];
        static class x{
                static int length = 5;
                static void printX()
                {
                    System.out.println(x.length); // prints 10, the variable "x" not the class (which was obscured)
                }
        }
    
        public static void main(String [] args)
        {
            new x().printX(); // have to use "new" to access the class - otherwise it would be obscured
        }
    
    }
    But then
    public class FooBar2 {
    
        static int [] x = new int[10];
        static class ExtraWrapperClass{
            static class x{
                    static int length = 5;
                    static void printX()
                    {
                        System.out.println(x.length); // the variable "x[10]", not the class due to obscuring
                    }
            }
        }
    
        public static void main(String [] args)
        {
             ExtraWrapperClass.x.printX();
        }
    }
    But in the Generic example, adding an "extra wrapper class" made generic "A" no longer obscure the class "A"
        class Bar<A>{
            class ExtraWrapperClass{  // this somehow changes the meaning.. 1 level further away from <A>
                A myA;     // class "A"
                class A{   // class "A"
                    A myA; // class "A"  // if it was treated like a variable.. it should still obscure the class????
                }
            }
        }
    Which is completely different from how obscuring works if it WAS a variable.. for example, this is how obscuring SHOULD work, even if there is an extra class:
    public class FooBar2 {
    
        static int [] x = new int[10];
        static class ExtraWrapperClass{
            static class x{
                    static int length = 5;
                    static void printX()
                    {
                        System.out.println(x.length); // the variable "x[10]", not the class
                    }
            }
        }
    
        public static void main(String [] args)
        {
             ExtraWrapperClass.x.printX();
        }
    
    }
    Since Netbeans and Java are not consistent on obscuring.. i think they are wrong.
    Either
    1) the generics act like "variables" and consistently obscure types
    or
    2) the generics act like "types" and can therefore be shadowed by more localized types.

    (personally i would like a 3rd option)

    3) generics act like "types" and Therefore you CANNOT have a Type with the same name in scope.. like this:
    public class BadCode {
    
        class A{
           class ExtraWrapperClass{
               class A{} // ERROR, The nested type A cannot hide an enclosing type
           }   
        }
        class A{ } // also ERROR, Duplicate nested type A
    }
    would be similar to
    public class I_Wish_BadCode<A> {
    
        class ExtraWrapperClass{
           class A{} // I wish ERROR,
       }
     
        class A{ } // I wish ERROR,
    }
  • 5. Re: Generic - a Type or Variable?
    EJP Guru
    Currently Being Moderated
    This thread is similar to the one posted here
    It would be simpler for everybody to have just one thread, so I've moved the other one here and am locking this one.