Can a method calls it own class? - java

I'm working on a project where I use Foo which is class that's implemented with an interface, FooExpression, and a separate concrete class called Replacement.
Replacement class uses hashmap:
private Map<Foo, FooExpression> replacementMap;
Replacement class uses put method:
public Expression put(Foo foo, FooExpression exp) {
return replacementMap.put(foo, exp);
}
The Replacement class has a method called get:
public FooExpression get(Foo foo) {
return replacementMap.get(foo);
}
The Foo class has a method, applyReplacement:
#Override
public FooExpression applyReplacement(Replacement r) {
Foo foo = new Foo(name);
FooExpression e = r.get(foo);
return e;
}
The Foo class uses an instance variable:
private String name;
The Foo class uses an equal and hashCode():
#Override
public boolean equals(Object o) {
if (!(o instanceof Foo)) {
return false;
} else {
return name.equals(o);
}
}
#Override
public int hashCode() {
return name.hashCode() + 41;
}
The FooExpression interface uses the applyReplacement method:
FooExpression applyReplacement(Replacement r);
Everytime I used applyReplacement method it returns null, simply because of the "new" instantiation.
I'm just wondering if there's a way to implement the Foo without erasing the existing value from the Replacement class? And I can't use generics for this one.

Your equals() method is wrongly implemented, currently it checks:
if o instanceof Foo
and if name.equals(o)
But o is in this case an instance of Foo. Your name though is an instance of String. This will never return true as a String will never be equal to a Foo.
You have to change your equals method accordingly:
#Override
public boolean equals(Object o) {
if (!(o instanceof Foo)) {
return false;
}
Foo foo = (Foo) o;
return name.equals(foo.name);
}
Which can also be simplified to:
#Override
public boolean equals(Object o) {
return o instanceof Foo && name.equals(((Foo) o).name);
}

Related

Java generic method Cannot resolve method 'getX()' in 'T'

