Unhandled Exception
Unhandled Exception

Reputation: 1513

"error: cannot find symbol " when calling a Method defined using Generics

After reading through the Generics info I am attempting a simple sample and encountering the following error.

MyClass.java:32: error: cannot find symbol
System.out.println("X = " + temp.x);
^
symbol: variable x
location: variable temp of type T
where T is a type-variable:
T extends Object declared in method tryThis(T)
1 error

Without the reference to "temp.x" it compiles which leads me to believe the definition is correct but possibly the way the variable is referenced is the issue. Or it could be the actual implementation is wrong. Not sure.

The main class has a method which can be called by either of the 2 inner classes. When called, the method attempts to access the variable specific to the inner class that called it.

public class MyClass {
    public class InnerClass1 {
        int x = 100;
        public void runThis() {
            tryThis(this);
            return;
        }
    }

    public class InnerClass2 {
        int x = 200;
        public void runThis() {
            tryThis(this);
            return;
        }
    }

    public static void main(String[] args) {
        MyClass x = new MyClass();
    }

    private <T> void tryThis(T temp) {
        System.out.println("X = " + temp.x);
    }
}

Upvotes: 1

Views: 2154

Answers (3)

Ian2thedv
Ian2thedv

Reputation: 2701

In order to get the value x from each class dynamically, you can define a common interface or abstract class for InnerClass1 and InnerClass2 to implement or extend. This allows the inheritance of methods and variables. Seeing that both holds a value of type T, let us create an interface called ValueHolder<T>:

interface ValueHolder<T> {
    public T getValue();
}

Both the InnerClass1 and InnerClass2 will need to implement this interface:

public class InnerClass1 implements ValueHolder<Integer> {
    private int x = 100;

    @Override
    public Integer getValue() {
        return this.x;
    }
}

public class InnerClass2 implements ValueHolder<String> {
    public String x = "200";

    @Override
    public String getValue() {
        return this.x;
    }
}

As you can see, InnerClass1 implements ValueHolder<Integer>, meaning the inherited getValue methods return type will be Integer. The same goes for InnerClass2, which implements ValueHolder<String>.

Change your tryThis as follows:

private <T> void tryThis(ValueHolder<T> temp) {
    System.out.println("Value = " + temp.getValue());
}

Now each value can be printed like this:

Generics g = new Generics();
g.tryThis(new InnerClass1());
g.tryThis(new InnerClass2());

Output:

X = 100
X = 200

Upvotes: 1

fhissen
fhissen

Reputation: 357

T in

private <T> void tryThis(T temp)</code>

is just a placeholder for any class. The compiler knows nothing more about it, so it knows nothing about the symbol x as well.

To accomplish what you are trying to do, you would need something like this:

public class Generics {

    abstract class MyClass {
        int x;
    }

    public class InnerClass1 extends MyClass {
        InnerClass1() {
            super.x = 100;
        }

        public void runThis() {
            tryThis(this);
            return;
        }
    }

    public class InnerClass2 extends MyClass {
        InnerClass2() {
            super.x = 200;
        }

        public void runThis() {
            tryThis(this);
            return;
        }
    }

    public static void main(String[] args) {
        Generics x = new Generics();

        x.new InnerClass1().runThis();
        x.new InnerClass2().runThis();
    }

    private <T extends MyClass> void tryThis(T temp) {
        System.out.println("X = " + temp.x);
    }

}

However, you would not need Generics for this specific case:

    private void tryThis2(MyClass temp) {
        System.out.println("X = " + temp.x);
    }

would accomplish the same.

Generics are very complex, although they look easy to use.

Upvotes: 0

tobias_k
tobias_k

Reputation: 82899

symbol: variable x
location: variable temp of type T
where T is a type-variable:
T extends Object declared in method tryThis(T)
^^^^^^^^^^^^^^^^

Without further specification, e.g. <T extends InnerClass1>, the only thing that is known about T within that method is that it extends Object, and for Object, the attribute x is not defined.

Maybe you should define a common super-class for those two classes, and declare x in that super-class.

Upvotes: 1

Related Questions