java编译器错误中的动态强制转换
我有3个类A、B和C。它们唯一的共同点是一个getName()函数,其他什么都没有 我有一个Class类型的数组,它存储上述类java编译器错误中的动态强制转换,java,casting,Java,Casting,我有3个类A、B和C。它们唯一的共同点是一个getName()函数,其他什么都没有 我有一个Class类型的数组,它存储上述类 Class[] classes = {A.class,B.class,C.class}; 然后我有一个包含类型a、B和C的对象的列表 List<?> list = new ArrayList<?>(); list.add(new A()); list.add(new B()); list.add(new C()); List List=new
Class[] classes = {A.class,B.class,C.class};
然后我有一个包含类型a、B和C的对象的列表
List<?> list = new ArrayList<?>();
list.add(new A());
list.add(new B());
list.add(new C());
List List=new ArrayList();
添加(新的A());
添加(新的B());
添加(新的C());
我想通过循环访问列表中的对象。我还想访问对象A、B和C的方法。因此,我尝试使用类数组强制转换它们
for(int i = 0; i < classes.length;i++)
{
classes[i].cast(list.get(i)).getName(); //A,B,and C have method getName() in common
}
for(int i=0;i
这给了我一个编译器错误:“没有为类型对象定义getName()方法
编译器是否有办法在运行时之前忽略这种类型的强制转换(我确信它在运行时会起作用)?或者是否有另一种解决方案可以满足我的期望(我正在寻找一种不涉及更改类a、B和C的代码的解决方案)您应该使用方法
getName()实现一个接口
,我们称之为可命名的:
public interface Nameable {
public String getName();
}
然后让这三个类A
B
和C
实现Nameable
。这将允许您将列表声明为列表
,并且在访问其元素时无需强制转换来调用此方法
编辑:好的,因为你不能修改这些类,你可以做一些类似于@JB niset建议的事情。但是,不要在循环中动态查找方法,因为这是昂贵的。静态地为每个类查找这些方法一次,并将它们保存在一个映射中,其中键是类
:
private static final Map<Class<?>, Method> getNameMap = new HashMap<Class<?>, Method>();
static {
try {
getNameMap.put(A.class, A.class.getMethod("getName"));
getNameMap.put(B.class, B.class.getMethod("getName"));
getNameMap.put(C.class, B.class.getMethod("getName"));
}
catch (NoSuchMethodException nsme) {
//handle method not being found
}
}
私有静态最终映射,方法>();
静止的{
试一试{
getNameMap.put(A.class,A.class.getMethod(“getName”));
getNameMap.put(B.class,B.class.getMethod(“getName”);
getNameMap.put(C.class,B.class.getMethod(“getName”);
}
捕获(NoSuchMethodException nsme){
//找不到句柄方法
}
}
然后从循环中查找方法:
for (Object obj : list) {
try {
Class<?> objClass = obj.getClass();
Object returned = getNameMap.get(objClass).invoke(obj);
String name = (String)returned; //I'm just assuming these methods return a String that you want to use for something
}
catch (IllegalAccessException iae) {
//handle method not being accessable
}
catch (InvocationTargetException ite) {
Throwable cause = ite.getCause();
//handle cause exception
}
}
用于(对象对象对象:列表){
试一试{
类objClass=obj.getClass();
返回的对象=getNameMap.get(objClass.invoke)(obj);
String name=(String)returned;//我只是假设这些方法返回一个您想要用于某些内容的字符串
}
捕获(IllegalacessException iae){
//句柄方法不可访问
}
捕获(调用targetException ite){
可丢弃原因=ite.getCause();
//处理原因异常
}
}
您应该使用方法getName()
实现一个接口,我们称之为Nameable
:
public interface Nameable {
public String getName();
}
然后让这三个类A
B
和C
实现Nameable
。这将允许您将列表声明为列表
,并且在访问其元素时无需强制转换来调用此方法
编辑:好的,因为你不能修改这些类,你可以做一些类似于@JB niset建议的事情。但是,不要在循环中动态查找方法,因为这是昂贵的。静态地为每个类查找这些方法一次,并将它们保存在一个映射中,其中键是类
:
private static final Map<Class<?>, Method> getNameMap = new HashMap<Class<?>, Method>();
static {
try {
getNameMap.put(A.class, A.class.getMethod("getName"));
getNameMap.put(B.class, B.class.getMethod("getName"));
getNameMap.put(C.class, B.class.getMethod("getName"));
}
catch (NoSuchMethodException nsme) {
//handle method not being found
}
}
私有静态最终映射,方法>();
静止的{
试一试{
getNameMap.put(A.class,A.class.getMethod(“getName”));
getNameMap.put(B.class,B.class.getMethod(“getName”);
getNameMap.put(C.class,B.class.getMethod(“getName”);
}
捕获(NoSuchMethodException nsme){
//找不到句柄方法
}
}
然后从循环中查找方法:
for (Object obj : list) {
try {
Class<?> objClass = obj.getClass();
Object returned = getNameMap.get(objClass).invoke(obj);
String name = (String)returned; //I'm just assuming these methods return a String that you want to use for something
}
catch (IllegalAccessException iae) {
//handle method not being accessable
}
catch (InvocationTargetException ite) {
Throwable cause = ite.getCause();
//handle cause exception
}
}
用于(对象对象对象:列表){
试一试{
类objClass=obj.getClass();
返回的对象=getNameMap.get(objClass.invoke)(obj);
String name=(String)returned;//我只是假设这些方法返回一个您想要用于某些内容的字符串
}
捕获(IllegalacessException iae){
//句柄方法不可访问
}
捕获(调用targetException ite){
可丢弃原因=ite.getCause();
//处理原因异常
}
}
您不需要强制转换:一个A
实例就是一个A
实例,强制转换不会改变它的类型。因为您在编译时不知道元素的类型是什么,所以强制转换对您没有帮助
您必须做的是通过反射调用getName
方法:
Class<?> clazz = list.get(i).getClass();
Method m = clazz.getMethod("getName");
m.invoke(list.get(i));
Class clazz=list.get(i).getClass();
方法m=clazz.getMethod(“getName”);
m、 调用(list.get(i));
您不需要强制转换:一个A
实例就是一个A
实例,强制转换不会改变它的类型。因为您在编译时不知道元素的类型是什么,所以强制转换对您没有帮助
您必须做的是通过反射调用getName
方法:
Class<?> clazz = list.get(i).getClass();
Method m = clazz.getMethod("getName");
m.invoke(list.get(i));
Class clazz=list.get(i).getClass();
方法m=clazz.getMethod(“getName”);
m、 调用(list.get(i));
因为编译器无法检查该列表中的对象是否有相应的getName()
方法。如果该列表中有一个类为D的对象,该怎么办?解决方案是使用方法定义一个接口getName()
import java.util.ArrayList;
导入java.util.List;
公共类接口示例{
接口I{
字符串getName();
}
静态类A实现了I{
...
}
静态类B实现了I{
...
}
静态类C实现了I{
...
}
公共静态void main(字符串[]args){
列表=新的ArrayList();
添加(新的A());
添加(新的B());
添加(新的C());
(I:列表){
i、 getName();
}
}
}
因为编译器无法检查该列表中的对象是否具有相应的ge
for(int i = 0; i < list.length;i++)
{
final Object obj = list.get(i);
final Method m = obj.getClass.getMethod("getName"); //A,B,and C have method getName() in common
m.invoke(obj);
// Exception-handling code omitted
}
public static void main(String[] args)
{
A aObject;
B bObject;
C cObject;
List list = new ArrayList();
list.add(new A());
list.add(new B());
list.add(new C());
list.add(new String());
for (Object current : list)
{
if (current instanceof A)
{
aObject = (A)current;
System.out.println(aObject.getName());
}
else if (current instanceof B)
{
bObject = (B)current;
System.out.println(bObject.getName());
}
else if (current instanceof C)
{
cObject = (C)current;
System.out.println(cObject.getName());
}
else
{
System.out.print("Unexpected class: ");
System.out.println(current.getClass());
}
}
}
public static void main(String[] args)
{
List list = new ArrayList();
Method getNameMethod;
list.add(new A());
list.add(new B());
list.add(new C());
list.add(new String());
for (Object current : list)
{
// getNameMethod = MethodUtils.getAccessibleMethod(current.getClass(), "getName", (Class[])null);
try
{
getNameMethod = current.getClass().getMethod("getName");
}
catch (SecurityException exception1)
{
getNameMethod = null;
}
catch (NoSuchMethodException exception1)
{
getNameMethod = null;
}
if (getNameMethod != null)
{
try
{
System.out.println(getNameMethod.invoke(current, (Object[])null));
}
catch (IllegalArgumentException exception)
{
// TODO Implement this catch block.
}
catch (IllegalAccessException exception)
{
// TODO Implement this catch block.
}
catch (InvocationTargetException exception)
{
// TODO Implement this catch block.
}
}
else
{
System.out.print("Unexpected class: ");
System.out.println(current.getClass());
}
}
}
static String executeGetName(Object o) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Method method = o.getClass().getMethod("getName");
return (String) method.invoke(o);
}