简体   繁体   English

为什么java找不到我的方法?

[英]Why can't java find my method?

I am trying to wrap my mind around something in java.我正试图围绕 java 中的一些东西。 When I pass an object to another class' method, can I not just call any methods inherent to that object class?当我将 object 传递给另一个类的方法时,我不能只调用 object class 固有的任何方法吗?

What is the reason code such as the example below does not compile?如下示例代码无法编译的原因是什么?

Thank you,谢谢,

class a {
  public static void myMethod(Object myObj) {
    myObj.testing();
  }
}


class b {
  public void testing() {
    System.out.println ("TESTING!!!");
  }
}


class c {  
  public static void main (String[] args) {
    b myB = new b();    
    a.myMethod(myB);  
  }
}

Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.编辑:我将 myMethod 中的参数保留为 Object 类型的原因是因为我希望能够传入各种 object 类型,每个类型都有一个 testing() 方法。

If you would like to pass in a variety of objects with testing() methods, have each object implement a Testable interface:如果你想通过testing()方法传入各种对象,让每个 object 实现一个Testable接口:

public interface Testable
{
   public void testing()
}

Then have myMethod() take a Testable .然后让myMethod()拿一个Testable

public static void myMethod(Testable testable)
{
  testable.testing();
}

Edit: To clarify, implementing an interface means that the class is guaranteed to have the method, but the method can do whatever it wants.编辑:为了澄清,实现一个接口意味着 class 保证拥有该方法,但该方法可以为所欲为。 So I could have two classes whose testing() methods do different things.所以我可以有两个类,它们的testing()方法做不同的事情。

public class AClass implements Testable
{
   public void testing()
   {
      System.out.println("Hello world");
   }
}

public class BClass implements Testable
{
   public void testing()
   {
      System.out.println("Hello underworld");
   }
}

The problem is that myMethod can't know it's getting a b object until it actually runs.问题是myMethod在实际运行之前无法知道它得到了 a b object。 You could pass a String in, for all it knows.你可以传入一个String ,因为它知道。

Change it to将其更改为

public static void myMethod(b myObj) {
  myObj.testing();
}

and it should work.它应该可以工作。


Update of the question:问题更新:

Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.编辑:我将 myMethod 中的参数保留为 Object 类型的原因是因为我希望能够传入各种 object 类型,每个类型都有一个 testing() 方法。

As Amanda S and several others have said, this is a perfect case for an interface.正如 Amanda S 和其他几个人所说,这是一个完美的界面案例。 The way to do this is to create an interface which defines the testing() method and change myMethod to take objects implementing that interface.这样做的方法是创建一个定义testing()方法的接口并更改myMethod以获取实现该接口的对象。

An alternative solution (without interfaces) would be to reflectively discover if the object has a testing() method and call it, but this is not recommended and not needed for a such a simple case.另一种解决方案(无接口)是反思性地发现 object 是否具有testing()方法并调用它,但对于这样一个简单的情况,不建议这样做,也不需要这样做。

What you are talking about is duck typing.你在说的是鸭子打字。 Java doesn't have duck typing. Java 没有鸭子类型。

Therefore you need to define an interface that all the classes with a testing() method implement.因此,您需要定义一个所有具有testing()方法的类都实现的接口。

eg:例如:

public interface Testable
{
   public void testing()
}

class B implements Testable 
{
  public void testing() {
    System.out.println ("TESTING!!!");
  }
}

class A {
  public static void myMethod(Testable myObj) {
    myObj.testing();
  }
}

Your issue is a classic argument in favor of an interface.您的问题是支持接口的经典论点。 You want as generic as possible, yet you want every object you pass to have a testing() method.您希望尽可能通用,但您希望通过的每个 object 都有一个 testing() 方法。 I suggest something along the lines of the following:我建议以下内容:

public interface Testable
{
  public void testing();
}

public class A
{
  public static void myMethod(Testable myObj)
  {    
    myObj.testing();
  }
}

public class B implements Testable
{
  public void testing()
  {
    System.out.println("This is class B");
  }
}

public class C implements Testable
{
  public void testing()
  {
    System.out.println("This is class C");
  }
}

public class Test
{  
  public static void main (String[] args) 
  {
    B myB = new B();
    C myC = new C();
    A.myMethod(myB); // "This is class B"
    A.myMethod(myC); // "This is class C" 
  }
}

Because you're passing in an Object (b inherit from Object).因为您传入的是 Object(b 继承自 Object)。 Object doesn't have testing, b does. Object 没有测试,b 有。

