【问题标题】:How to call a method from a Java generic object?如何从 Java 通用对象调用方法?
【发布时间】:2022-11-30 16:07:41
【问题描述】:

我有来自不同类的一些项目,我想编写一个采用通用对象的方法(目的是所有其他类的超类)

  • 验证项目都有 getId() 方法
  • 然后收集 getId() 值。

请注意,对象实际上可以是任何东西——它不能被限制

我试过类似的东西

  String getObjectId(Object item) throws Exception {
    // If the getId() method is not implemented, throw exception
    if (Arrays.stream(item.getClass().getMethods())
        .filter(method -> "getId".equals(method.getName()))
        .findFirst()
        .isEmpty()) {
      throw new Exception(...);
    }

    return item.getId();
  }

问题是编译器忽略了这个验证——我总是得到这个错误,即使我只是验证它有方法


cannot find symbol
  return item.getId();
                ^

在这种情况下如何调用方法?

【问题讨论】:

  • 您是否检查过 Object 类是否具有“getId()”方法?您的返回语句不会通过 getClass() 和所有这些。它只是在 Object 类中寻找该方法,因为这就是声明的项目
  • 正确的方法是使用强制存在 getId() 的接口。
  • 你不能像这样在Object上调用item.getId()。如果您使用反射,则需要使用 Method.invoke(item) 来调用您找到的方法。但是反射在这里似乎不是一个好的解决方案,你不能为那些暴露getId()方法的类添加一个通用接口吗?这样一来,您可能一开始就不需要 getObjectId() 方法。
  • 我相信它不是developer.classpath.org/doc/java/lang/Object-source.html 嗯,这是一个很好的观点。也许我可以通过 Object 中存在的身份函数重命名 getId()
  • 这回答了你的问题了吗? How do I call a method of a generic type object?

标签: java generics


【解决方案1】:

当您调用item.getId();时,java 不知道您的对象的确切类型是什么,因此它不知道您的对象类型是什么。即使您之前使用反射检查过它。

  1. 如果你想从对象调用getId方法,这个sn-p可以帮助你:
    Method getIdMethod = item.getClass().getMethod("getId");
    Object result = getIdMethod.invoke(item);
    return result == null? null: result.toString();
    
    1. 如果你所有的对象都有getId()方法,你可以在不使用反射的情况下改变你的代码:
    public interface Identifiable {
       String getId();
    
       void setId(String value);
    }
    
    class A implements Identifiable {
    ...
    }
    
    class B implements Identifiable {
    
    }
    
    

    使用示例:

    Collection<? extends Identifiable> coll = new ArrayList<>();
    ...
    coll.stream().map(Identifiable::getId).collect(Collectors.toList());
    

【讨论】:

  • 如果您对此提供一些额外的解释可能会更好
【解决方案2】:

评论时间太长,所以这将是一个答案。

在您的情况下,正如其他人已经建议的那样,我会做的是使用基本类型。

假设您有以下基本类型(接口、抽象类):

IMyInterface、MyAbstractClass、IGetInfo。

package com.me;

public class MyWorker implements IGetInfo {

    public String getObjectInfo() {
        return "MyWorker";
    }    

    public String getObjectInfo(IGetInfo x) {
        return x.getObjectInfo();
    }

    
    public String getObjectInfo(IMyInterface x) {
        return x.getId();
    }

    // and so on

}

这使您的意图在代码中变得清晰。它不像某些人希望的那样干,但它确实使您的代码更易于理解,并且您可以避免在不得不处理可能具有或不具有某些预期方法/属性的对象时出现问题。

另一种解决方案是使用反射来检查对象,以确定它是否实现了给定的接口/类,然后对其进行操作,或者抛出异常。 这将允许您继续将 Object 用于您的方法,但反射会变得有些复杂并且一段时间后难以阅读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-28
    • 2016-10-11
    • 2013-09-18
    • 1970-01-01
    • 2018-04-09
    • 2010-11-24
    • 1970-01-01
    • 2014-08-17
    相关资源
    最近更新 更多