Java并避免使用类似方法的对象的if语句

时间:2011-10-19 06:30:38

标签: java design-patterns

我有2个班级,例如A和B.
这些类有几个具有相同名称的getter / setter方法。

现在在代码中我执行以下操作:

if(obj.getClassName().equals(A.class.getName())){
   A a = (A) obj;
   String result = a.getInfo();
}
else if(obj.getClassName().equals(B.class.getName())){
   B a = (B) obj;
   String result = a.getInfo();
}

我想知道是否有办法调用getInfo来避免if语句 注意:我无法重构类以使用继承或其他东西 我只是感兴趣,如果在java中有一个技巧,以避免if语句。

8 个答案:

答案 0 :(得分:6)

除非你想使用反射,否则没有。 Java将发生的两种类型视为完全独立的相同方法(getInfo()),并采用完全独立的方法。

如果你有共性,你应该使用一个共同的超类或它们都继承的公共接口。您已经标记了“设计模式”这一问题 - 模式是使用该语言提供的工具来显示共性。

正如Eng.Fouad所示,无论如何使用instanceof更简单 - 更好,因为这意味着您的代码仍然适用于AB的子类。

你可以隔离这种丑陋,当然,把它放在一个地方 - 或者是一个可以用A或{{1}构建的外观类通过一个执行此检查的方法,然后从多个位置调用它。

答案 1 :(得分:1)

如果你不能使用继承并希望避免使用if语句(甚至使用instanceof)......那么......你能做的最好就是包裹检查,投射和调用避免代码重复的功能......否则就无法做到这一点。

答案 2 :(得分:1)

您需要reflection。这是我的完整例子。

A类

 package a;
    public class A {
        String info;
        public String getInfo() {
            System.out.println("A getInfo");
            return info;
        }
        public void setInfo(String info) {
            this.info = info;
        }
    }

B类

package a;
public class B {
    String info;
    public String getInfo() {
        System.out.println("B getInfo");
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}

测试类

package a;
import java.lang.reflect.Method;
public class TestAB {
    public static void main(String[] args) {
        A a= new A();
        doSth(a);
    }
    private static void doSth(Object obj) {
        Class c = obj.getClass();
        Method m;
        try {
            m = c.getMethod("getInfo", new Class[] { });
            String result = (String) m.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

见这一行:

Class c = obj.getClass();

m = c.getMethod("getInfo", new Class[] { });

String result = (String) m.invoke(obj);

没有if陈述

答案 3 :(得分:1)

如果obj声明为A或B,则可以使用重载方法。 (关于类型安全的一个很好的论据。)这是一个测试,说明了这一点:

import static org.junit.Assert.*;

import org.junit.Test;

public class FooTest {

    class A {
        public String getInfo() {
            return "A";
        }
    }

    class B {
        public String getInfo() {
            return "B";
        }
    }

    public String doBarFor(A a) {
        return a.getInfo();
    }

    public String doBarFor(B b) {
        return b.getInfo();
    }

    public String doBarFor(Object obj) {
        throw new UnsupportedOperationException();
    }

    @Test
    public void shouldDoBarForA() {
        A a = new A();
        assertEquals("A", doBarFor(a));
    }

    @Test
    public void shouldDoBarForB() {
        B b = new B();
        assertEquals("B", doBarFor(b));
    }

    @Test(expected = UnsupportedOperationException.class)
    public void shouldFailIfDeclaredAsObject() {
        Object a = new A();
        assertEquals("A", doBarFor(a)); // exception thrown
    }
}

答案 4 :(得分:0)

怎么样:

String result = null;

if(obj instanceof A)
{
    result = ((A) obj).getInfo();
}
else if(obj instanceof B)
{
    result = ((B) obj).getInfo();
}

答案 5 :(得分:0)

如果这是您想要实现的目标,请参阅:this tutorial

答案 6 :(得分:0)

如果obj是对象,则需要检查。如果您不想使用if语句,可以尝试只是转换并捕获异常:

String result = null;
try {
    result = ((A)obj).getInfo();
}
catch(ClassCastException e1) {
    try {
        result = ((B)obj).getInfo();
    }
    catch(ClassCastException e2) {
         // do something else
    }
}

你可以做的另一件事是让两个类都实现一个接口,然后只检查那个接口,如:

public interface HasInfo
{
    public String getInfo();
}

然后在A和B的类定义中添加implements HasInfo。然后您可以检查(或转换)到HasInfo

答案 7 :(得分:0)

在Java中,您可以使用点作为范围解析运算符和静态方法。尝试这样的事情:

String a_info = A.getInfo();
String b_info = B.getInfo();

对于对象,如果两个接口实际上具有相同参数和相同返回类型的相同方法,为什么必须区别对待它们?看看here,了解更深入的问题。

祝你好运。