Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (536)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Generics Questions / BUG ?  (Read 2398 times)
0 Members and 1 Guest are viewing this topic.
Offline zero

Junior Member





« Posted 2006-10-17 02:07:42 »

I playing around with generics and have the following four Java Objects (2 interfaces + 1 abstract class + 1 enum), and an obscure error message. I hope anyone here can explain the reason or maybe even agree with me that it could be a bug:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
interface Scalar<T> {
    public abstract T    getValue();    
    public abstract void setValue(T value) throws UnsupportedOperationException, NullPointerException;    
}

interface Vector<T> {
    T    getElement(int index) throws IndexOutOfBoundsException;
    void setElement(int index, T value) throws UnsupportedOperationException, IndexOutOfBoundsException, NullPointerException;    
}


abstract class Vector2<T> implements Vector<T> {
   
    public static enum Elements {
        X {
            <T> Scalar<T> get(final Vector2<T> source) {
                return new Scalar<T>() {
                    public T    getValue()        { return source.getElement(0);        }
                    public void setValue(T value) {        source.setElement(0, value); }
                };
            }
        },
        Y {
            <T> Scalar<T> get(final Vector2<T> source) {
                return new Scalar<T>() {
                    public T    getValue()        { return source.getElement(1);        }
                    public void setValue(T value) {        source.setElement(1, value); }
                };
            }            
        };
       
       
        abstract <T> Scalar<T> get(final Vector2<T> source);
    }

}


Now, l added a single method to the Vector2 class:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
// Compiler Error:
//incompatible types
//found   : Scalar<T>
//required: Scalar<T>
// lines
//this.x = x.get(Vector2.this);  
//this.y = y.get(Vector2.this);    
public Vector2<T> get(Elements x, Elements y) {

    final class Swizzle<T> extends Vector2<T> {

        private final Scalar<T> x, y;

        Swizzle(final Vector2.Elements x, final Vector2.Elements y) {
            this.x = x.get(Vector2.this);
            this.y = y.get(Vector2.this);
        }

        public T    getElement(int index)      { return this.x.getValue();  }
        public void setElement(int index, T x) {        this.x.setValue(x); }

    }  

    return new Swizzle<T>(x, y);
}


Note, that I am somehow scared by the error message part: found: Scalar<T>, required: Scalar<T>

Then, I thought a local class is like a non-static inner class and therefore implicitly derives the generic type T, but the following also doesn't work too:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
// Compiler Warning/Error with Xlint:unchecked:
// warning: [unchecked] unchecked conversion
// found   : Swizzle
// required: Vector2<T>
// lines:
// return new Swizzle(x, y);  
public Vector2<T> get(Elements x, Elements y) {

    final class Swizzle extends Vector2<T> {

        private final Scalar<T> x, y;

        Swizzle(final Vector2.Elements x, final Vector2.Elements y) {
            this.x = x.get(Vector2.this);
            this.y = y.get(Vector2.this);
        }

        public T    getElement(int index)      { return this.x.getValue();  }
        public void setElement(int index, T x) {        this.x.setValue(x); }

    }  

    return new Swizzle(x, y);
}


Again, I was confused that required: Vector<T> but found is Swizzle. Note that Swizzle derives from Vector2<T> and therefore should be compatible!

Finally, I used an inner class and it worked fine, but I'd preferred a local class:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
// Works but I'd prefer a local class instead of an inner class:    
final class Swizzle2 extends Vector2<T> {

    private final Scalar<T> x, y;

    Swizzle2(final Vector2.Elements x, final Vector2.Elements y) {
        this.x = x.get(Vector2.this);
        this.y = y.get(Vector2.this);
    }

    public T    getElement(int index)      { return this.x.getValue();  }
    public void setElement(int index, T x) {        this.x.setValue(x); }
}                  

public Vector2<T> get(Elements x, Elements y) {
    return new Swizzle2(x, y);  

}



Thanks for comments,
 Michael
Offline zero

Junior Member





« Reply #1 - Posted 2006-10-17 02:18:20 »

Btw. I know that the code make no sense  Roll Eyes
Offline cylab

JGO Ninja


Medals: 38



« Reply #2 - Posted 2006-10-17 12:20:18 »

Your T is not T Wink
Remove the leading <T> from your get methods in the Elements enum.

And try the generics quiz: http://www.grayman.de/quiz/java-generics.quiz

Mathias - I Know What [you] Did Last Summer!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline zero

Junior Member





« Reply #3 - Posted 2006-10-17 12:44:26 »

Removing the leading <T> from the enum methods would make the class useless since it cannot return Scalar<T>. Note that enums don't derive the <T> because they are implictly static inner classes.

Further IMO, the T is the right T.

<T> T foo(T t); returns exactly the passed T, because its a generic method, which has nothing todo with the class.
=> the T of the returned scalar is the same T as in the Vector2 class (Vector2.this) taken as argument:
this.x = x.get(Vector2.this);

Btw the generics quiz doesn't contain an example about local or inner classes, so it doesn't fit here.
Offline zero

Junior Member





« Reply #4 - Posted 2006-10-17 13:11:44 »

