Java 当类名为字符串时强制转换为未知类型
这里,exam函数的参数是一个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
对象
。但我想让论点是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 5for
循环,您可以按如下方式重写循环:
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();
}
}
}