Say I have a couple of Objects (=classes) which each has a method getX():
public class A{
/* some code */
public float getX(){}
}
public class B{
/* some code */
public float getX(){}
}
Now I want to write a generic static method as the following:
public static <T> boolean isOverlaps(T obj) {
if (obj == null || (!obj.getClass().isInstance(A.class) && !obj.getClass().isInstance(B.class)))
return false;
return obj.getX() >= 0 && /*some logic*/; // here it falls
}
IDE says:
Cannot resolve method 'getX()' in 'T'
How can I resolve the method properly without casting (since it is a generic method)? Is it even possible?
You need an interface to let Java know that T has the desired function:
public interface I {
float getX();
}
public class A implements I {
/* some code */
public float getX(){
return 1.0f;
}
}
public class B implements I {
/* some code */
public float getX(){
return 2.0f;
}
}
public static <T extends I> boolean isOverlaps(T obj) {
return obj.getX() >= 0 && /*some logic*/;
}
Or, a bit simpler without the unnecessary type variable:
public static boolean isOverlaps(I obj) {
return obj.getX() >= 0 && /*some logic*/;
}
Using an interface is the preferred way to solve this, but the statement "you need an interface" is incorrect.
You can achieve this without an interface too. In some situations (i.e. where you can't modify A or B), this may be the best you can do.
public static boolean isOverlaps(Object obj) {
float x = -1;
if (obj instanceof A) {
x = ((A) obj).getX();
}
else if (obj instanceof B) {
x = ((B) obj).getX();
}
return x >= 0 && /*some logic*/;
}
public static <T> boolean isOverlaps(T obj) {
This isn't really a generic method. OK, it is a generic method, because it has a type variable; it's just not a usefully generic method. You can pass anything to it: it's essentially equivalent to:
public static boolean isOverlaps(Object obj) {
That is, you can't access anything inside that method which isn't a method on Object.
If you want to use this, and you can't use the common interface approach, you could do an instanceof chain:
public static boolean isOverlaps(Object obj) {
if (obj instanceof A) {
return /* logic */;
} else if (obj instanceof B) {
// Do something.
return /* logic */;
}
return false;
}
The problem with this is that you're losing the compile-time safety of not being allowed to pass things other than As and Bs to it (e.g. you could call isOverlaps("Hello world!"), which is presumably nonsensical).
It's actually better to define two overloads:
public static boolean isOverlaps(A obj) { return /* logic */; }
public static boolean isOverlaps(B obj) { return /* logic */; }
because now trying to pass in anything other than an A or a B results in a compile-time error; but it's a compile-time error at the call site, not in these methods.
If /* logic */ depends on some property which can be derived from A and B, e.g. a getter, you can consolidate the repeated logic into a helper:
public static boolean isOverlaps(A obj) { return helper(obj.getX()); }
public static boolean isOverlaps(B obj) { return helper(obj.getX()); }
private static boolean helper(SomeType value) {
return /* logic */
}

How to cast integer to some generic type?

I have a class MyClass and its super-class MySuperClass.
MySuperClass is from a standard library, so its codes cannot be changed.
As per the user requirement, the method name myMethod() of MyClass cannot be changed as well.
Unluckily, the same name MyClass is already in MySuperClass, and those codes are not what I want. I used #Override to override those codes (Thanks for the help from Matteo NNZ who suggested me for this fix in the case of having various generic types).
However, I need to cast keyInt to type K such that I can call the mySubMethod(). Below is my code:
MyClass
public class MyClass<K,V> extends MySuperClass {
// the name "myMethod" are not allowed to be modified
public boolean myMethod(K key) { // if key is NOT integer, Main.java will call this method
mySubMethod(key);
return false;
}
#Override // This is a fix; To Override myMethod(int index) of MySuperClass.
public boolean myMethod(int keyInt) { // if key is integer, Main.java will call this method
K key = (K) keyInt; // <-- I have error here
mySubMethod(key);
return false;
}
public boolean mySubMethod(K key) {
System.out.println("I want to call this");
return false;
}
}
MySuperClass
public class MySuperClass { // codes of MySuperClass are not allowed to be modified
public boolean myMethod(int index) {
System.out.print("Shouldn't be called.");
return false;
}
}
To call MyClass, in Main.java I will create new instances for either MyClass<Integer, String> or MyClass<String, String>. But currently I got error message "Cannot cast from int to K".
I tried to fix the error by using if(key instanceof Integer){ /** blahblahblah */}, but it doesn't work since KeyInt is already an integer when the method is called. How can I fix this?
Do you want this result?
public class MyClass<K,V> extends MySuperClass {
// the name "myMethod" are not allowed to be modified
public boolean myMethod(K key) { // if key is NOT integer, Main.java will call this method
mySubMethod(key);
return false;
}
#Override // This is a fix; To Override myMethod(int index) of MySuperClass.
public boolean myMethod(int keyInt) { // if key is integer, Main.java will call this method
// K key = (K) keyInt; // <-- I have error here
mySubMethod(keyInt);
return false;
}
public <T> boolean mySubMethod(T key) {
System.out.println("I want to call this");
return false;
}
}

Turning a method implemented in superclass into abstract

I have a Java program with the following classes in it
public class A{
protected String name;
...
#Override
public boolean equals(Object obj){
if(!(obj instanceof A)){
return false;
}
A a = (A)(obj);
return a.name.equals(this.name);
}
}
public abstract class B extends A{
#Override
public boolean equals(Object obj){
return equals2(obj);
}
public abstract boolean equals2(Object obj);
}
public class C extends B{
private String data;
...
#Override
public boolean equals2(Object obj){
if(!(obj instanceof C)){
return false;
}
C c = (C)(obj);
if(c.data.equals(this.data)){
return c.name.equals(this.name);
}else{
return false;
}
}
}
Is there a way to force all classes extending class B to implement their own equals methods without having to use equals2 like the example?
Thanks
The only way I can think of is to throw an exception in Bs equals:
public abstract class B extends A {
#Override
public boolean equals(Object obj) {
throw new UnsupportedOperationException();
}
}
This will ensure that sub-classes of B that fail to override equals will not fallback to A's implementation of equals.
Unfortunately, this will result in run-time exceptions, as opposed to compile time errors, which are preferable.
Off the top of my head, you could have the abstract class B throw an exception in its equal() method:
public abstract class B extends A{
#Override
public boolean equals(Object obj){
throw new UnsupportedOperationException("add your own implementation");
}
public abstract boolean equals2(Object obj);
}
Then, anyone subclass of B which attempted to default to the inherited equals method would not work, forcing them to implement their own version.

Cast type using an instance

The error:
CAP#1 is not a fresh type
The code:
public Boolean isAssigned(HttpServletRequest request, String name, Foo foo) {
Boolean isAssigned = false;
if ((foo.getClass()) request.getSession().getAttribute(name) != null) {
isAssigned = true;
}
return isAssigned;
}
What is the solution?
May not be what you are looking for but it answers the question in the title.
The Class<T> class has a cast method which can cast any object to its own type T. Obviously it will throw a ClassCastException if the object cannot be cast to that type.
public <T> T castTo(Class<T> t, Object o) {
return t.cast(o);
}
public <T> T castTo(T t, Object o) {
return (T) castTo(t.getClass(), o);
}
public void test() {
String s = "Hello";
Object b = s;
String c = castTo(String.class, b);
String d = castTo("Some String", b);
}
If you want to test whether
request.getSession().getAttribute(name)
is of type Foo and execute a method method on it afterwards you could simply try using instanceof and cast:
if (request.getSession().getAttribute(name) instanceof Foo) {
((Foo) request.getSession().getAttribute(name)).method();
}

How to refer to the outer class in another instance of a non-static inner class?

I'm using the Apache Commons EqualsBuilder to build the equals method for a non-static Java inner class. For example:
import org.apache.commons.lang.builder.EqualsBuilder;
public class Foo {
public class Bar {
private Bar() {}
public Foo getMyFoo() {
return Foo.this
}
private int myInt = 0;
public boolean equals(Object o) {
if (o == null || o.getClass() != getClass) return false;
Bar other = (Bar) o;
return new EqualsBuilder()
.append(getMyFoo(), other.getMyFoo())
.append(myInt, other.myInt)
.isEquals();
}
}
public Bar createBar(...) {
//sensible implementation
}
public Bar createOtherBar(...) {
//another implementation
}
public boolean equals(Object o) {
//sensible equals implementation
}
}
Is there syntax by which I can refer to other's Foo reference apart from declaring the getMyFoo() method? Something like other.Foo.this (which doesn't work)?
No.
The best way is probably what you suggested: add a getFoo() method to your inner class.
No, not possible without a getter. The 'this' keyword will always point to the current instance. I'm quite curious why you would want to do this... seems like you are doing composition in the wrong way.
public class Foo {
public Bar createBar(){
Bar bar = new Bar(this)
return bar;
}
}
public class Bar {
Foo foo;
public Bar(Foo foo){
this.foo = foo;
}
public boolean equals(Object other) {
return foo.equals(other.foo);
}
}
Since using Foo.this limits creation of the inner class (Foo myFoo = new Foo(); myFoo.new Bar(); to an instance I'd say this is much cleaner.
yes:
public class Foo {
public class Bar {
public Foo getMyFoo() {
return Foo.this;
}
}
public Foo foo(Bar bar) {
return bar.getMyFoo();
}
public static void main(String[] arguments) {
Foo foo1=new Foo();
Bar bar1=foo1.new Bar();
Foo foo=(new Foo()).foo(bar1);
System.out.println(foo==foo1);
}
}

Categories

Resources