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

时间:2022-08-20 20:40:11

I am trying to wrap my mind around something in java. When I pass an object to another class' method, can I not just call any methods inherent to that object class?

我试图用java包围我的想法。当我将一个对象传递给另一个类的方法时,我不能只调用该对象类固有的任何方法吗?

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类型的原因是因为我希望能够传递各种对象类型,每种类型都有一个testing()方法。

8 个解决方案

#1


If you would like to pass in a variety of objects with testing() methods, have each object implement a Testable interface:

如果您想使用testing()方法传递各种对象,请让每个对象实现一个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. So I could have two classes whose testing() methods do different things.

编辑:为了澄清,实现一个接口意味着该类保证具有该方法,但该方法可以做任何想做的事情。所以我可以有两个类,其tests()方法做不同的事情。

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");
   }
}

#2


The problem is that myMethod can't know it's getting a b object until it actually runs. You could pass a String in, for all it knows.

问题是myMethod无法知道它在实际运行之前获取b对象。你知道,你可以传入一个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类型的原因是因为我希望能够传递各种对象类型,每种类型都有一个testing()方法。

As Amanda S and several others have said, this is a perfect case for an interface. The way to do this is to create an interface which defines the testing() method and change myMethod to take objects implementing that interface.

正如Amanda S和其他几位人士所说,这是一个完美的界面案例。这样做的方法是创建一个定义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.

另一种解决方案(没有接口)将反射性地发现对象是否具有testing()方法并调用它,但这不是推荐的,并且对于这样一个简单的情况不需要。

#3


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()方法的所有类的接口。

e.g:

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();
  }
}

#4


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. I suggest something along the lines of the following:

您的问题是支持接口的经典论据。您希望尽可能通用,但是您希望传递的每个对象都有一个testing()方法。我建议的内容如下:

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" 
  }
}

#5


Because you're passing in an Object (b inherit from Object). Object doesn't have testing, b does.

因为你传入了一个Object(b继承自Object)。对象没有测试,b确实没有。

You can either pass in b or cast the object to b before calling the method.

您可以在调用方法之前传入b或将对象强制转换为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. All objects that you pass in must implement the interface.

编辑要传入实现该方法的泛型类:您需要创建一个具有方法签名的接口,并传入接口类型而不是Object。传入的所有对象都必须实现该接口。

#6


You can only access the members that are visible for the type of reference you have to the 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中定义的成员,因此在类a中,类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实例上的测试方法。

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!!!");
    }
}

#7


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.

由于此验证是在编译期间进行的,并且对象类型没有“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中执行此操作的“OTHER”方式是反射性地调用方法,但我不确定这是否是您所需要的,因为当您以这种方式执行时代码更加抽象,但这就是自动化测试框架的方式(而且许多其他框架(如Hibernate)确实可以正常工作。

I hope this help you to clarify the reason.

我希望这能帮助你澄清原因。

#8


If you REALLY, REALLY want to keep the parameter as abstract as possible, you should consider reflection API. That way, you can pass whatever object you want and dynamically execute the method you want. You can take a look at some examples.

如果你真的,真的想让参数保持尽可能抽象,你应该考虑反射API。这样,您可以传递任何您想要的对象并动态执行您想要的方法。你可以看看一些例子。

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的帖子。

#1


If you would like to pass in a variety of objects with testing() methods, have each object implement a Testable interface:

如果您想使用testing()方法传递各种对象,请让每个对象实现一个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. So I could have two classes whose testing() methods do different things.

编辑:为了澄清,实现一个接口意味着该类保证具有该方法,但该方法可以做任何想做的事情。所以我可以有两个类,其tests()方法做不同的事情。

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");
   }
}

#2


The problem is that myMethod can't know it's getting a b object until it actually runs. You could pass a String in, for all it knows.

问题是myMethod无法知道它在实际运行之前获取b对象。你知道,你可以传入一个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类型的原因是因为我希望能够传递各种对象类型,每种类型都有一个testing()方法。

As Amanda S and several others have said, this is a perfect case for an interface. The way to do this is to create an interface which defines the testing() method and change myMethod to take objects implementing that interface.

正如Amanda S和其他几位人士所说,这是一个完美的界面案例。这样做的方法是创建一个定义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.

另一种解决方案(没有接口)将反射性地发现对象是否具有testing()方法并调用它,但这不是推荐的,并且对于这样一个简单的情况不需要。

#3


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()方法的所有类的接口。

e.g:

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();
  }
}

#4


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. I suggest something along the lines of the following:

您的问题是支持接口的经典论据。您希望尽可能通用,但是您希望传递的每个对象都有一个testing()方法。我建议的内容如下:

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" 
  }
}

#5


Because you're passing in an Object (b inherit from Object). Object doesn't have testing, b does.

因为你传入了一个Object(b继承自Object)。对象没有测试,b确实没有。

You can either pass in b or cast the object to b before calling the method.

您可以在调用方法之前传入b或将对象强制转换为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. All objects that you pass in must implement the interface.

编辑要传入实现该方法的泛型类:您需要创建一个具有方法签名的接口,并传入接口类型而不是Object。传入的所有对象都必须实现该接口。

#6


You can only access the members that are visible for the type of reference you have to the 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中定义的成员,因此在类a中,类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实例上的测试方法。

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!!!");
    }
}

#7


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.

由于此验证是在编译期间进行的,并且对象类型没有“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中执行此操作的“OTHER”方式是反射性地调用方法,但我不确定这是否是您所需要的,因为当您以这种方式执行时代码更加抽象,但这就是自动化测试框架的方式(而且许多其他框架(如Hibernate)确实可以正常工作。

I hope this help you to clarify the reason.

我希望这能帮助你澄清原因。

#8


If you REALLY, REALLY want to keep the parameter as abstract as possible, you should consider reflection API. That way, you can pass whatever object you want and dynamically execute the method you want. You can take a look at some examples.

如果你真的,真的想让参数保持尽可能抽象,你应该考虑反射API。这样,您可以传递任何您想要的对象并动态执行您想要的方法。你可以看看一些例子。

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的帖子。