在Java中转换为具体类和调用方法

假设我们有一个名为A的基类和一些子类( BCD等)。 大多数子类都有方法do()但基类没有。 AA类提供了一个名为getObject()的方法,它将创建一个BCD等的对象,但是将该对象作为类型A返回。

如果此方法可用,如何将返回的对象强制转换为具体类型并调用其do()方法?

编辑: 我不允许更改类A ,子类或AA ,因为我使用一个封闭的源API ..是的,它确实有一些设计问题,你可以看到。

我认为更好的想法是让A类将do()方法定义为抽象方法或具体的空方法。 这样你就不必做任何演员表了。

如果你不允许改变任何类,你可以定义一个类MyA extends A ,它定义了do()方法和MyBMyC ,…和一个基本上做AA所做的MyAA ,只是它返回MyBMyC类型的对象….

如果这不好,那么我没有看到另一种方法,而不是检查返回的对象是否为B类型并对B进行强制转换等等。

您可以使用instanceof进行测试并调用do()方法:

 A a = aa.getObject(); if (a instanceof B) { B b = (B) a; b.do(); } // ... 

假设A定义了do ,它不是私有的,你可以在没有强制转换的情况下调用它,无论AA返回的子类。 这是多态性的特征之一。 在运行时,解释器将使用do的正确(即实际类的实现)版本。

首先,使用do()作为抽象方法将Class A作为抽象类是更好的方法……

此外,如果你仍然想要你想要的方式……那么

做一个明确的演员。

B b = (B) a; // a is a casted back to its concrete type.

此外,您应该记住编译器的这一非常重要的行为

The Object Reference Variable of Super Type must have the method to be called, whether the Sub Type Object has or not.

例如:

 A a = new B(); 

要调用方法,对类型A的Object Reference Variable do() ,类A 必须具有 go()方法。

如果您不允许更改A但您可以更改子类,那么您可以使用方法do()创建一个接口,并让所有子类实现该接口。

 public interface Doer { public void do(); } public class B extends A implements Doer { //implement do method } //.. same for other subclass 

那你就不需要演员。 否则你需要一些明确的向下转发。

您在描述的内容在我看来就像您想要在Base class引用上调用Derived Class方法。

但是,为此,您还需要在base class使用您的方法。
所以,你需要在你的基类A声明你的方法do() 。如果你不想给一个实现,让它是抽象的,或者让它成为一个空方法..这没关系..

现在,如果你做同样的事情你正在解释..你不需要做一个类型转换..

因为,将根据which derived class object does your base class reference point to调用适当的Derived Class方法

 public abstract class A { public abstract void do(); } public class B extends A { public void do() { System.out.println("In B"); } } public class Test { public static void main(String[] args) { A obj = returnA(); obj.do(); // Will invoke class B's do() method } /** Method returning BaseClass A's reference pointing to subclass instance **/ public static A returnA() { A obj = new B(); return obj; } } 

好的,刚才看到你的编辑,你不能改变你的课程..

在这种情况下,您实际上需要根据返回的引用实例进行typecast

所以,在上面的main方法中,在A obj = returnA(); 这一行添加以下行: –

 if (obj instanceof B) { B obj1 = (B) obj; } 

但是,在这种情况下,您需要在每个子类上检查instanceof ..这可能是一个主要问题..

最好的方法是使用A类方法。 但是因为你不允许改变任何课程。 我建议你使用reflection在所有类周围创建一个包装器实例。

下面的类中的静态方法仅用于说明如何执行此操作。 你可以有单独的实例变量,它可以在E中包装A.

 public class E { public static void doMethod(A a) { Class class1 = a.getClass(); Method method; try { method = class1.getDeclaredMethod("doMethod", null);// B, C, D has doMethod method.invoke(a, null); // I know to many exceptions } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } 

第二个选项是您必须检查类型然后投射它的instance of

如果方法调用返回有问题的类的实例,则可以通过一些工作来完成此操作,这是您的具体问题(上图)。

 import static java.lang.System.out; public class AATester { public static void main(String[] args){ for(int x: new int[]{ 0, 1, 2 } ){ A w = getA(x); Chain.a(w.setA("a")).a( (w instanceof C ? ((C) w).setC("c") : null ); out.println(w); } } public static getA(int a){//This is whatever AA does. A retval;//I don't like multiple returns. switch(a){ case 0: retval = new A(); break; case 1: retval = new B(); break; default: retval = new C(); break; } return retval; } } 

测试类A

 public class A { private String a; protected String getA() { return a; } protected A setA(String a) { this.a=a; return this; }//Fluent method @Override public String toString() { return "A[getA()=" + getA() + "]"; } } 

测试B级

 public class B { private String b; protected String getB() { return b; } protected B setB(String b) { this.b=b; return this; }//Fluent method @Override public String toString() { return "B[getA()=" + getA() + ", getB()=" + getB() + "]\n " + super.toString(); } } 

测试类C.

 public class C { private String c; protected String getC() { return c; } protected C setC(String c) { this.c=c; return this; }//Fluent method @Override public String toString() { return "C [getA()=" + getA() + ", getB()=" + getB() + ", getC()=" + getC() + "]\n " + super.toString(); } } 

连锁课

 /** * Allows chaining with any class, even one you didn't write and don't have * access to the source code for, so long as that class is fluent. * @author Gregory G. Bishop ggb667@gmail.com (C) 11/5/2013 all rights reserved. */ public final class Chain { public static  _ a(K value) {//Note that this is static return new _(value);//So the IDE names aren't nasty } } 

连锁的助手类。

 /** * An instance method cannot override the static method from Chain, * which is why this class exists (ie to suppress IDE warnings, * and provide fluent usage). * * @author Gregory G. Bishop ggb667@gmail.com (C) 11/5/2013 all rights reserved. */ final class _ { public T a;//So we can reference the last value if desired. protected _(T t) { this.a = T; }//Required by Chain above public  _ a(K value) { return new _(value); } } 

输出:

  A [get(A)=a] B [get(A)=a, getB()=null] A [getA()=a] C [getA()=a, getB()=null, getC()=c)] B [get(A)=a, getB()=null] A [get(A)=a]