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

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);
}
}

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.

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

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.

Related

How can I get a variable of a class from an abstract class?

if I have an abstract class and a class that extends it, how can I get variable of the class that extends it to the class that is extended, something like this:
abstract class A {
void getVariable () {
//get *variable* from class B and print it out
}
}
class B extends A {
int variable = 5;
}
You cannot access variable field from child class directly but you can do like this
abstract class A {
abstract int getVariable ();
void anotherMethod() {
System.out.println("Variable from child: " + getVariable());
}
}
class B extends A {
int variable = 5;
#Override
int getVariable() {
return variable;
}
}
Forget about variables: What you might inherit and override is behaviours (=methods). Try this:
abstract class A {
protected abstract int getVariable ();
}
class B extends A {
private int variable = 5;
protected int getVariable ()
{
return variable;
}
}
class C extends A {
protected int getVariable ()
{
return 0; // This class might decide not to define its own variable.
}
}
variable is only known to class B. Its superclass A has no knowledge of it. If you move variable to the superclass A and don't mark it private, then you can access it from B.

How to modify superclass variable from subclass?

In C++ I could use 1 class throughout multiple files and when I modify a value using a function from one file, it would change that value globally.
In Java every file has to have it's own class; when I change a value using a method from one file, it does not change this value globally.
For example in C++ the files might look like this:
someClass.h
class someClass{
private:
int x;
public:
//Constructor
someClass(){
x = 5;
}
void changeVariable(); //Declaring function for later
}
main.cpp
int main(){
someClass cClass;
cClass.changeVariable(); //Call function
cout << x; //outputs 6
}
fileA.cpp
void someClass::changeVariable(){
x = 6; //x is changed to 6 globally.
}
In Java:
someClass.java
public class someClass {
int x;
//Constructor
public someClass() {
x = 5;
}
main.java
public class main {
public static void main() {
someClass cClass = new someClass();
subClass cSub = new subClass();
cSub.changeVariable();
System.out.print(x); //outputs 5
}
}
fileA.java
public class fileA extends someClass {
void changeVariable() {
x = 6; //x is changed to 6 only for fileA
}
}
My question is how can I change a variable from the sub class so that the variable is changed globally (For Java). Sorry if the question is still confusing.
Try with this:
public class someClass {
static int x;
//Constructor
public someClass() {
x = 5;
}
That a variable where static means that its value is common for all objects of the same class. That only one variable x is created for all, not one for each object.
Read that answer if you want a good explication of what static means:
What does the 'static' keyword do in a class?
Expose a function. setXyz in parent
public class someClass {
int x;
//Constructor
public someClass() {
x = 5;
}
public void setX(int n){
this.x = n;
}
}
public class fileA extends someClass {
void changeVariable() {
setX(6);
}
No need for static variable, this is the most equivalent thing you can do in Java:
public abstract class SomeClass {
protected int x = 5;
public abstract void changeVariable();
}
public class FileA extends SomeClass {
#Override
public void changeVariable() {
x = 6;
}
}
SomeClass doesn't have to be abstract of course, but you would have to implement it's changeVariable method.
Also x cannot be private, it has to be protected, so that it can be accessed by subclasses.

How to initialize a protected final variable in a child class of an abstract parent in Java?

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?
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.
In my personal oppinion, your problems hints towards a flaw in design.
But to answer your question. If absolutly 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.
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?

How To Cast An Inherited Encapsulated Property To Expose Methods Of Subclass - Java

In Java I have an abstract base class, let's say WrapX, which contains a property of a type, say X (think Decorator DP). This class presents a method to call a specific method on the encapsulated X:
public abstract class WrapX{
protected X instance;
public WrapX(X x){
this.instance = x;
}
public void foo(){
instance.foo();
}
}
public class X {
public void foo(){
System.out.println("foo");
}
}
There is then a class called Y that extends from X and provides an additional method:
public class Y extends X {
public void bar(){
System.out.println("bar");
}
}
Then naturally I have created WrapY that can be used as a decorated type over the type Y:
public class WrapY extends WrapX{
...
public void bar(){
instance.bar();
}
}
So herein lies the issue. WrapY has inherited the instance property of type X from its parent WrapX. As far as Eclipse is concerned, instance is of type X and so will complain that it contains no method .bar().
Fair enough of course, but how then in this subclass can we implicitly cast the instance to an instance of Y (a valid subclass of the initial type X)... WITHOUT the need for explicit cast ascriptions littering the code, or variable shadowing?
If I just had this in the constructor:
public WrapY(Y y){
this.instance = y;
}
Eclipse still complains that .bar() is not a method of type X because I guess it cannot infer for certain that WrapY(Y y) will be used prior to construct the WrapY instance:
public void bar(){
instance.bar(); // ERROR
}
Here is the current approach I have, littered with casts:
public WrapY(Y y){
(Y)instance = y;
}
public void bar(){
((Y)instance).bar();
}
I haven't come across this particular type of architectural problem in my experience before, file it under 'Decorator-Based-Inheritance-Type-Casting'(!)... Please enlighten me as to how I can model this in a better way.
Another issue is that, if in future someone extends WrapY, the type of instance their class inherits will be the natural (uncasted) type of X, when they may reasonably assume it should be of type Y.
Thanks
You could make your Wrap class generic, for example:
public abstract class Wrap<T extends X>{
protected T instance;
public Wrap(T x){
this.instance = x;
}
public void foo(){
instance.foo();
}
}
public final class WrapY extends Wrap<Y> {
public WrapY(Y y) {
super(y);
}
public void bar(){
instance.bar();
}
}
Then for instances of WrapY, instance will be a Y.
Update:
If you want to inherit from WrapY, too (and address your last issue of the wrapped type being the most appropriate), do:
public class WrapY<U extends Y> extends Wrap<U> {
public WrapY(U y) {
super(y);
}
public void bar(){
instance.bar();
}
}

Object Oriented Class Communication

I have a Java assessment that gets marked by a robot. Whenever I upload my assignment it shows a screen like this.
A good object-oriented design places each method into the most appropriate
class. The most appropriate class for a method should be the same class as
the data fields that that method needs to access. If you don't place a method
into the right class, then this will most likely increase the amount of
communication that is required between your classes.
The score below measures the amount of communication between your classes. A
lower score is better.
19 method invocations between classes
7 arguments passed between classes
15 results returned between classes
Amount of communication = invocations + 2*inputs + 2*outputs = 63
Now what exactly does "method invocations between classes", "arguments passed between classes" and "results returned between classes" mean?
Method invocations between classes
As your class contains their own methods if you want to call the method from another class you have to use an instance of this class.
For example :
class A{
public void methodA(){
  }
}
class B{
public void methodB(){
}
}
If I want to call methodA() from the class B I must use this:
public void methodB(){
A a = new A();
a.methodA(); // method invocation between classes
}
Argument passed between classes
This time methodA() will need an argument, and B as a field which could be used as argument.
class A{
public void methodA(int argument){
  }
}
class B{
private int fieldB = 42;
public void methodB(){
}
}
To call methodA() from B you will pass an argument from a class to another.
public void methodB(){
A a= new A();
a.methodA(fieldB); //Argument passed between classes
}
Results returned between classes
And now methodA() returns a result this is the code.
class A{
public int methodA(){
return 42;
}
}
class B{
private int fieldB;
public void methodB(){
}
}
To use/handle the returned value of the methodA() from the class B you'll have to do this:
public void methodB(){
A a= new A();
fieldB = a.methodA(); //Result returned between classes
}
I'd have to say:
method invocations between classes
Suppose you have classes X and Y. This would be any time class X calls some method on class Y.
e.g.,
class Y
{
public void foo() { }
}
class X
{
public void someMethod()
{
Y y = new Y();
y.foo();
}
}
arguments passed between classes
Could possibly mean one of two things.
Either you are accessing a field of another class directly.
class Y
{
public int number;
}
class X
{
public void someMethod()
{
Y y = new Y();
int yNum = y.number;
}
}
Or a method was called where arguments are supplied. (most likely case)
class Y
{
public void foo(int arg) { }
}
class X
{
public void someMethod()
{
Y y = new Y();
y.foo(56);
}
}
results returned between classes
Received a value from a method of another class that returned a value. e.g., getters or other methods.
class Y
{
public int foo() { return 42; }
private int number;
public int getNumber() { return number; }
}
class X
{
public void someMethod()
{
Y y = new Y();
int yFoo = y.foo();
int yNumber = y.getNumber();
}
}

Categories