since the aboe code was uneccesary complex for showing the problem or potential compiler bug, here is a simpler version:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
abstract class Foo<T> {
   
    enum Bar {
        A,B;
       
        <T> T get(T t) { return t; }        
    }
   
    abstract T get();
   
   Foo<T> error(Bar bar) {
       
        class Error<T> extends Foo<T> {
           
            final T t;
           
            Error(final Bar bar) {
                // error: incompatible types, but Bar.get is a generice method,
               // which returns the same as the specified as argument.
               this.t = bar.get(Foo.this.get());
            }
           
            T get() { return t; }            
        }
               
        return new Error<T>(bar); //
   }
   
   
   Foo<T> error2(Bar bar) {
       
        class Error2 extends Foo<T> {
           
            final T t;
           
            Error2(final Bar bar) {
                this.t = bar.get(Foo.this.get());
            }
           
            T get() { return t; }            
        }
               
        // works so the above def. seems legal, so the T must be the T of Foo.this
       //return null;
       
        // warning: unchecked conversion, but why? Error2 extends Foo<T>
       return new Error2(bar);
    }
   
   
    class Works extends Foo<T> {

        final T t;

        Works(final Bar bar) {
            this.t = bar.get(Foo.this.get());
        }

        T get() { return t; }
    }    
   
   Foo<T> works(Bar bar) {
        // works, but the above code should work too!!
       // and I wanted to use a local not an innver class.
       return new Works(bar);
    }  
}
Offline cylab

JGO Ninja


Medals: 38



« Reply #5 - Posted 2006-10-17 13:12:23 »

Removing the leading <T> from the enum methods would make the class useless since it cannot return Scalar<T>. Note that enums don't derive the <T> because they are implictly static inner classes.

Further IMO, the T is the right T.

<T> T foo(T t); returns exactly the passed T, because its a generic method, which has nothing todo with the class.
=> the T of the returned scalar is the same T as in the Vector2 class (Vector2.this) taken as argument:
this.x = x.get(Vector2.this);
Sorry, was a bit quick to answer, I did'nt try it first. I meant the T is not the right T from the compiler perspective regarding the methods signature. However, if you change Swizzle<T> extends Vector2<T> to Swizzle extends Vector2<T> it works, since you introduced a second type parameter T by Swizzle<T>

Btw the generics quiz doesn't contain an example about local or inner classes, so it doesn't fit here.
Yes I know, but it's fun and interesting. Wink

Mathias - I Know What [you] Did Last Summer!
Offline cylab

JGO Ninja


Medals: 38



« Reply #6 - Posted 2006-10-17 13:15:03 »

since the aboe code was uneccesary complex for showing the problem or potential compiler bug, here is a simpler version:
Same here, in class Error<T> extends Foo<T> you have two Ts: a new type parameter (in class Error<T>) and the original T (in  Foo<T>)

Mathias - I Know What [you] Did Last Summer!
Offline zero

Junior Member





« Reply #7 - Posted 2006-10-17 13:21:06 »

Sorry, was a bit quick to answer, I did'nt try it first. I meant the T is not the right T from the compiler perspective regarding the methods signature. However, if you change Swizzle<T> extends Vector2<T> to Swizzle extends Vector2<T> it works, since you introduced a second type parameter T by Swizzle<T>

Isn't your solution equal to my second examples, which lead to the compiler warning: unchecked conversion, although Swizzle/Error2 derives from Vector2<T>/Foo<T> ?
Offline tortoise

Junior Member




<3 Shmups


« Reply #8 - Posted 2006-10-17 13:31:48 »


Damn, German is required for Java generics? No wonder they are so confusing Smiley
Offline cylab

JGO Ninja


Medals: 38



« Reply #9 - Posted 2006-10-17 13:35:12 »

Isn't your solution equal to my second examples, which lead to the compiler warning: unchecked conversion, although Swizzle/Error2 derives from Vector2<T>/Foo<T> ?
Actually yes and it does not give me compiler warnings... hmm. I am using 1.5_05 on windows

Mathias - I Know What [you] Did Last Summer!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline zero

Junior Member





« Reply #10 - Posted 2006-10-17 13:40:58 »

Actually yes and it does not give me compiler warnings... hmm. I am using 1.5_05 on windows

Oh great, that's it!

I used Java SE 6.0 Release 1 Developer Preview 6, which is based on SUN's JDK 1.6.0_b88.
I switched to Java 5 and the warning was gone :-)
(Both on MacOS X)

Guess I have to fill a bug report for Java 6..
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CogWheelz (13 views)
2014-07-30 21:08:39

Riven (21 views)
2014-07-29 18:09:19

Riven (14 views)
2014-07-29 18:08:52

Dwinin (12 views)
2014-07-29 10:59:34

E.R. Fleming (32 views)
2014-07-29 03:07:13

E.R. Fleming (12 views)
2014-07-29 03:06:25

pw (42 views)
2014-07-24 01:59:36

Riven (42 views)
2014-07-23 21:16:32

Riven (29 views)
2014-07-23 21:07:15

Riven (30 views)
2014-07-23 20:56:16
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!