You can either pass in b or cast the object to b before calling the method.在调用该方法之前,您可以传入 b 或将 object 转换为 b。

EDIT To pass in a generic class that implements that method: you'll want to make an interface that has the method signature and pass in the interface type instead of Object.编辑要传入实现该方法的通用 class:您需要创建一个具有方法签名的接口并传入接口类型而不是 Object。 All objects that you pass in must implement the interface.您传入的所有对象都必须实现该接口。

You can only access the members that are visible for the type of reference you have to the object.您只能访问对 object 的引用类型可见的成员。

In the case of myMethod(Object myObj) that means only the members defined in Object, so in class a the members of class b will not be visible.myMethod(Object myObj)的情况下,这意味着只有 Object 中定义的成员,因此在class aclass b的成员将不可见。

If you changed the definition of a.myMethod to be public static void myMethod(b myObj) you would then be able to see the testing method on the instance of b while in myMethod .如果您将a.myMethod的定义更改为public static void myMethod(b myObj)您将能够在myMethod中看到b实例上的testing方法。

update based on clarification:根据澄清更新:

In that case defining an interface for all of them to implement is likely what you want.在这种情况下,为所有这些定义一个接口来实现可能是您想要的。

public interface Testable {
    public void testing();
}

public class a {
    public static void myMethod(Testable myObj) {
        myObj.testing();
    }
}

public class b implements Testable {
    public void testing () {
        System.out.println("TESTING!!!");
    }
}

Why can't java find my method?为什么java找不到我的方法?

Because of the way Java was designed.由于 Java 的设计方式。

Java is "statically typed" that means objects types are checked during compilation. Java 是“静态类型的” ,这意味着编译期间检查对象类型。

In Java you can invoke a method only if that method belongs to that type.在 Java 中,只有当该方法属于该类型时,您才能调用该方法。

Since this verification is made during compilation and the Object type does not have the "testing()" method, the compilation fails ( even though if at runtime the objects do have that method". This is primarily for safety.由于此验证是在编译期间进行的,并且 Object 类型没有“testing()”方法,因此编译失败(即使在运行时对象确实具有该方法)。这主要是为了安全。

The workaround as described by others will require you to create a new type, where you can tell the compiler其他人描述的解决方法将要求您创建一个新类型,您可以在其中告诉编译器

"Hey, the instances of this type will respond the the testing method" “嘿,这种类型的实例响应测试方法”

If you want to pass a variety of objects and keep it very generic, one way is having those objects to implement and interface.如果您想传递各种对象并保持其非常通用,一种方法是让这些对象实现和接口。

public interface Testable { 
    public void testing();
}

class A implements Testable { // here this class commits to respond to "testing" message 
    public void testing() {
    }
}

class B implements Testable { // B "is" testable 
    public void testing() { 
        System.out.println("Testing from b");
    } 
}


class C implements Testable { // C is... etc. 
    public void testing() { 
        //.... 
    }
}

Later somewhere else后来在别的地方

public void doTest( Testable object ) { 
    object.testing();
}

doTest( new A() );
doTest( new B() );
doTest( new C() );

The "OTHER" way to do this, in java is invoking the methods reflectively , but I'm not sure if that's what you need, for the code is much more abstract when you do it that way, but that's how automated testing frameworks (and a lot of other frameworks such as Hibernate) do actually work.在 java 中执行此操作的“其他”方式正在反射地调用方法,但我不确定这是否是您需要的,因为当您这样做时代码更加抽象,但这就是自动化测试框架的方式(和许多其他框架(例如 Hibernate)确实有效。

I hope this help you to clarify the reason.我希望这可以帮助您澄清原因。

If you REALLY, REALLY want to keep the parameter as abstract as possible, you should consider reflection API.如果你真的,真的想尽可能地保持参数抽象,你应该考虑反射 API。 That way, you can pass whatever object you want and dynamically execute the method you want.这样,您可以传递您想要的任何 object 并动态执行您想要的方法。 You can take a look at some examples .你可以看看一些例子

It's not the only way, but it might be a valid alternative depending on your problem.这不是唯一的方法,但根据您的问题,它可能是一种有效的替代方法。

Keep in mind that reflection is way slower than calling your methods directly.请记住,反射比直接调用您的方法要慢得多。 You might consider using an interface as well, such as the one on Amanda's post.您也可以考虑使用界面,例如 Amanda 帖子中的界面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM