Java 当类名为字符串时强制转换为未知类型

Java 当类名为字符串时强制转换为未知类型,java,reflection,casting,Java,Reflection,Casting,这里,exam函数的参数是一个对象。但我想让论点是Horse。。。那么在“exam(hrt.cast(hritr.next())”方法调用中必须做哪些更改呢?我不想在callHorse()中显式使用类名Horse。。。那我该怎么办 谢谢您可能想看看泛型 public class ExampleClass { public static void main(String[] args) { // TODO Auto-generated method stub

这里,exam函数的参数是一个
对象
。但我想让论点是
Horse
。。。那么在“
exam(hrt.cast(hritr.next())
”方法调用中必须做哪些更改呢?我不想在
callHorse()
中显式使用类名
Horse
。。。那我该怎么办


谢谢

您可能想看看泛型

public class ExampleClass {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Horse hr1 = new Horse();
        Horse hr2 = new Horse();
        Horse hr3 = new Horse();
        Horse hr4 = new Horse();
        Set hrSet = new HashSet();
        hrSet.add(hr1);
        hrSet.add(hr2);
        hrSet.add(hr3);
        hrSet.add(hr4);
        Horse hr;
        String hor = "sher_pkg.Horse";
        callHorse(hrSet,hor);
    }
    public static void callHorse(Set xSet,String clsName){
        try {
            Class hrt = Class.forName(clsName);

            Iterator hritr = xSet.iterator();
            while(hritr.hasNext()){
                exam(hrt.cast(hritr.next()));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void exam(Object obj){ //I want to use exam(Horse hrr)
        System.out.println(obj);
    }
}
publicstaticvoidcallhorse(Set-xSet){
迭代器hritr=xSet.Iterator();
while(hritr.hasNext()){
考试(hritr.next());
}
}
公共静态无效检查(Horse obj){//我想使用检查(Horse hrr)
系统输出打印项次(obj);
}

当然,在您的示例中,您始终可以仅投射对象。我无法理解您为什么不想这样做。

您可能想看看泛型

public class ExampleClass {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Horse hr1 = new Horse();
        Horse hr2 = new Horse();
        Horse hr3 = new Horse();
        Horse hr4 = new Horse();
        Set hrSet = new HashSet();
        hrSet.add(hr1);
        hrSet.add(hr2);
        hrSet.add(hr3);
        hrSet.add(hr4);
        Horse hr;
        String hor = "sher_pkg.Horse";
        callHorse(hrSet,hor);
    }
    public static void callHorse(Set xSet,String clsName){
        try {
            Class hrt = Class.forName(clsName);

            Iterator hritr = xSet.iterator();
            while(hritr.hasNext()){
                exam(hrt.cast(hritr.next()));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void exam(Object obj){ //I want to use exam(Horse hrr)
        System.out.println(obj);
    }
}
publicstaticvoidcallhorse(Set-xSet){
迭代器hritr=xSet.Iterator();
while(hritr.hasNext()){
考试(hritr.next());
}
}
公共静态无效检查(Horse obj){//我想使用检查(Horse hrr)
系统输出打印项次(obj);
}

当然,在您的示例中,您始终可以仅投射对象。我无法理解您为什么不想这样做。

您可以在函数调用中显式强制转换-

public static void callHorse(Set<Horse> xSet) {
    Iterator<Horse> hritr = xSet.iterator();
    while (hritr.hasNext()) {
        exam(hritr.next());
    }
}
public static void exam(Horse obj) { //I want to use exam(Horse hrr)
    System.out.println(obj);
}

但是我不确定您在这里想要实现什么-如果您正在编写显式引用马的代码,为什么需要从字符串动态确定类类型?

您可以显式地在函数调用中强制转换-

public static void callHorse(Set<Horse> xSet) {
    Iterator<Horse> hritr = xSet.iterator();
    while (hritr.hasNext()) {
        exam(hritr.next());
    }
}
public static void exam(Horse obj) { //I want to use exam(Horse hrr)
    System.out.println(obj);
}

但是我不确定您在这里想要实现什么-如果您正在编写显式引用Horse的代码,为什么需要从字符串动态确定类类型?

首先,您的集合应该使用泛型或显式定义为仅包含Horse对象

    try {
            Class hrt = Class.forName(clsName);

            Iterator hritr = xSet.iterator();
            while(hritr.hasNext()){
                    exam((Horse)hrt.cast(hritr.next()));
            }
    } 
(最终集xSet,最终字符串clsName){
...}

解决了这个问题,您就解决了90%的问题。

首先,您的集合应该使用泛型或显式定义为仅包含Horse对象

    try {
            Class hrt = Class.forName(clsName);

            Iterator hritr = xSet.iterator();
            while(hritr.hasNext()){
                    exam((Horse)hrt.cast(hritr.next()));
            }
    } 
(最终集xSet,最终字符串clsName){
...}

解决了这个问题,您就解决了90%的问题。

看起来您的设计对Java来说是错误的,您无法直接完成您的要求


也许您需要重塑代码以使用访问者模式?否则,您需要解释您的需求,而不是您想要使用的解决方案。通过这种方式,我们可以告诉您适合您需求的Java解决方案。

看起来您的设计对Java来说是错误的,您无法直接完成您的要求


也许您需要重塑代码以使用访问者模式?否则,您需要解释您的需求,而不是您想要使用的解决方案。通过这种方式,我们可以告诉您适合您需求的Java解决方案。

我不确定在callHorse方法中避免引用“Horse”是否可能或可取。从ClassNotFoundException之后的printstacktrace判断,如果由于某种原因找不到该类,则会抛出一个硬错误

出于同样的原因,如果场景中的某个东西不是马,难道你不能直接投到“马”然后抓住classcastexception吗

你能解释一下为什么你需要传入类名而不是类吗


也许您也可以使用方法重载,但我必须对此进行测试,因为我不完全确定在这种情况下优先级是什么。

我不确定在callHorse方法中避免引用“Horse”是否可能或可取。从ClassNotFoundException之后的printstacktrace判断,如果由于某种原因找不到该类,则会抛出一个硬错误

出于同样的原因,如果场景中的某个东西不是马,难道你不能直接投到“马”然后抓住classcastexception吗

你能解释一下为什么你需要传入类名而不是类吗

也许您也可以使用方法重载,但我必须对此进行测试,因为我不完全确定在这种情况下优先级是什么。

当您说:

(final Set xSet<Horse>, final String clsName){
...}
您告诉编译器希望它检查对exam()的所有调用,并确保每个调用都提供一个Horse对象作为参数。但是,在callHorse()中,您使用动态强制转换参数调用exam(),编译器无法检查该参数

您可以通过使用反射和动态调用exam()方法来解决此问题。

当您说:

(final Set xSet<Horse>, final String clsName){
...}
您告诉编译器希望它检查对exam()的所有调用,并确保每个调用都提供一个Horse对象作为参数。但是,在callHorse()中,您使用动态强制转换参数调用exam(),编译器无法检查该参数


您可以通过使用反射和动态调用exam()方法来解决这个问题。

如果您使用
Class.cast()
和传递给另一个函数的参数来执行动态强制转换,那么在编译时,您传递的类型是未知的。这就是为什么不能使用
Horse
作为定义方法的参数类型,而是以您自己的方式使用反射调用方法。您的cast除了验证(只要您没有得到
异常
)之外几乎没有什么作用,您传入的集合完全由您以其名称传入的
类的成员组成

请注意,
Class.cast()
方法是在Java5中引入的,这意味着如果您可以访问
Class.cast()
,就可以访问泛型。泛型可以帮助清理问题,尽管它们不能解决您试图解决的问题

使用Java 5
for
循环,您可以按如下方式重写循环:

exam(Horse hrr)
检查(对象)
方法
import java.lang.reflect.*;

public class Test {

public static void exam( Object o ) {
  System.out.println( "Object version called" );
}


public static void exam( Test t ) {
  System.out.println( "Test version called" );
}

public static void main (String[] args) {

try {

  // Create an instance of Test but reference it as an Object

  Object untypedTest = new Test();

  // Calling exam directly will invoke the Object version

  exam( untypedTest );

  // But if we use reflection to select the version of exam
  // that takes the desired class name, we can invoke it without
  // even explicitly casting

  String className = "Test";

  Class[] examMethodParams = { Class.forName( className ) };

  Method examMethod = Test.class.getMethod( "exam", examMethodParams  );

  Object[] actualParams = { untypedTest };

  examMethod.invoke( null, actualParams );

} catch (Exception e) {
  e.printStackTrace();
}

}

}
if (obj instanceof Cust)
{
    Cust c = (Cust) obj;
    Set cxSet = c.getCustPhonSet();
    CustPhon cx;
    if (cxSet != null && cxSet.size() > 0)
    {
        Iterator cxSetIterator = cxSet.iterator();
        while (cxSetIterator.hasNext())
        {
            cx = (CustPhon) cxSetIterator.next();
            this.stringProp(cx);
        }
    }
    //....pattern continues here... CustPhon is replaced by various classes like CustNam etc... Also getCustPhonSet by getCustNamSet etc...
}
public void dynamicIteration(Set xlSet, String clsName)
{
    if (xSet != null && xSet.size() > 0)
    {
        try{
            Class clsinstance = Class.forName(clsName);
            Iterator itr = generalSet.iterator();
            while(itr.hasNext())
            {
                this.stringProp(clsinstance.cast(itr.next()));// See this is wrong.. thats y i posted here by using a simple Horse example
            }
        }catch(ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }
}
//process customer email address
Set cxSet = c.getCustPhonSet();
className = "pkg.CustPhon";
dynamicIteration(cxSet,className);
// Similarly for other patterns
public class Test {
  public void test(Object obj) {
    if (obj instanceof Horse) {
      Horse c = (Horse) obj;
      noise(c);
    }
    if (obj instanceof Cow) {
      Cow c = (Cow) obj;
      noise(c);
    }
  }

  public void noise(Horse h) {
    System.out.println("Neigh");
  }

  public void noise(Cow c) {
    System.out.println("Moo");
  }

  public static void main(String[] args) {
    Object o1 = new Horse();
    Object o2 = new Cow();
    Test tester = new Test();
    tester.test(o1);
    tester.test(o2);
  }
}

class Horse {}

class Cow {}
    if (obj instanceof Horse) {
      Horse c = (Horse) obj;
      noise(c);
    }
    if (obj instanceof Horse) {
      handleNoise(obj, Horse.class);
    }
void handleNoise(Object obj, Class clazz) {
  noise(clazz.cast(obj));
}
public class Test {
  public void test(Animal obj) {
    obj.noise();
  }

  public static void main(String[] args) {
    Animal o1 = new Horse();
    Animal o2 = new Cow();
    Test tester = new Test();
    tester.test(o1);
    tester.test(o2);
  }
}

interface Animal {
  void noise();
}

class Horse implements Animal {
  public void noise() {
    System.out.println("Neigh");
  }
}

class Cow implements Animal {
  public void noise() {
    System.out.println("Moo");
  }
}
if (obj instanceof Cust) {
  loopOverSet(c.getCustPhonSet());
} else if (obj instanceof Name) {
  loopOverSet(c.getCustNameSet());
}
// and so on for the rest...
void loopOVerSet(Set cxSet) {
  if (cxSet != null && cxSet.size() > 0) {
    Iterator cxSetIterator = cxSet.iterator();
    while (cxSetIterator.hasNext())
    {
      ((StringProp)cxSetIterator.next()).stringProp();
    }
  }
}